Search code examples
xsltmergeexternal

I need to change an xml attribute value conditionaly from an external xml using Xsl


I have the following 2 xml files,

Mapping.xml

<xml>
    <map ordinal="0" reverse="xxx" forward="ThisIsXxx" />
    <map ordinal="0" reverse="yyy" forward="ThisIsYyy" />
    <map ordinal="0" reverse="zzz" forward="thisIsZzz" />
    <map ordinal="0" reverse="xx1" forward="ThisIsXx1Info" />
    <map ordinal="0" reverse="yy1" forward="ThisIsYy1Info" />
    <map ordinal="0" reverse="zz1" forward="ThisIsZz1Info" />
</xml>

and an input xml file with a series of elements with some of them having a 'name' attribute

second.xml

<?xml version="1.0" encoding="UTF-8"?>
<xml>
   <Children>
      <child name="xxx">
        <info name="xx1">
        </info>
      </child>
      <child name="yyy">
        <info name="yy1">
        </info>
      </child>
      <child name="zzz">
        <info name="zz1">
        </info>
      </child>
   </Children>     <!-- Added by edit --> 
</xml>

What I need is if direction is 'forward' then the second.xml files @name to be set to the value from @forward from the Mapping.xml such as the following,

output.xml

<?xml version="1.0" encoding="UTF-8"?>
<xml>
   <Children>
      <child name="ThisIsXxx">
        <info name="ThisIsXx1Info">
        </info>
      </child>
      <child name="ThisIsZzz">
        <info name="ThisIsYy1Info">
        </info>
      </child>
      <child name="ThisIsYyy">
        <info name="ThisIsZz1Info">
        </info>
      </child>
</xml>

Xslt file I have is setting all @name="" but not getting any values from the external file..

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  
  <xsl:output method="xml" indent="yes"/>

  <!-- get the mapping db -->
  <xsl:variable name="mapDb" select="document('Mapping.xml')" />
  <xsl:variable name="mapFwd" select="forward" />

  
  <!-- for all @name find the @mapdb/*/@reverse == @name and set @name=@mapDb/*/forward -->
  <xsl:template match="*/@name">
    <xsl:choose>
      <xsl:when test="$mapFwd='forward'">
        <xsl:attribute name="name">
          <xsl:value-of select="$mapDb/xml/map[@reverse='{@name}']/@forward"/>
        </xsl:attribute>
      </xsl:when>
      <xsl:otherwise>
        <xsl:attribute name="name">
          <xsl:value-of select="$mapDb/xml/map[@forward='{@name}']/@reverse"/>
        </xsl:attribute>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!--Copy Everything unchanged-->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

I would appreciate some help.


Solution

  • I think you want to use current() e.g. $mapDb/xml/map[@reverse=current()] in your comparisons in the template matching the @name attribute and of course the variable should be initialized with <xsl:variable name="mapFwd" select="'forward'"/>.