2
votes

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

1
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?helderdarocha
Note also that your requested output does not have a root element.michael.hor257k
@helderdarocha - Result sample that i gave was not perfect but the xsl was.user3644942
@michael.hor257k- correct, Missed giving the root node but Marcus Rickert solution took care of that requirement as well.user3644942

1 Answers

1
votes

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.