Entomo
Entomo

Reputation: 275

XSL child element to parent attribute, part deux: order of elements matters?

So, based on my previous question (XSLT transform child element to attribute in the parent) I want to use data in a child as an attribute in the parent element. The problem is that when I convert an element that has another child before "poolColor", the poolColor somehow is not added as an attribute.

Working:

<Exchange xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <parent xsi:type="SinglePool">
        <poolColor colorType="Basecolor" colorKey="GN"/>
        <poolLength type="full_length" length="2"/>
    </parent>
</Exchange>

Results in:

<Exchange xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <parent xsi:type="SinglePool" basecolor="GN">
        <poolLength type="full_length" length="2" />
    </parent>
</Exchange>

Not working:

<Exchange xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <parent xsi:type="SinglePool">
        <poolLength type="full_length" length="2" id="N7" />
        <poolColor colorType="Basecolor" colorKey="GN" id="N3" />
    </parent>
</Exchange>

Results in:

<Exchange xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <parent xsi:type="SinglePool">
        <poolLength type="full_length" length="2" id="N7" />
    </parent>
</Exchange>

The XSL code that I am using is the following:

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

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

    <xsl:template match="poolColor">
        <xsl:attribute name='{translate(@colorType,"BC","bc")}'>
        <xsl:value-of select="@colorKey" />
    </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

I would be glad if someone could shed some light into why this is happening.

Upvotes: 0

Views: 39

Answers (1)

wero
wero

Reputation: 32980

xsl:attribute in the second example does not work since <poolength>has been added to <parent>. This is an error according to the XSLT rec:

The following are all errors:
Adding an attribute to an element after children have been added to it; implementations may either signal the error or ignore the attribute.
...

The following would work since any poolColor child is handled before the other content:

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="@*|poolColor" />
        <xsl:apply-templates select="node()[name()!='poolColor']" />
    </xsl:copy>
</xsl:template>

Upvotes: 1

Related Questions