This stylesheet would also work:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<!--Identity template to copy content forward-->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!--specialized template for elements with an "n" attribute-->
<xsl:template match="*[@n]">
<xsl:element name="{@n}">
<xsl:apply-templates select="node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
The first template in an identity template which matches on @*
(which means any attribute) and node()
(which means any element, text node, processing-instruction, or comment). The default behavior is to copy the matched item, and then apply-templates
to any of it's attributes or child nodes.
If no other templates were declared in the stylesheet, then that identity template would match for everything and the XSLT would simply make a copy of the XML document.
The second template matches on *[@n]
, which is any element that has an "n" attribute. *
is a wildcard match for any element. The square brackets are a predicate filter, which act kind of like an SQL WHERE clause. Any conditions specified in the predicate must be true in order for the template match to select whatever is being fitlered. The predicate filter evaluates from the context of the matched item, so assuming that you are "standing" on an element, does it have an @n
? If so, then this template matches.
The second template has a more specific match criteria than the first "identity" template, so it "wins" and will match for elements that have an @n
.
The logic for the second template is to create an element with the name of the value of the @n
and then apply-templates
for any of the child node()
(which includes both text()
and elements, but does not include attributes).