我想要一个表达式来选择 div 下的所有节点,但那些不是a
. 树结构必须保持不变。
使用:
/div/descendant::node()[not(self::a)]
div
这将选择(后代)不是的顶部元素的任何后代a
。
基于 XSLT 的验证:
<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="/div/descendant::node()[not(self::a)]">
<xsl:value-of select="concat('
', position(), '. "')"/>
<xsl:copy-of select="."/>"
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<div>
<span>
<a>lala</a>
</span>
</div>
评估 XPath 表达式,并以适当的格式输出所有选定的节点,以使它们清晰可见:
1. "
"
2. "<span>
<a>lala</a>
</span>"
3. "
"
4. "lala"
5. "
"
6. "
"
正如我们所见,选择了 6 个节点——一个span
元素、四个纯空白文本节点和一个非纯空白文本节点——它们都不是a
.
更新:
在评论中,OP 澄清说他实际上希望将 XML 文档转换为另一个,其中a
a 的任何后代都div
被省略。
这是一种这样的转变:
<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="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div//a"/>
</xsl:stylesheet>
当将此转换应用于同一个 XML 文档(上图)时,会产生(我猜是)想要的结果:
<div>
<span/>
</div>
如果我们只想产生任何div
具有后代的a
后代,那么我们需要几乎相同的转换:
<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="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div[.//a]"><xsl:apply-templates/></xsl:template>
<xsl:template match="div//a"/>
</xsl:stylesheet>
应用到与上述相同的 XML 文档的结果是:
<span/>