1

I want to sort parent node, based on child's name attribute.

XML unsorted:

<grand-parent>
  <parent>
    <child name="c"/>
    <child_next name="a"/>
  </parent>
  <parent>
    <child name="a"/>
    <child_next name="a"/>
  </parent>
  <parent>
    <child name="b"/>
    <child_next name="a"/>
  </parent>
</grand-parent>

Expected Output:

<grand-parent>
  <parent>
    <child name="a"/>
    <child_next name="a"/>
  </parent>
  <parent>
    <child name="b"/>
    <child_next name="a"/>
  </parent>
  <parent>
    <child name="c"/>
    <child_next name="a"/>
  </parent>
</grand-parent>

XSLT In Use (not working - returns the same XML that is input):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes" method="xml" encoding="UTF-8"/>
  <xsl:strip-space  elements="*"/>
  <xsl:template match="node()|@*" name="identity">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*">
        <xsl:sort select="/grand-parent/parent/child/@name" order="descending" />
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>  
</xsl:stylesheet>
Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
NiTiN
  • 1,022
  • 1
  • 16
  • 25
  • What is the actual (not working) output you are getting? "Not working" isn't a real description. That's probably why you were getting blocked by the quality filters. – Robert Harvey Jul 12 '12 at 19:20
  • http://stackoverflow.com/questions/7384434/sort-parent-nodes-xml-depends-on-child-nodes-values – zod Jul 12 '12 at 19:21
  • @RobertHarvey It returns exact same xml. (thats why I wrote "NoOp".) Thx! – NiTiN Jul 12 '12 at 19:23

1 Answers1

4

I would take the sort out of the identity transform:

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <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="grand-parent">
        <xsl:copy>
            <xsl:apply-templates select="parent|@*">
                <xsl:sort select="child/@name" data-type="text"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Output

<grand-parent>
   <parent>
      <child name="a"/>
      <child_next name="a"/>
   </parent>
   <parent>
      <child name="b"/>
      <child_next name="a"/>
   </parent>
   <parent>
      <child name="c"/>
      <child_next name="a"/>
   </parent>
</grand-parent>
Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
  • it works great, but I lose other elements if xml is : _ – NiTiN Jul 12 '12 at 19:37
  • @NiTiN - Try changing `` to ``. If you need everything else to appear either before or after the `` elements, you can add another `xsl:apply-templates`. If you want me to update the example, please let me know. – Daniel Haley Jul 12 '12 at 19:48
  • I tried with select="node()|@*", but it brought element below the parents. It would be great if you can modify your answer. Thanks! – NiTiN Jul 12 '12 at 21:25
  • 1
    @NiTiN - if the XML you showed us isn't representative of the real XML, then you need to go back and revise the question. Rejecting answers because you didn't give enough information isn't helpful, and can go on for ever. – Michael Kay Jul 12 '12 at 23:10
  • @NiTiN - Like Michael Kay pointed out, please update your XML with a more representative example of the real XML input and the expected output. The examples could end up changing a lot if there are "other" elements before/after the `` elements and if they need to stay in their original locations while only the `` elements are sorted. – Daniel Haley Jul 13 '12 at 04:03