JohnXsl
JohnXsl

Reputation: 269

XSLT Convert attribute to element and copy value from an other elemen

I have XML data like this

<ABC version="1.0">
  <XYZ>
    <ROWSET ROWS="00001">
      <ROWDEF>
        <COLUMN ID="ACCT_ID" LEN="016" NULL="Y"/>
        <COLUMN ID="AGNT_ID" LEN="004" NULL="Y"/>
        <COLUMN ID="CUST_EXTR_ID" LEN="024" NULL="Y"/>
        <COLUMN ID="PI_ID" LEN="019" NULL="Y"/>
        <COLUMN ID="PRIN_ID" LEN="004" NULL="Y"/>
        <COLUMN ID="SYS_ID" LEN="004" NULL="Y"/>
      </ROWDEF>
      <ROW>
        <C>6369921501000060</C>
        <C>0000</C>
        <C>C13093102141063422034238</C>
        <C>6369921501000060   </C>
        <C>1500</C>
        <C>9008</C>
      </ROW>
      <ROW>
        <C>6369921501000061</C>
        <C>0001</C>
        <C>C13093102141063422034231</C>
        <C>6369921501000060   </C>
        <C>1501</C>
        <C>9001</C>
      </ROW>
    </ROWSET>
  </XYZ>
</ABC>

And I'm trying to convert this into

<?xml version="1.0" encoding="utf-8"?>
<ABC version="1.0">
  <XYZ RC="0067">
    <ROWSET ROWS="00001">
      <ROWDEF>
        <ACCT_ID>6369921501000060</ACCT_ID>
        <AGNT_ID>0000</AGNT_ID>
        <CUST_EXTR_ID>C13093102141063422034238</CUST_EXTR_ID>
        <PI_ID>6369921501000060</PI_ID>
        <PRIN_ID>1500</PRIN_ID>
        <SYS_ID>9008</SYS_ID>
      </ROWDEF>
      <ROWDEF>
        <ACCT_ID>6369921501000061</ACCT_ID>
        <AGNT_ID>0001</AGNT_ID>
        <CUST_EXTR_ID>C13093102141063422034231</CUST_EXTR_ID>
        <PI_ID>6369921501000060</PI_ID>
        <PRIN_ID>1501</PRIN_ID>
        <SYS_ID>9001</SYS_ID>
      </ROWDEF>
    </ROWSET>
  </XYZ>
</ABC>

I have looked around and tried few things but it is not working. Can someone help me with this. Below is my XSLT. Thanks in advance.

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

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

  <xsl:template match="COLUMN">
    <xsl:element name="{@ID}">
      <xsl:copy>
        <xsl:apply-templates select="node()"></xsl:apply-templates>
      </xsl:copy>
      <xsl:apply-templates />
      <!--<xsl:call-template name="value"></xsl:call-template>-->
    </xsl:element>
  </xsl:template>

  <!--
  <xsl:template match="ROW" name="value">
    <xsl:copy>
      <xsl:apply-templates select="node()"></xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
  -->

</xsl:stylesheet>

Upvotes: 0

Views: 1939

Answers (1)

Borodin
Borodin

Reputation: 126722

This stylesheet will mostly do what you want, but I cannot fathom how to generate the attribute for <XYZ RC="0067">.

For each ROWSET it comes across it saves the ROWDEF element in a variable, copies all attribute nodes, and then processes each ROW element. The position of each C element in the ROW is caclulated, and the COLUMN in the corresponding position within the stored ROWDEF element is used to fetch an element name from the ID attribute.

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="ROWSET">

    <xsl:variable name="columns" select="ROWDEF/COLUMN"/>

    <xsl:copy>

      <xsl:apply-templates select="@*" />

      <xsl:for-each select="ROW">
        <ROWDEF>
          <xsl:for-each select="C">
            <xsl:variable name="pos" select="position()"/>
            <xsl:element name="{$columns[$pos]/@ID}">
              <xsl:value-of select="."/>
            </xsl:element>
          </xsl:for-each>
        </ROWDEF>
      </xsl:for-each>

    </xsl:copy>

  </xsl:template>

</xsl:stylesheet>

output

<?xml version="1.0" encoding="utf-8"?>
<ABC version="1.0">
   <XYZ>
      <ROWSET ROWS="00001">
         <ROWDEF>
            <ACCT_ID>6369921501000060</ACCT_ID>
            <AGNT_ID>0000</AGNT_ID>
            <CUST_EXTR_ID>C13093102141063422034238</CUST_EXTR_ID>
            <PI_ID>6369921501000060   </PI_ID>
            <PRIN_ID>1500</PRIN_ID>
            <SYS_ID>9008</SYS_ID>
         </ROWDEF>
         <ROWDEF>
            <ACCT_ID>6369921501000061</ACCT_ID>
            <AGNT_ID>0001</AGNT_ID>
            <CUST_EXTR_ID>C13093102141063422034231</CUST_EXTR_ID>
            <PI_ID>6369921501000060   </PI_ID>
            <PRIN_ID>1501</PRIN_ID>
            <SYS_ID>9001</SYS_ID>
         </ROWDEF>
      </ROWSET>
   </XYZ>
</ABC>

Upvotes: 2

Related Questions