Entomo
Entomo

Reputation: 275

Change element name based on attribute value XSLT

I want to do something simple (or so I thought) using XSLT. I want to split a list of elements to two, rename an element using The idea is that a xml formed like this:

<elem at="value" id="something"/>
<elem at="value" id="something2"/>
<elem at="random" id="something3"/>

will be converted to:

<elemVal id="something"/>
<elemVal id="something2"/>
<elemRa id="something3"/>

(the new element names are static) So the elements are renamed based on the value of an attribute.

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

<xsl:template match="elem/@at[.='value']">
    <xsl:element name="elemVa">
        <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
</xsl:template>

So far I have an identity template, but I don't understand how I can go backwards and change the elements name, keeping it's content.

Upvotes: 4

Views: 1867

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167506

Instead of

<xsl:template match="elem/@at[.='value']">

you need

<xsl:template match="elem[@at ='value']">

then create the new element (a literal suffices) and make sure the at attribute is not processed:

<xsl:template match="elem[@at ='value']">
    <elemVa>
        <xsl:apply-templates select="@* except @at | node()"/>
    </elemVa>
</xsl:template>

The above is XSLT/XPath 2.0, in 1.0 you can use

<xsl:template match="elem[@at ='value']">
    <elemVa>
        <xsl:apply-templates select="@*[not(local-name() = 'at')] | node()"/>
    </elemVa>
</xsl:template>

Upvotes: 5

Related Questions