Using XSLT how can I copy a specific XML subtree

Viewed 1984

I've found a variety of answers around using xsl:copy (XSLT 1.0) properly, but they all seem to use the same <xsl:template match="@*|node()"> which works fine for copying a whole document. I'm struggling to match just a specific node whose sub-tree I'd like to copy and apply templates to.

For example, given this XML doc:

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

And this stylesheet:

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

What I'd like to do is copy only the element foo along with its attributes and child nodes, while at the same time applying that translation 'y'->'Y'. The result I want is this:

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

I thought it might be as easy as changing <xsl:template match="@*|node()"> to <xsl:template match="//foo"> or <xsl:template match="//foo/@*|//foo/node()">. I've been guessing at a variety of other permutations but I can't get the results I need.

1 Answers
Related