删除除上次使用XSLT之外的所有子节点

时间:2015-01-02 11:20:58

标签: xml xslt

我有一个XML文件:

<a>
  <b>
    <e />
    <f />
  </b>
  <c>
    <g>
      <j />
    </g>
    <g>
      <j />
    </g>
    <g>
      <j />
    </g>
  </c>
  <d>
    <h>
      <i />
    </h>
    <h>
      <i />
    </h>
    <h>
      <i />
    </h>
  </d>
</a>

我尝试做的是将XSL转换应用于获取c和d的最后节点(包括其子节点)以及文件的其余部分,导致:

<a>
  <b>
    <e />
    <f />
  </b>
  <c>
    <g>
      <j />
    </g>
  </c>
  <d>
    <h>
      <i />
    </h>
  </d>
</a>

我对XSLT没有经验,非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

通常最好从identity transform开始并添加例外,然后有时会例外。

在此转换中,第一个模板是标识转换,第二个模板跳过<c><d>的子项,第三个模板覆盖排除项以包含每个<c>的最后一个子项和<d>标记。

<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="c/*|d/*"/>

 <xsl:template match="c/*[last()]|d/*[last()]">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

</xsl:stylesheet>

我必须修改输入xml以删除一些空格。根据{{​​3}},构造<x/ >并不真正有效。

如评论中所述,除了身份之外,只使用一个模板可以缩短时间。我无法让[not(last()]工作,但这个较短的模板可以:

<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="c/*[position() &lt; last()]|d/*[position() &lt; last()]"/>

</xsl:stylesheet>

并且在这种情况下可能会有所改善。

哪个更好当然是品味问题。我发现原来的反应更清晰了。