tags:

views:

139

answers:

3
+2  Q: 

Sorting XML file

Hi,

I need to sort an XML by tag names and attribute. Is it possible using DOM?

I need the result in a sorted XML file not HTML.

for example:

<books>
 <book id='1'>
  <name value='N1'/>
  <author value='A1'/>
 </book>
 <book id='3'>
  <name value='N3'/>
  <author value='A3'/>
 </book>
 <book id='2'>
  <author value='A2'/>
  <name value='N2'/>
 </book>
</books>

I expect to get after sortXML ('id')

<books>
 <book id='1'>
  <author value='A1'/>
  <name value='N1'/>  
 </book>
 <book id='2'>
  <author value='A2'/>
  <name value='N2'/>
 </book>
 <book id='3'>
  <author value='A3'/>
  <name value='N3'/>  
 </book>
</books>

XML is sorted by tag names then by id

+3  A: 

You could write an XSL that sorts your data using the sort-element and transform you XML document with it, if your DOM implementation supports XSL Transformations.

Alternatively you could fetch all elements to an array and implement a sorting algorithm, e.g. bubble sort, to sort the elements of the array.

Or, if you are using the .Net DOM you could use a sorting XPath query. XPath does not support sorting by itself, but the .Net implementation provides the XPathExpression.AddSort method.

Vinz
Great response (overall) .. +1
infant programmer
A: 

Using java:

  • create a list of 'Element'
  • loop over all the elements 'book' under 'books' and add it to the list
  • detach all the 'book' from the parent 'books'
  • sort your list using a custom Comparator<Element>

    Comparator< Element > { int compareTo(Element a,Element b) { /* compare the values of a/author and b/author */ } }

  • loop over all the Element in your list and insert it back to 'books'

Using xslt:

see xsl:for-each and xsl:sort

Pierre
A: 

Just to add the xsl suggested by Vinz:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="books">
     <books>
      <xsl:apply-templates select="book">
       <xsl:sort select="@id" data-type="number" order="ascending" />
      </xsl:apply-templates>
     </books>
    </xsl:template>

    <xsl:template match="book">
     <book>
      <xsl:attribute name="id">
       <xsl:value-of select="@id"/>
      </xsl:attribute>
      <xsl:apply-templates>
       <xsl:sort select="local-name()" data-type="text" order="ascending" />
      </xsl:apply-templates>
     </book>
    </xsl:template>

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