Here's an option that is self-contained and doesn't require any outside XML files.
When this XSLT:
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my"
exclude-result-prefixes="my"
version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:attributeNames>
<name original="FingerOne" new="F1"/>
<name original="FingerTwo" new="F2"/>
<name original="FingerThree" new="F3"/>
</my:attributeNames>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Hand/*">
<xsl:attribute
name="{document('')/*/my:attributeNames/*
[@original = name(current())]/@new}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
...is applied against the provided XML:
<Hand id="left">
<FingerOne>Thumb</FingerOne>
<FingerTwo>Pointer</FingerTwo>
<FingerThree>Middle</FingerThree>
</Hand>
...the wanted result is produced:
<Hand id="left" F1="Thumb" F2="Pointer" F3="Middle" />
Explanation:
Note the
<my:attributeNames>
"array" of elements; furthermore, note how the "old" and "new" values are contained on these elements as attributes.These values are accessed via the use of the
document('')
instruction, which instructs the parser to gather elements from the current document.
Alternatively, here's a different XSLT 1.0 solution. It might be more useful if:
document('')
is, for some reason, not available in your environment.
OR
- Using a pseudo-dictionary in your XSLT seems a bit heavy-handed (and you're willing to make a small assumption).
When this XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vStartingChar" select="'F'" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Hand/*">
<xsl:attribute
name="{concat($vStartingChar, count(preceding-sibling::*) + 1)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
...is applied against the same input XML, the wanted result is, again, produced:
<Hand id="left" F1="Thumb" F2="Pointer" F3="Middle" />
Explanation:
Note the variable defined at the top of the XSLT:
<xsl:variable name="vStartingChar" select="'F'" />
This provides a convenient mechanism to change to the starting character of the new attributes. As mentioned before, if this same pattern continues (i.e., additional attributes would follow the same scheme - F4
, F5
, etc.), this solution is a shade nicer, as it doesn't require you to update an "array" of elements.