这是我的xml
<element1> <subel1/> </element1> <element2> <subel2/> </element2> <element3> <subel3/> </element3> <criteria> <subel3/> </criteria>
我如何选择xsl不属于条件子节点的所有节点? 喜欢这些
<subel1/> <subel2/>
这是怎么做到的?
如果xml格式为:
<element1>
<el> subel1 </el>
</element1>
<element2>
<el> subel2
</el>
</element2>
<element3>
<el> subel3 </el>
</element3>
<criteria>
<subel3/>
</criteria>
答案 0 :(得分:6)
此转化:
<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:for-each select=
"/*/*[not(self::criteria)]/*">
<xsl:copy-of select=
"self::node()[not(/*/criteria/*[name()=name(current())])]"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
应用于此XML文档(基于提供的XML片段,但将XML片段包含在顶部元素中,并将另外一个子元素添加到criteria
以使问题变得不那么简单) :
<t>
<element1>
<subel1/>
</element1>
<element2>
<subel2/>
</element2>
<element3>
<subel3/>
</element3>
<criteria>
<subel3/>
<subel1/>
</criteria>
</t>
产生想要的结果(在撰写时没有其他公布的答案会产生正确的结果):
<subel2/>
分步说明:
XPath表达式:
/*/*[not(self::criteria)]/*
选择其父元素是未命名为"criteria"
的元素的每个元素,并且该元素是文档顶部元素的子元素。
<xsl:for-each>
指令中,我们检查当前节点的名称是否不是criteria
的任何子项的名称之一,并且只复制这样的节点: self::node()[not(/*/criteria/*[name()=name(current())])]
仅当不存在self::node()
的子节点时,此XPath表达式才会选择当前节点(/*/criteria
),其子节点的名称与当前节点的名称相同({{1} })。
我们仅在节点集not(/*/criteria/*[name()=name(current())])
为空时使用not(someNode-Set)
为false()
的事实。
答案 1 :(得分:2)
最简单的方法是构造一个xpath表达式,它对条件节点进行交叉检查。例如:
步骤1:以下将选择不在标准区域中的所有节点(因此所有没有父级的节点都标记为“条件”)
//*[name(..) != 'criteria']
步骤2:过滤掉也出现在critera部分
中的所有节点//*[name(..) != 'criteria' and not(name(//criteria/*) = name(.))]
现在最后一条语句将选择与条件节点不匹配的所有节点。但是你只想要子节点,所以我们可以修改选择器只抓取“子元素”元素或没有子节点的叶子元素。
//*[name(..) != 'criteria' and not(name(//criteria/*) = name(.)) and not(*)]
所以这是我们每个条件的细分再次出现:
name(..)!='criteria' - 对不在条件部分的节点的限制
not(name(// criteria / *)= name(。)) - 对与标准部分中的节点名称不同的节点的限制
而不是(*) - 限制没有任何子节点的节点(所以你想要的叶子节点。)
所以,如果你做了类似的事情:
<xsl:for-each select="//*[name(..) != 'criteria' and not(name(//criteria/*) = name(.)) and not(*)]">
<xsl:value-of select="name(current())"/> :
</xsl:for-each>
对于上面的示例,这将打印:
subel1 : subel2
希望这有帮助。
干杯,
凯西
答案 2 :(得分:1)