0

I am trying to transform an xml. The xml root and child element tags will not same all the time but they follow some pattern in common. The xml looks like

<INV_100248>
<INV_100248_row>
<INVNO> 100248</INVNO>
<INVDT>20-01-2017</INVDT>
</INV_100248_row>
</INV_100248>

The INV number will be changing each time we receive the xml. EX: <INV_100249>.

Please help me to transform this xml so that it works for any xml with just a change in the INV Number.

Any help is really appreciated.

6
  • use "/" at root transform and for child use "*" Commented Mar 4, 2017 at 13:53
  • or you can directly use //INVNO or //INVDT Commented Mar 4, 2017 at 13:59
  • "Please help me to transform this xml" Transform it into what? Please show your expected result. Commented Mar 4, 2017 at 16:20
  • Input xml <INV_100248> <INV_100248_row> <INVNO> 100248</INVNO> <INVDT>20-01-2017</INVDT> <ITN>Item1</ITN> <ITN_QTY>2</ITN_QTY> <ITN_UP>200</ITN_UP> <ITN_TP>400</ITN_TP> </INV_100248_row> <INV_100248_row> <INVNO> 100248</INVNO> <INVDT>20-01-2017</INVDT> <ITN>Item2</ITN> <ITN_QTY>1</ITN_QTY> <ITN_UP>100</ITN_UP> <ITN_TP>100</ITN_TP> </INV_100248_row> <INV_100248_row> <INVNO> 100248</INVNO> <INVDT>20-01-2017</INVDT> <ITN>Item3</ITN> <ITN_QTY>5</ITN_QTY> <ITN_UP>250</ITN_UP> <ITN_TP>750</ITN_TP> </INV_100248_row> </INV_100248> Commented Mar 4, 2017 at 17:57
  • Output xml <INV> <INVNO>100248</INVNO> <INVDT>20-01-2017</INVDT> <ITEMS> <ITEM> <ITN>Item1</ITN> <ITN_QTY>2</ITN_QTY> <ITN_UP>200</ITN_UP> <ITN_TP>400</ITN_TP> </ITEM> <ITEM> <ITN>Item2</ITN> <ITN_QTY>1</ITN_QTY> <ITN_UP>100</ITN_UP> <ITN_TP>100</ITN_TP> </ITEM> <ITEM> <ITN>Item3</ITN> <ITN_QTY>5</ITN_QTY> <ITN_UP>250</ITN_UP> <ITN_TP>750</ITN_TP> </ITEM> </ITEMS> </INV> Commented Mar 4, 2017 at 17:58

2 Answers 2

1

Given:

XML

<INV_100248>
  <INV_100248_row>
    <INVNO> 100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item1</ITN>
    <ITN_QTY>2</ITN_QTY>
    <ITN_UP>200</ITN_UP>
    <ITN_TP>400</ITN_TP>
  </INV_100248_row>
  <INV_100248_row>
    <INVNO> 100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item2</ITN>
    <ITN_QTY>1</ITN_QTY>
    <ITN_UP>100</ITN_UP>
    <ITN_TP>100</ITN_TP>
  </INV_100248_row>
  <INV_100248_row>
    <INVNO> 100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item3</ITN>
    <ITN_QTY>5</ITN_QTY>
    <ITN_UP>250</ITN_UP>
    <ITN_TP>750</ITN_TP>
  </INV_100248_row>
</INV_100248>

yoiu can use:

XSLT 1.0

<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="/*">
    <INV>
        <xsl:copy-of select="*[1]/INVNO | *[1]/INVDT"/>
        <ITEMS>
            <xsl:for-each select="*">
                <ITEM>
                    <xsl:copy-of select="ITN | ITN_QTY  | ITN_UP | ITN_TP"/>
                </ITEM>
            </xsl:for-each>
        </ITEMS>
    </INV>
</xsl:template>

</xsl:stylesheet>

to return:

Result

