2

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

2
  • 2
    Forgive my ignorance, but why do you want to sort your XML? Relying on the order of elements is unwise in my understanding of XML. Happy to be corrected though :) Commented Dec 17, 2009 at 8:43
  • 1
    @Tom Duckering: For displaying purposes i guess? Commented Dec 17, 2009 at 8:57

4 Answers 4

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Great response (overall) .. +1
1

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

Comments

1

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">
    <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>

Comments

0

You can use the YAML processor mikefarah/yq to sort XML.

Version < 4.30

yq --input-format xml --output-format xml '.books.book |= (sort_by(.+id) | .. | sort_keys(.))'

Version >= 4.30

yq --input-format xml --output-format xml '.books.book |= (sort_by(.+@id) | .. | sort_keys(.))'

sort_by(.+@id) sorts the array elements. sort_keys(.) sorts the keys inside every item.

Output

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.