2009-10-12 105 views
2

中第一次出现我有XML是这样的:XSLT:删除所有,但给定节点

<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> 

但是,这是不正确的。有什么建议么?

回答

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> 
+0

没有必要为起点' //模式中的操作符。 – 2011-01-24 17:57:25

2

//TheNode[position()!=1]不起作用,因为在这里,position()相对于每个<TheNode>的父上下文。它会选择所有<TheNode>,这些不是其各自的父母中的第一个。

但是你是在正确的轨道上。你什么意思

 
(//TheNode)[position()!=1] 

注意括号 - 它们导致谓词分别适用于整个选择的节点集,而不是到每个节点。

不幸的是,即使这是有效的XPath表达式,它作为匹配模式无效。匹配模式必须对单个节点有意义(适用),它不能是选择表达式。

所以@ Alohci的解决方案,

 
//TheNode[preceding::TheNode] 

是表达你想要的正确途径。

0

的图案之外的做法是:

<xsl:template match="TheNode[generate-id() 
          != generate-id(/descendant::TheNode[1)]"/> 

注意:它更可能是一个绝对的表达被optimizated相对表达inteads像preceding::TheNode