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 t开发者_如何学Pythono 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
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.
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
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>
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>
精彩评论