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

Remove all child nodes except last using 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 的 last 节点(包括它们的子节点)以及文件的其余部分,导致:

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

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

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

在此转换中,第一个模板是身份转换,第二个模板跳过 <c><d> 的子级,第三个覆盖排除以包含每个 [=12] 的最后一个子级=] 和 <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 以删除一些空格。根据 specification (section 3.1 Start-tags, end-tags, and empty-element tags).

,构造 <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>

而且病情可能会有改善。

哪个更好当然是口味问题。我发现我原来的回复稍微清楚了。