2017-08-29 65 views
0

我具有低于输入,我要更新的<orderitem><name><price> = Desktop与另一个<orderitem>(存在于XML的任意位置)的<price>其具有<associationid>相同值作为其<objectid>XSLT修改基于条件以xml

在这里例如,我有<associationid>作为为2,现在我寻找<objectid>与价值为2,并得到它的价格,并在这里更新它。下面的示例输出。

请让我知道解决涉及遍历的这些问题的方法,我是XSL新手,尝试引用XSLT烹饪书和SO,但没有得到适当的参考。谢谢。

<listoforders> 
    <Orderitem> 
     <name>Desktop</name> 
     <place>NZ</place> 
     <price>120ass</price> 
     <associationid>2</associationid> 
     <Orderitem> 
      <name>Desktop2</name> 
      <place>NZ</place> 
      <price>130</price> 
     </Orderitem> 
     <Orderitem> 
      <name>Desktop3</name> 
      <place>NZ</place> 
      <price>130obj1</price> 
      <objectid>1</objectid> 
      <price>130</price> 
     </Orderitem> 
    </Orderitem> 
    <Orderitem> 
     <name>laptop</name> 
     <place>NZ</place> 
     <price>120</price> 
     <Orderitem> 
      <name>laptop2</name> 
      <place>NZ</place> 
      <price>130</price> 
     </Orderitem> 
     <Orderitem> 
      <name>laptop3</name> 
      <place>NZ</place> 
      <price>130obj2</price> 
      <objectid>2</objectid> 
     </Orderitem> 
    </Orderitem> 
</listoforders> 

输出

<listoforders> 
    <Orderitem> 
     <name>Desktop</name> 
     <place>NZ</place> 
     <price>130obj2</price> 
     <associationid>2</associationid> 
     <Orderitem> 
      <name>Desktop2</name> 
      <place>NZ</place> 
      <price>130</price> 
     </Orderitem> 
     <Orderitem> 
      <name>Desktop3</name> 
      <place>NZ</place> 
      <price>130obj1</price> 
      <objectid>1</objectid> 
      <price>130</price> 
     </Orderitem> 
    </Orderitem> 
    <Orderitem> 
     <name>laptop</name> 
     <place>NZ</place> 
     <price>120</price> 
     <Orderitem> 
      <name>laptop2</name> 
      <place>NZ</place> 
      <price>130</price> 
     </Orderitem> 
     <Orderitem> 
      <name>laptop3</name> 
      <place>NZ</place> 
      <price>130obj2</price> 
      <objectid>2</objectid> 
     </Orderitem> 
    </Orderitem> 
</listoforders> 

XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" 
     indent="yes" /> 
    <xsl:strip-space elements="*" /> 

    <!-- identity transform --> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()" /> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="price[../name='Desktop']"> 
     <xsl:copy-of select="price[//objectid=.//associationid]" /> 
    </xsl:template> 
</xsl:stylesheet> 

回答

1

它总是最好使用key来解决交叉引用:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="ord" match="Orderitem" use="objectid" /> 

<!-- identity transform --> 
<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="price[../name='Desktop']"> 
    <xsl:copy-of select="key('ord', ../associationid)/price"/>   
</xsl:template> 

</xsl:stylesheet> 
+0

和的区别是什么 – Rupesh

+0

其短,更简单 - 我已经写它,你发布你的面前。 –

0

您可以使用键此:

<?xml version="1.0" encoding="UTF-8"?> 
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     version="2.0"> 
     <xsl:output indent="yes"/> 

     <xsl:key name="keyitem" match="price" use="../objectid"/> 

     <!-- Identity Transformation --> 
     <xsl:template match="node()|@*"> 
      <xsl:copy> 
       <xsl:apply-templates select="node()|@*"></xsl:apply-templates> 
      </xsl:copy> 
     </xsl:template> 

     <xsl:template match="price[../name eq 'Desktop'][../associationid]"> 
      <xsl:variable name="id" select="../associationid"/> 
      <xsl:copy> 
      <xsl:value-of select="key('keyitem',$id)"/> 
      </xsl:copy> 
     </xsl:template> 
    </xsl:stylesheet> 
+0

感谢您的输入@Rupesh – Krish

0

我注意到在您的XSLT三两件事:

  1. xsl:copy-of,您目前没有通过所有的价格一样穿越你打算,因为你需要使用//price
  2. 在这种情况下,您要测试属于价格的元素objectid,因此您应该使用../objectid而不是//objectid
  3. 因此,在您隐式“离开”桌面价格元素的上下文的情况下,您不再可以直接访问.//associationid。然而,可以使用current()功能来指代对象(感谢michael-hor257k

这XSLT产生所需的输出:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 
    <!-- identity transform --> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="price[../name='Desktop']"> 
     <xsl:copy-of select="//price[../objectid=current()/../associationid]"/>   
    </xsl:template> 
</xsl:stylesheet> 

另一种可能性是使用一个变量来存储的ID为稍后比较。

<xsl:template match="price[../name='Desktop']"> 
    <xsl:variable name="var.associationid" select="../associationid"/> 
    <xsl:copy-of select="//price[../objectid=$var.associationid]"/>   
</xsl:template> 
+1

这是'current()'函数的用途。尽管如此,使用密钥既优雅又高效。 –

+0

感谢您的输入@everdream – Krish