Re: [xsl] rearranging nodes using XSLT

Subject: Re: [xsl] rearranging nodes using XSLT
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Wed, 17 Feb 2010 12:15:41 -0500
At 2010-02-17 10:32 -0600, a kusa wrote:
How can I rearrange nodes in xslt?

Remember you are creating a new arrangement of nodes, you are not rearranging the old nodes.


My source XML looks something like this: I am trying to rearrance
tbd1, tbd2, tbd3 in that order

Then simply process them in that order where you find them grouped. I hope the answer below helps. It creates the structure you cite as your desired output.


. . . . . . . . . . . Ken

T:\ftemp>type akusa.xml
<root>
  <list1>
    <item1>
      <para>sample</para>
    </item1>
    <tbd2><para>test1</para></tbd2>
    <tbd1><para>test1</para></tbd1>
    <list2>
      <item1>
        <para>sample</para>
      </item1>
      <tbd3><para>test1</para></tbd3>
      <tbd1><para>test1</para></tbd1>
      <item1>
        <para>sample</para>
      </item1>
    </list2>
  </list1>
</root>

T:\ftemp>call xslt2 akusa.xml akusa.xsl
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <list1>
      <item1>
         <para>sample</para>
      </item1>
      <tbd1>
         <para>test1</para>
      </tbd1>
      <tbd2>
         <para>test1</para>
      </tbd2>
      <list2>
         <item1>
            <para>sample</para>
         </item1>
         <tbd1>
            <para>test1</para>
         </tbd1>
         <tbd3>
            <para>test1</para>
         </tbd3>
         <item1>
            <para>sample</para>
         </item1>
      </list2>
   </list1>
</root>
T:\ftemp>type akusa.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="2.0">

<xsl:output indent="yes"/>

<xsl:template match="*[tbd1|tbd2|tbd3]">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>

<!--find each group of elements in which a sequence of target elements
are found-->
<xsl:for-each-group select="*"
group-starting-with="*[not(self::tbd1 | self::tbd2 |
self::tbd3 )]">
<!--first put out all of those that are not in the group, then put out
the group of target elements in the desired order-->
<xsl:apply-templates select="current-group()
[not(self::tbd1 | self::tbd2 | self::tbd3 )],
current-group()[self::tbd1],
current-group()[self::tbd2],
current-group()[self::tbd3]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>


<xsl:template match="@*|node()"><!--identity for all other nodes-->
  <xsl:copy>
    <xsl:apply-templates select="@*,node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>


<root>
<list1>
<item1>
<para>sample</para>
</item1>
<tbd2><para>test1</tbd2>
<tbd1><para>test1</tbd1>
<list2>
<item1>
<para>sample</para>
</item1>
<tbd3><para>test1</tbd3>
<tbd1><para>test1</tbd1>
<item1>
<para>sample</para>
</item1>
</list2>
</list1>
</root>

My desired output:

<root>
<list1>
<item1>
<para>sample</para>
</item1>
<tbd1><para>test1</tbd1>
<tbd2><para>test1</tbd2>
<list2>
<item1>
<para>sample</para>
</item1>

<tbd1><para>test1</tbd1>
<tbd3><para>test1</tbd3>
<item1>
<para>sample</para>
</item1>
</list2>
</list1>
</root>

Thanks in advance for your help.


--
XSLT/XQuery/XPath training after http://XMLPrague.cz 2010-03-15/19
XSLT/XQuery/XPath training:   San Carlos, California 2010-04-26/30
Vote for your XML training:   http://www.CraneSoftwrights.com/s/i/
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
Video lesson:    http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18
Video overview:  http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18
G. Ken Holman                 mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Male Cancer Awareness Nov'07  http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers:  http://www.CraneSoftwrights.com/legal

Current Thread