<?xml version="1.0" encoding="UTF-8"?>
<INV>
   <INVNO> 100248</INVNO>
   <INVDT>20-01-2017</INVDT>
   <ITEMS>
      <ITEM>
         <ITN>Item1</ITN>
         <ITN_QTY>2</ITN_QTY>
         <ITN_UP>200</ITN_UP>
         <ITN_TP>400</ITN_TP>
      </ITEM>
      <ITEM>
         <ITN>Item2</ITN>
         <ITN_QTY>1</ITN_QTY>
         <ITN_UP>100</ITN_UP>
         <ITN_TP>100</ITN_TP>
      </ITEM>
      <ITEM>
         <ITN>Item3</ITN>
         <ITN_QTY>5</ITN_QTY>
         <ITN_UP>250</ITN_UP>
         <ITN_TP>750</ITN_TP>
      </ITEM>
   </ITEMS>
</INV>
Sign up to request clarification or add additional context in comments.

2 Comments

Michael, Thank you so much for your answer it really helped me a lot. Need one more help. The pattern match should be some thing that matches "INV_XXXX" for root element and "INV_XXXX_row" for child elements. As we are using only one xsl for different pattern matches. Please help me with this.
@Vijay 1. Why is this necessary? 2. Can you use XSLT 2.0?
0

Here's another possibility; this solution is slightly longer, but I think it provides nice flexibility (in case a single XML document could contain data on multiple invoices).

When this XSLT:

<?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" omit-xml-declaration="no" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="kInvByNo" match="*/*" use="INVNO"/>

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

  <xsl:template match="/*">
    <INV>
      <xsl:apply-templates
        select="*[
        generate-id() = generate-id(key('kInvByNo', INVNO)[1])
        ]"/>
    </INV>
  </xsl:template>

  <xsl:template match="*[contains(name(), '_row')]">
    <xsl:apply-templates select="INVNO|INVDT"/>
    <ITEMS>
      <xsl:for-each select="key('kInvByNo', INVNO)">
        <ITEM>
          <xsl:apply-templates select="*[starts-with(name(), 'ITN')]"/>
        </ITEM>
      </xsl:for-each>
    </ITEMS>
  </xsl:template>

</xsl:stylesheet>

...is used on the provided XML:

<INV_100248>
  <INV_100248_row>
    <INVNO>100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item1</ITN>
    <ITN_QTY>2</ITN_QTY>
    <ITN_UP>200</ITN_UP>
    <ITN_TP>400</ITN_TP>
  </INV_100248_row>
  <INV_100248_row>
    <INVNO>100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item2</ITN>
    <ITN_QTY>1</ITN_QTY>
    <ITN_UP>100</ITN_UP>
    <ITN_TP>100</ITN_TP>
  </INV_100248_row>
  <INV_100248_row>
    <INVNO>100248</INVNO>
    <INVDT>20-01-2017</INVDT>
    <ITN>Item3</ITN>
    <ITN_QTY>5</ITN_QTY>
    <ITN_UP>250</ITN_UP>
    <ITN_TP>750</ITN_TP>
  </INV_100248_row>
</INV_100248>

...the desired answer is produced:

<?xml version="1.0"?>
<INV>
  <INVNO>100248</INVNO>
  <INVDT>20-01-2017</INVDT>
  <ITEMS>
    <ITEM>
      <ITN>Item1</ITN>
      <ITN_QTY>2</ITN_QTY>
      <ITN_UP>200</ITN_UP>
      <ITN_TP>400</ITN_TP>
    </ITEM>
    <ITEM>
      <ITN>Item2</ITN>
      <ITN_QTY>1</ITN_QTY>
      <ITN_UP>100</ITN_UP>
      <ITN_TP>100</ITN_TP>
    </ITEM>
    <ITEM>
      <ITN>Item3</ITN>
      <ITN_QTY>5</ITN_QTY>
      <ITN_UP>250</ITN_UP>
      <ITN_TP>750</ITN_TP>
    </ITEM>
  </ITEMS>
</INV>

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.