user283145
user283145

Reputation:

How to map values of an xml attribute to some other values

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

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

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:

  1. Overriding the identity template for value attributes whos value is equal to a from attribute in the map.

  2. 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

Related Questions