我有这样的XML:
<MyXml>
<RandomNode1>
<TheNode>
<a/>
<b/>
<c/>
</TheNode>
</RandomeNode1>
<RandomNode2>
</RandomNode2>
<RandomNode3>
<RandomNode4>
<TheNode>
<a/>
<b/>
<c/>
</TheNode>
</RandomNode4>
</RandomNode3>
</MyXml>
<TheNode>
出现在整个XML中但不在同一级别,通常在其他节点内。我需要做的是消除所有出现的<TheNode>
除了第一次。其余的都是多余的,占用空间。什么是XSL可以做到这一点?
我有这样的事情:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="//TheNode[position()!=1]">
</xsl:template>
</xsl:stylesheet>
但这不正确。有什么建议吗?
答案 0 :(得分:4)
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="TheNode[preceding::TheNode]"/>
</xsl:stylesheet>
答案 1 :(得分:2)
//TheNode[position()!=1]
不起作用,因为此处position()
相对于每个<TheNode>
的父上下文。它将选择所有<TheNode>
s,这些{{1}}不在其各自的父级中。
但你走在正确的轨道上。您的含义是:
(//TheNode)[position()!=1]
请注意括号 - 它们会将谓词应用于整个选定的节点集,而不是单独应用于每个节点。
不幸的是,即使这是有效的XPath表达式,它也无法作为匹配模式。匹配模式必须对单个节点有意义(适用),它不能是选择表达式。
所以@ Alohci的解决方案,
//TheNode[preceding::TheNode]
是表达你想要的正确方法。
答案 2 :(得分:0)
该模式的其他方法是:
<xsl:template match="TheNode[generate-id()
!= generate-id(/descendant::TheNode[1)]"/>
注意:绝对表达式更有可能获得相对表达式的优化整数,如preceding::TheNode