我有以下输入,我必须用<name>
=Desktop
更新<orderitem>
的<price>
,用另一个<orderitem>
(存在于xml中的任何位置)的<price>
更新,该的值与其<objectid>
具有相同的<associationid>
值。
例如,在这里,我<associationid>
为 2 表示Desktop
,现在我寻找值为 2 的<objectid>
并获取其价格并在此处更新。示例输出如下。
请让我知道解决涉及遍历的此类问题的方法,我是 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>
最好使用键来解析交叉引用:
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>
你可以使用key:
<?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>
我注意到您的 XSLT 中有三件事:
- 在
xsl:copy-of
,您目前没有像预期的那样遍历所有价格,为此您需要使用//price
. - 在这种情况下,您要测试属于价格的元素
objectid
,因此您应该使用../objectid
而不是//objectid
。
因此,在这种情况下,您 - 隐式"离开"桌面价格元素的上下文,因此您不再可以直接访问
.//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>