1
votes

I'm currently stuck on applying multiple xsl:template with the same match for an element. The example below shows the problem.

Does anyone knows a XSL template that creates the expected output using two "template match"s? For technical reasons it's not possible to put the two "template" elements together.

Input

<root>
    <elem>123.45</elem>
    <elem>789.12</elem>
</root>

XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:decimal-format name="de" decimal-separator="," grouping-separator="."/>

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

    <xsl:template match="/root/elem">
        <xsl:element name="renamed">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="/root/elem">
        <xsl:element name="elem">
            <xsl:value-of select="format-number(.,'#.##0,0000','de')" />
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

Output:

<root>
    <elem>123,4500</elem>
    <elem>789,1200</elem>
</root>

Expected output:

<root>
    <renamed>123,4500</renamed>
    <renamed>789,1200</renamed>
</root>

Thanks

2

2 Answers

14
votes

Having two templates of the same priority that match the same node is an error according to the XSLT specification, and:

if [the processor] does not signal the error, it must recover by choosing, from amongst the matching template rules that are left, the one that occurs last in the stylesheet. (source)

That is why the second template wins.

If you want to factor out the number formatting as a re-usable component I'd consider a named template

<xsl:template name="format">
  <xsl:value-of select="format-number(.,'#.##0,0000','de')" />
</xsl:template>

<xsl:template match="/root/elem">
  <renamed>
    <xsl:call-template name="format" />
  </renamed>
</xsl:template>
0
votes

Normally you would use "mode" to process the same node with different templates. That I think you do not need in your case. If you apply this XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:decimal-format name="de" decimal-separator="," grouping-separator="."/>


<xsl:template match="/">
    <root>
    <xsl:apply-templates />
    </root>
</xsl:template>

<xsl:template match="/root/elem">
    <xsl:element name="renamed">
        <xsl:value-of select="format-number(.,'#.##0,0000','de')" />
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

to your source XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
 <elem>123.45</elem>
 <elem>789.12</elem>
</root>

you get this output:

<?xml version="1.0" encoding="UTF-8"?>
<root>
 <renamed>123,4500</renamed>
 <renamed>789,1200</renamed>
</root>

Best regards, Peter