0

I need to be able to convert this XML:

<Root>
  <Fields>
    <Field ID="XYZ" Value="M" />
    <Field ID="XYZ.DECODED" Value="Male" />    
    <Field ID="ABC.DECODED" Value="Yellow" />
    <Field ID="ABC" Value="Y" />
    <Field ID="123.DECODED" Value="Low" />
    <Field ID="456" Value="Smith" />
    <Field ID="123" Value="1" />    
  </Fields>
</Root>

into this XML:

<Root>
  <Fields>
    <Field ID="XYZ" Value="M" DisplayValue="Male" />
    <Field ID="ABC" Value="Y" DisplayValue="Yellow" />
    <Field ID="456" Value="Smith" DisplayValue="Smith" />
    <Field ID="123" Value="1" DisplayValue="Low" />
  </Fields>
</Root>

using XSLT. The "XYZ", "ABC", "123", etc. ID attributes I won't know ahead of time. Any ideas how? Do I need to create an XPATH expression from a variable?

2 Answers 2

1

This does what you want

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="Field">
        <xsl:variable name="ref" select="concat(@ID,'.DECODED')"/>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="DisplayValue"><xsl:value-of select="//Field[@ID=$ref]/@Value"/></xsl:attribute>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Field[contains(@ID,'.DECODED')]"/>

</xsl:stylesheet>

It's an identity transform plus two templates, one to eliminate the Field nodes that have .DECODED in the ID attribute, and one to copy the nodes you want and add the value.

Sign up to request clarification or add additional context in comments.

1 Comment

Perfect! Thank you!
0

I added a bit to add the DisplayValue for the elements without the .DECODED values.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="Field">
    <xsl:variable name="ref" select="concat(@ID,'.DECODED')"/>
    <xsl:copy>
      <xsl:variable name="dv">
        <xsl:choose>
          <xsl:when test="//Field[@ItemOID=$ref]/@Value">
            <xsl:value-of select="//Field[@ItemOID=$ref]/@Value"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="@Value"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <xsl:apply-templates select="@*"/>
      <xsl:attribute name="DisplayValue">
        <xsl:value-of select="$dv"/>
      </xsl:attribute>
    </xsl:copy>    
  </xsl:template>
  <xsl:template match="Field[contains(@ID,'.DECODED')]"/>
</xsl:stylesheet>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.