使用XSLT如何复制特定的XML子树

时间:2017-06-02 15:42:41

标签: xml xslt

我已经找到了正确使用xsl:copy(XSLT 1.0)的各种答案,但它们似乎都使用相同的<xsl:template match="@*|node()">,它可以正常复制整个文档。我正在努力匹配一个特定节点,该节点的子树我想复制并应用模板。

例如,给定此XML文档:

<MyXML>
  <a>
    <b>c</b>
  </a>
  <d>
    <e>f</e>
  </d>
  <g x="y">
    <foo bar="baz">
      <item name="aname">quux</item>
      <item name="bname">xyzzy</item>
    </foo>
  </g>
</MyXML>

这个样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

  <xsl:template match="item[@name='bname']/text()">
    <xsl:value-of select="translate(current(), 'y', 'Y')" />
  </xsl:template>

</xsl:stylesheet>

我想要做的只是复制元素foo及其属性和子节点,同时应用该翻译&#39; y&#39; - &gt;& #39; Y&#39 ;.我想要的结果是:

<foo bar="baz">
  <item name="aname">quux</item>
  <item name="bname">xYzzY</item>
</foo>

我认为这可能就像将<xsl:template match="@*|node()">更改为<xsl:template match="//foo"><xsl:template match="//foo/@*|//foo/node()">一样简单。我一直在猜测各种其他排列,但我无法得到我需要的结果。

1 个答案:

答案 0 :(得分:2)

如果您只想处理foo元素,则只需添加一个与根节点匹配的模板,并仅将模板应用于您想要的节点(从而删除所有其他节点):

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="/">
    <xsl:apply-templates select="MyXML/g/foo"/>
</xsl:template>

<xsl:template match="item[@name='bname']/text()">
    <xsl:value-of select="translate(., 'y', 'Y')" />
</xsl:template>

</xsl:stylesheet>

请注意,这假设最多只有一个foo元素 - 否则结果将不是格式良好的XML文档。