In an XSLT mapping I wanted to convert the node with its child nodes to a node with attributes.
I noticed that the source schema contained more than 60 child nodes and most of them could be optional. The transform of this mapping would result in a big piece of code for some logic that perhaps could be made in a better way.
This process could be optimized by creating the attributes in a dynamic way.
For illustration, I am using this small piece of XML:
<Contact>
<Name>Reception</Name>
<Phone>+32 9 247 32 65</Phone>
<Mobile>+32 475 36 45 78</Mobile>
<Fax>+32 9 247 32 66</Fax>
<Email>reception@company.be</Email>
</Contact>
This is the desired output:
<Contact Name=’Reception’ Phone=’+32 9 247 32 65′ Mobile=’+32 475 36 45 78′ Fax=’+32 9 247 32 66′ Email=’reception@company.be’ />
The Problem
I am looping through each child node with the query Contact/* (there is no namespace for simplicity reasons). The function name() is able to give the name of the node. I store this name in the variable $attributeName, for later usage. When we know the name of the current node, this should be easy to create an attribute dynamically:
<Contact>
<xsl:for-each select=”Contact/*”>
<xsl:variable name=”attributeName” select=”name(.)” />
<xsl:attribute name=”$attributeName”>
<xsl:value-of select=”‘value'”/>
</xsl:attribute>
</xsl:for-each>
</xsl:for-each>
</Contact>
Although, it is impossible to define special characters in the name parameter of the attribute definition.
Visual studio gave me the error “the ‘$’ character, hexadecimal value 0x24, cannot be included in a name.”
The Solution
The name argument is not able to perform a query or do some piece of logic. This problem can be solved by working with attribute value templates. Attribute value templates will evaluate the expression and convert the resulting object to a string.
I replaced $attributeName with {$attributeName}
This is the final result:
<Contact>
<xsl:for-each select=”Contact/*”>
<xsl:variable name=”attributeName” select=”name(.)” />
<xsl:attribute name=”{$attributeName}”>
<xsl:value-of select=”‘value'”/>
</xsl:attribute>
</xsl:for-each>
</xsl:for-each>
</Contact>
More information about attribute value templates can be found on the website of W3C.
Additional Notes
The same trick can be used to create elements in a dynamic way in XSLT or for using variables in arguments.
Note that when the source schema will be changed and some child nodes are added, this mapping will also add those attributes, even if this is unknown by the destination schema. This can be positive or negative.
Subscribe to our RSS feed