Thesaurus Rex
Thesaurus Rex

Reputation: 143

XSLT : concatenate attributes with unknown names

Following my last answered question, I am now trying to delete two attributes and creating a new one using their concatenated values :

Input :

<A>
<B>
    <elemX att1="SN:" att2="toto1" att3="tata" SerialNumber="123X" />
    <elemY att1="SN:" att2="toto2" att3="tata" SerialNumber="123Y" />
</B>
<B>
    <elemX att1="tata1" att2="SN:" att3="toto" SerialNumber="456X" />
    <elemY att1="tata2" att2="SN:" att3="toto" SerialNumber="456Y" />
</B>
<B>
    <elemX att1="toto1" att2="tata" att3="SN:" SerialNumber="789X" />
    <elemY att1="toto" att2="tata2" att3="SN:" SerialNumber="789Y" />
</B>

Desired output :

<A>
<B>
    <elemX SerialHarnessNumber="SN:"123X att2="toto1" att3="tata" />
    <elemY SerialHarnessNumber="SN:123Y" att2="toto2" att3="tata" />
</B>
<B>
    <elemX att1="tata1" SerialHarnessNumber="SN:456X" att3="toto" />
    <elemY att1="tata2" SerialHarnessNumber="SN:456Y" att3="toto" />
</B>
<B>
    <elemX att1="toto1" att2="tata" SerialHarnessNumber="SN:789X" />
    <elemY att1="toto" att2="tata2" SerialHarnessNumber="SN:789Y" />
</B>

The order of the elements doesn't really matter here.

To do so, I use the following XSL :

<?xml version="1.0" encoding="UTF-8"?>

<xsl:output method="xml" indent="yes"/>

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

<xsl:template match="@*[.='SN:']" >
    <xsl:attribute name="SerialHarnessNumber">
        <xsl:value-of select="concat('SN:', @SerialNumber)" />
    </xsl:attribute>
</xsl:template>

<xsl:template match="@SerialNumber" />

For the moment, I only managed to display "SN:" in the SerialNumber attribute, but the SerialHarnessNumber doesn't concatenate with it, though I used the @ before SerialNumber, a syntax which worked previously on another XSLT.

I assume the problem comes from the fact that the SN: value is never in the same element.

How can I concatenate the SerialNumber value with the attX value ?

Upvotes: 1

Views: 214

Answers (3)

michael.hor257k
michael.hor257k

Reputation: 117043

Wouldn't this be simpler?

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="@SerialNumber">
    <xsl:attribute name="SerialHarnessNumber">
            <xsl:value-of select="concat('SN:', .)" />
    </xsl:attribute>
</xsl:template>

<xsl:template match="@*[.='SN:']"/>

</xsl:stylesheet>

Upvotes: 0

Martin Honnen
Martin Honnen

Reputation: 167641

Use ../@SerialNumber to select the parent element's attribute.

Upvotes: 0

Tomalak
Tomalak

Reputation: 338278

Almost.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="@*[.='SN:']" >
        <xsl:attribute name="SerialHarnessNumber">
            <xsl:value-of select="concat('SN:', ../@SerialNumber)" />
            <!-- _______________________________^^^               -->
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="@SerialNumber" />

</xsl:stylesheet>

Upvotes: 1

Related Questions