Re: [xsl] copying complete document, but sort specific childnodes

Subject: Re: [xsl] copying complete document, but sort specific childnodes
From: Martin Honnen <Martin.Honnen@xxxxxx>
Date: Fri, 04 Sep 2009 14:52:51 +0200
Marc Harding | marcharding.de wrote:

my source document:

<document>
	<group id="group_abc123">
		<item id="123456" sort-order="2">
			<childitem id="bar">foo</childitem>
			<childitem id="text">1</childitem>
		</item>
		<item id="123456" sort-order="1">
			<childitem id="bar">foo</childitem>
			<childitem id="text">1</childitem>
		</item>	
		<item id="123456" sort-order="3">
			<childitem id="bar">foo</childitem>
			<childitem id="text">1</childitem>
		</item>
		<group id="group_def123">
			<item id="123456" sort-order="2">
				<childitem id="bar">foo</childitem>
				<childitem id="text">1</childitem>
			</item>
			<item id="123456" sort-order="1">
				<childitem id="bar">foo</childitem>
				<childitem id="text">1</childitem>
			</item>	
			<item id="123456" sort-order="3">
				<childitem id="bar">foo</childitem>
				<childitem id="text">1</childitem>
			</item>
			<item id="123456" sort-order="4">
				<childitem id="bar">foo</childitem>
				<childitem id="text">1</childitem>
			</item>
		</group>	
		<item id="123456" sort-order="4">
			<childitem id="bar">foo</childitem>
			<childitem id="text">1</childitem>
		</item>
	</group>
	<group id="group_abc456">
		<item id="123456" sort-order="2">
			<childitem id="bar">foo</childitem>
			<childitem id="text">1</childitem>
		</item>
		<item id="123456" sort-order="1">
			<childitem id="bar">foo</childitem>
			<childitem id="text">1</childitem>
		</item>	
		<item id="123456" sort-order="3">
			<childitem id="bar">foo</childitem>
			<childitem id="text">1</childitem>
		</item>
		<item id="123456" sort-order="4">
			<childitem id="bar">foo</childitem>
			<childitem id="text">1</childitem>
		</item>
	</group>
</document>

expected result:

<?xml version="1.0" encoding="UTF-8"?>
<document>
  <group id="group_abc123">
      <item id="123456" sort-order="1">
        <childitem id="bar">foo</childitem>
        <childitem id="text">1</childitem>
      </item>
      <item id="123456" sort-order="2">
        <childitem id="bar">foo</childitem>
        <childitem id="text">1</childitem>
      </item>
      <item id="123456" sort-order="3">
        <childitem id="bar">foo</childitem>
        <childitem id="text">1</childitem>
      </item>
      <group id="group_def123">
         <item id="123456" sort-order="1">
           <childitem id="bar">foo</childitem>
           <childitem id="text">1</childitem>
         </item>
         <item id="123456" sort-order="2">
           <childitem id="bar">foo</childitem>
           <childitem id="text">1</childitem>
         </item>
         <item id="123456" sort-order="3">
           <childitem id="bar">foo</childitem>
           <childitem id="text">1</childitem>
         </item>
         <item id="123456" sort-order="4">
           <childitem id="bar">foo</childitem>
           <childitem id="text">1</childitem>
         </item>
     </group>
      <item id="123456" sort-order="4">
        <childitem id="bar">foo</childitem>
        <childitem id="text">1</childitem>
      </item>
  </group>
  <group id="group_abc456">
    <item id="123456" sort-order="1">
      <childitem id="bar">foo</childitem>
      <childitem id="text">1</childitem>
    </item>
    <item id="123456" sort-order="2">
      <childitem id="bar">foo</childitem>
      <childitem id="text">1</childitem>
    </item>
    <item id="123456" sort-order="3">
      <childitem id="bar">foo</childitem>
      <childitem id="text">1</childitem>
    </item>
    <item id="123456" sort-order="4">
      <childitem id="bar">foo</childitem>
      <childitem id="text">1</childitem>
    </item>
  </group>
</document>

I realize you probably want an XSLT 1.0 solution as you posted an XSLT 1.0 stylesheet but as I am currently not sure there is a straightforward 1.0 solution here is an XSLT 2.0 solution:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  version="2.0">

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="group">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each-group select="*" group-adjacent="exists(@sort-order)">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <xsl:apply-templates select="current-group()">
              <xsl:sort select="@sort-order" data-type="number"/>
            </xsl:apply-templates>
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates select="current-group()"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

For above cited input it produces above cited output.


--


	Martin Honnen
	http://msmvps.com/blogs/martin_honnen/

Current Thread