2

I have to a large xml in the below format.

<First>
<Second Argument="12" Argument2="34" >
    <Order InvOrg="123" Identifier="3580456" >
                <SupplyDetails Type="TRACK" Quantity="7" Demand="ONHAND" />
    </Order>
    <Order InvOrg="Test" Identifier="3580457" >
                <SupplyDetails Type="TRACK" Quantity="15" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="3580458" >
                <SupplyDetails Type="TRACK" Quantity="17" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="3580459" >
                <SupplyDetails Type="TRACK" Quantity="10" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="2888144" >
                <SupplyDetails Type="TRACK" Quantity="3" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="2888147" >
                <SupplyDetails Type="TRACK" Quantity="9" Demand="ONHAND" />
    <Order>
    <Order InvOrg="123" Identifier="2749622" >
                <SupplyDetails Type="TRACK" Quantity="142" Demand="ONHAND" />
    </Order>
</Second>
</First>

I need to convert it into the below format

<First>
<Second Argument="12" Argument2="34" >
    <Order InvOrg="123" Identifier="3580456" >
                <SupplyDetails Type="TRACK" Quantity="7" Demand="ONHAND" />
    </Order>
    <Order InvOrg="Test" Identifier="3580457" >
                <SupplyDetails Type="TRACK" Quantity="15" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="3580458" >
                <SupplyDetails Type="TRACK" Quantity="17" Demand="ONHAND" />
    </Order>
</Second>
</First>
<First>
<Second Argument="12" Argument2="34" >
    <Order InvOrg="123" Identifier="3580459" >
                <SupplyDetails Type="TRACK" Quantity="10" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="2888144" >
                <SupplyDetails Type="TRACK" Quantity="3" Demand="ONHAND" />
    </Order>
    <Order InvOrg="123" Identifier="2888147" >
                <SupplyDetails Type="TRACK" Quantity="9" Demand="ONHAND" />
    <Order>
    <Order InvOrg="123" Identifier="2749622" >
                <SupplyDetails Type="TRACK" Quantity="142" Demand="ONHAND" />
    </Order>
</Second>
</First>

In xslt 2.0, It can be achieved with the below code..

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


<xsl:output method="xml" indent="yes"/>

<xsl:template match="/First">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="Second">
  <xsl:for-each-group select="Order" group-starting-with="Order[(position() -1)mod 3 = 0]">

    <First>
       <Second>
          <xsl:copy-of select="current-group()"/>
       </Second>
    </First>

  </xsl:for-each-group>
</xsl:template>

My project uses only xslt 1.0, so i need to change the above logic to 1.0. How can i implement the same logic in xslt 1.0

4
  • 2
    It seems that your XSLT 2.0 code organizes the blocks in groups of three, which would produce 3 blocks (the last one containing only one element), but your desired result above has 2 blocks (the second with 4 elements). Which of the two results are you expecting? Commented May 16, 2014 at 16:58
  • 1
    Note also that your requested output does not have a root element. Commented May 16, 2014 at 20:10
  • @helderdarocha - Result sample that i gave was not perfect but the xsl was. Commented May 20, 2014 at 8:27
  • @michael.hor257k- correct, Missed giving the root node but Marcus Rickert solution took care of that requirement as well. Commented May 20, 2014 at 8:29

1 Answer 1

1

The following XSLT uses a recursion to "iterate" over the orders and split of blocks of a configured size (e.g. 3).

<?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" />

  <!-- set the elements per block -->
  <xsl:param name="block_length" select="3"/>

  <!-- initialize the "iteration" over the Order elements by selecting all
       of them as the "child_list" -->
  <xsl:template match="/First">
    <root>
      <xsl:call-template name="split">
        <xsl:with-param name="child_list" select="Second/Order"/>
      </xsl:call-template>
    </root>
  </xsl:template>

  <!-- handle a list of orders, split off the first three and then "iterate" over
       the remaining orders by recursion -->
  <xsl:template name="split">
    <xsl:param name="child_list"/>


    <xsl:if test="count($child_list) &gt; 0">
      <!-- split off the first three -->
      <First>
        <Second>
          <xsl:copy-of select="$child_list[position() &lt;= $block_length]"/>
        </Second>
      </First>

      <!-- handle the remaining entries by recursion -->
      <xsl:call-template name="split">
        <xsl:with-param name="child_list" select="$child_list[position() > $block_length]"/>
      </xsl:call-template>
    </xsl:if>

  </xsl:template>

</xsl:stylesheet>

yielding this result

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <First>
    <Second>
      <Order InvOrg="123" Identifier="3580456">
        <SupplyDetails Type="TRACK" Quantity="7" Demand="ONHAND"/>
      </Order>
      <Order InvOrg="Test" Identifier="3580457">
        <SupplyDetails Type="TRACK" Quantity="15" Demand="ONHAND"/>
      </Order>
      <Order InvOrg="123" Identifier="3580458">
        <SupplyDetails Type="TRACK" Quantity="17" Demand="ONHAND"/>
      </Order>
    </Second>
  </First>
  <First>
    <Second>
      <Order InvOrg="123" Identifier="3580459">
        <SupplyDetails Type="TRACK" Quantity="10" Demand="ONHAND"/>
      </Order>
      <Order InvOrg="123" Identifier="2888144">
        <SupplyDetails Type="TRACK" Quantity="3" Demand="ONHAND"/>
      </Order>
      <Order InvOrg="123" Identifier="2888147">
        <SupplyDetails Type="TRACK" Quantity="9" Demand="ONHAND"/>
      </Order>
    </Second>
  </First>
  <First>
    <Second>
      <Order InvOrg="123" Identifier="2749622">
        <SupplyDetails Type="TRACK" Quantity="142" Demand="ONHAND"/>
      </Order>
    </Second>
  </First>
</root>

I would assume that this solution has a small portion with complexity O(n*n) with n being the initial number of orders so you may run into performance problems with huge order numbers.

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

1 Comment

The above logic perfectly works for my requirement. Thanks for the time and Effort.

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.