我有一个必须匹配文字和标签的XPath,标签<aa>
除外;所以,
./node()[name()!='aa']
是正确的xpath。 但是对于标签aa进入节点的情况,这是不够的,我需要类似的东西,
./node()[name()!='aa' and not(.//aa)]
但是此xpath 不起作用(!)。
./*[not(self::aa or .//aa)] | ./text()
但是它丢失了节点的原始序列顺序。使用XSLT时,这个问题更加明显,例如:
<xsl:for-each select="./*[not(self::aa or .//aa)] | ./text()">
<xsl:copy-of select="."/>
<xsl:for-each>
无法按预期工作(无法确保节点的顺序)。使用./node()
时,订单始终是正确的。
PS:使用XSLT我们有一个解决方案,使用所有解释的xpath,
<xsl:for-each select="./node()[name()!='aa']">
<xsl:if test="not(.//aa)"><xsl:copy-of select="."/><xsl:if>
<xsl:for-each>
但理想/最简单的不能使用相同的结果(处理大型和复杂的输入时),
<xsl:copy-of select="*[not(self::aa or .//aa)] | ./text()"/>
答案 0 :(得分:1)
我想象你的文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<aa/>
<b>
<aa/>
</b>
<c>
<b>
<aa/>
</b>
</c>
<d/>
<e>
<b/>
</e>
</root>
然后是表达式
//node()[not(descendant-or-self::aa)]
返回所有节点(包括空白文本节点),这些节点本身不是<aa>
元素或具有<aa>
后代。 <aa>
的孩子也匹配。
您可能想要做类似
的事情<xsl:copy-of select="node()[not(descendant-or-self::aa)]"/>