所有
我是XSLT的新手,面临着一个典型的问题。以下是问题详情
根据以下数据,我只需要在ANAME BBC而不是ItemB / tempBNum的一部分时显示ItemA / ANum元素
所以下面数据的结果应该是0214,BBC,因为它的部分是ItemA,也是BBC没有出现在ItemB中。
<myData>
<ItemA>
<ANum>0213</ANum>
<AName>OOC</AName>
</ItemA>
<ItemA>
<ANum>0031</ANum>
<AName>BBC</AName>
</ItemA>
<ItemA>
<ANum>0214</ANum>
<AName>BBC</AName>
</ItemA>
<ItemA>
<ANum>0044</ANum>
<AName>BBC</AName>
</ItemA>
<ItemB>
<tempBNum>0031</tempBNum>
</ItemB>
<ItemB>
<tempBNum>0044</tempBNum>
</ItemB>
</myData>
为此,我尝试使用嵌套For循环的逻辑,只有当ItemAObj / ANum = tempBNum时,嵌套循环的问题才会中断,但它不会破坏并产生重复的结果。
<xsl:for-each select="myData/ItemA">
<xsl:variable name="ItemAObj" select="." />
Num = <xsl:value-of select="$ItemAObj/ANum"/>
<xsl:for-each select="/myData/ItemB">
<xsl:choose>
<xsl:when test="$ItemAObj/ANum!=tempBNum and $ItemAObj/AName='BBC'"> <xsl:value-of select="tempBNum"/>
<xsl:text> </xsl:text>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
对此的任何帮助将不胜感激。
答案 0 :(得分:0)
您无法休息,但添加了条件以确保没有previous-sibling
ItemAObj/ANum = tempBNum
答案 1 :(得分:0)
这可以通过不同的方式实现,需要 for-each 迭代项目并在轮流上进行检查。相反,您可以使用键来查找数字是否存在 ItemB 元素
<xsl:key name="itemB" match="ItemB" use="tempBNum" />
然后,您可以简单地匹配 ANNA
中没有 ItemB 元素的 itemA 元素<xsl:apply-templates select="ItemA[AName='BBC'][not(key('itemB', ANum))]" />
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="itemB" match="ItemB" use="tempBNum" />
<xsl:template match="/myData">
<xsl:apply-templates select="ItemA[AName='BBC'][not(key('itemB', ANum))]" />
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML时,输出以下内容:
<ItemA>
<ANum>0214</ANum>
<AName>BBC</AName>
</ItemA>
答案 2 :(得分:0)
您无需使用任何xsl:for-each
来解决问题,更不需要嵌套 xsl:for-each
。
事实上,可以使用单个XPath表达式选择所需的ItemA
元素:
/*/ItemA[AName = 'BBC'
and
not(ANum = /*/ItemB/tempBNum)
]
因此,评估上述XPath表达式并将结果复制到输出的简单XSLT转换是:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy-of select=
"/*/ItemA[AName = 'BBC' and not(ANum = /*/ItemB/tempBNum)]"/>
</xsl:template>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<myData>
<ItemA>
<ANum>0213</ANum>
<AName>OOC</AName>
</ItemA>
<ItemA>
<ANum>0031</ANum>
<AName>BBC</AName>
</ItemA>
<ItemA>
<ANum>0214</ANum>
<AName>BBC</AName>
</ItemA>
<ItemA>
<ANum>0044</ANum>
<AName>BBC</AName>
</ItemA>
<ItemB>
<tempBNum>0031</tempBNum>
</ItemB>
<ItemB>
<tempBNum>0044</tempBNum>
</ItemB>
</myData>
产生了想要的正确结果:
<ItemA>
<ANum>0214</ANum>
<AName>BBC</AName>
</ItemA>
如果我们只想要文本节点的值,只需使用string()
函数:
string(/*/ItemA[AName = 'BBC' and not(ANum = /*/ItemB/tempBNum)])
然后是如此修改的转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select=
"string(/*/ItemA[AName = 'BBC' and not(ANum = /*/ItemB/tempBNum)])"/>
</xsl:template>
</xsl:stylesheet>
当应用于同一XML文档(上面)时,产生:
0214
BBC
注意:如果性能开始变得重要,那么使用密钥可能是提高转换效率的下一步。