Reputation: 25
I use XSLT transformation to add elements configuration
and status
to my XML data in case one or both of them are missing. I'd like to use independent templates to handle each of the these, but it seems only one of the template takes effect.
Source data:
<data>
<environment>
<id>test</id>
<details>Detail info for environment...</details>
</environment>
<default_conf>abcd1234</default_conf>
<default_status>1</default_status>
</data>
XSLT:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<!-- identity transformation -->
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<!-- if configuration not given, create it with the value of default_conf -->
<xsl:template match="data[not(configuration)]">
<xsl:copy>
<xsl:apply-templates/>
<!--xsl:apply-templates select="@*|node()"/-->
<configuration><xsl:value-of select="default_conf"/></configuration>
</xsl:copy>
</xsl:template>
<!-- if status not given, create it with the value of default_status -->
<xsl:template match="data[not(status)]">
<xsl:copy>
<xsl:apply-templates/>
<!--xsl:apply-templates select="@*|node()"/-->
<status><xsl:value-of select="default_status"/></status>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
In the result XML only the element is created, but not the element. What's wrong with the transformation templates and how to correct it?
Please note that I need to pass also the default_conf
and default status
elements, so I'm not looking to rename these elements.
Desired output:
<data>
<environment>
<id>test</id>
<details>Detail info for environment...</details>
</environment>
<default_conf>abcd1234</default_conf>
<default_status>1</default_status>
<configuration>abcd1234</configuration>
<status>1</status>
</data>
Upvotes: 1
Views: 125
Reputation: 117043
In XSLT,
A node is processed by finding all the template rules with patterns that match the node, and choosing the best amongst them;
https://www.w3.org/TR/1999/REC-xslt-19991116/#section-Processing-Model
When both configuration
and status
are missing, you have two templates that match the same node, with the same priority. This is an error:
An XSLT processor may signal the error; if it 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.
https://www.w3.org/TR/1999/REC-xslt-19991116/#conflict
The simple solution is to use a single template with two xsl:if
instructions to add each missing node. Otherwise you would need to use not two, but three templates - and make sure the added template takes precedence.
Upvotes: 1