user1131913
user1131913

Reputation: 1

XSLT to copy an XML with change of values

We have a xml which needs to be transformed using XSLT. But, we have to add two attributes of a tag and place it in other tag.

In below XML compilation tag with column 'Reusable' has values contrib and max_available. We want addition of these two attributes and want it in the attribute postPosition of compilation tag with column "Usable". Now, we have additional requirement to add on the basis of fac value as well.

Input

<?xml version="1.0" encoding="UTF-8"?>
<answers user="LST">
    <answer name="compile">
        <output>
            <compilations>
                <compilation column="Usable" fac="123" contrib="0" max_available="0" postPosition="35000">
                </compilation>
                  <compilation column="Usable" fac="456" contrib="0" max_available="0" postPosition="35000">
                </compilation>
                  <compilation column="ReUsable" fac="123" contrib="0" max_available="200" postPosition="300">
                </compilation>
                <compilation column="Reusable" fac="456" contrib="100.00" postPosition="100.00" max_available="200">
                </compilation>
            </compilations>
        </output>
    </answer>
</answers>

Output :

<?xml version="1.0" encoding="UTF-8"?>
    <answers>
        <answer name="compile">
            <output>
                <compilations>
                    <compilation column="Usable" fac="123" contrib="0" max_available="0" postPosition="500">
                    </compilation>
                      <compilation column="Usable" fac="456" contrib="0" max_available="0" postPosition="300">
                    </compilation>
                      <compilation column="ReUsable" fac="123" contrib="0" max_available="200" postPosition="300">
                    </compilation>
                    <compilation column="Reusable" fac="456" contrib="100.00" postPosition="100.00" max_available="200">
                    </compilation>
                </compilations>
            </output>
        </answer>
    </answers>

Upvotes: 0

Views: 1858

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 117140

How about simply:

XSLT 2.0

<xsl:stylesheet version="2.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="compilation[@column='Usable']/@postPosition">
    <xsl:attribute name="postPosition" select="format-number(../../compilation[@column='Reusable']/(@contrib + @max_available), '0.00')" />
</xsl:template>

</xsl:stylesheet>

Note that this assumes there is only one compilation with a 'Reusable' column in a compilations element.


EDIT:

To do the same thing in 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="compilation[@column='Usable']/@postPosition">
<xsl:variable name="reusable" select="../../compilation[@column='Reusable']" />
    <xsl:attribute name="postPosition"> 
        <xsl:value-of select="format-number($reusable/@contrib + $reusable/@max_available, '0.00')" />
    </xsl:attribute>  
</xsl:template>

</xsl:stylesheet>

Upvotes: 1

Philipp
Philipp

Reputation: 4749

Following XSLT will copy the Usable compilation and change the value of the postPosition attribute:

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:template match="compilation[@column='Usable']">
        <xsl:copy>
            <!-- copy other attributes first -->
            <xsl:apply-templates select="@column"/>
            <xsl:apply-templates select="@contrib"/>
            <xsl:apply-templates select="@max_available"/>
            <!-- set the postPosition attribute -->
            <xsl:attribute name="postPosition">
                <xsl:variable name="reusableCompilation" select="../compilation[@column='Reusable']"/>
                <xsl:value-of select="number($reusableCompilation/@contrib)+number($reusableCompilation/@max_available)"></xsl:value-of>
            </xsl:attribute>
            <!-- copy all child elements -->
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- generic template - copy all the rest -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

This will give you following output with the sumb of both attributes @contrib + @max_available:

<?xml version="1.0" encoding="UTF-8"?>
<answers>
    <answer name="compile">
        <output>
            <compilations>
                <compilation column="Usable" contrib="0" max_available="0" postPosition="300">
                </compilation>
                <compilation column="Reusable" contrib="100.00" postPosition="100.00" max_available="200">
                </compilation>
            </compilations>
        </output>
    </answer>
</answers>

Upvotes: 0

Related Questions