Reputation:
I have a XML file similar to the following:
<a>
<b value="a123" />
<b value="b234" />
<b value="c345" />
</a>
I need to map the attributes to some other value. For example, I want to replace a123
with q999
, b234
with z998
and c345
with u997
. Is it possible to do such transformation efficiently using XSLT? The mapping itself is generated, so I can convert it into almost any format. For now, let's say it's the following XML file:
<map>
<item from="c345" to="u997" />
<item from="b234" to="z998" />
<item from="a123" to="q999" />
</map>
Maybe there's a better tool than XSLT to do such transformation? Currently I just sed
through the file many times. Obviously this solution is horribly inefficient and doesn't scale at all.
Upvotes: 3
Views: 5654
Reputation: 243449
As easy as this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:map>
<map>
<item from="c345" to="u997" />
<item from="b234" to="z998" />
<item from="a123" to="q999" />
</map>
</my:map>
<xsl:variable name="vMap" select=
"document('')/*/my:map/*/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"@value[. = document('')/*/my:map/*/*/@from]">
<xsl:attribute name="value">
<xsl:value-of select="$vMap[@from = current()]/@to"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the provided XML document:
<a>
<b value="a123" />
<b value="b234" />
<b value="c345" />
</a>
the wanted, correct result is produced:
<a>
<b value="q999"/>
<b value="z998"/>
<b value="u997"/>
</a>
Explanation:
Overriding the identity template for value
attributes whos value is equal to a from
attribute in the map.
The map is presented inline in the transformation and accessed using the document()
function. Alternatively, the filepath to the file containing the map can be passed as external parameter to the transformation and the Map XML document can be accessed using again the document()
function, passing as argument to it this filepath.
Upvotes: 8