Reputation: 166
I am trying to sort the xml based on code in the field tag.
Below is the code implementation I tried but it is printing only one field
Sorting should be mainly done on code attribute
import xml.etree.ElementTree as ET
xmlData = '''<data>
<values>
<field code="6">rst</field>
<show>qwerty6</show>
<chip/>
<normal/>
</values>
<values>
<field code="5">opq</field>
<show>qwerty5</show>
<chip/>
<normal/>
</values>
<values>
<field code="4">klm</field>
<show>qwerty4</show>
</values>
<values>
<field code="3">hij</field>
<show>qwerty3</show>
<chip/>
<normal/>
</values>
<values>
<field code="2">efg</field>
<show>qwerty2</show>
<chip/>
<normal/>
</values>
<values>
<field code="1">abc</field>
<show>qwerty1</show>
</values>
</data>'''
tree = ET.fromstring(xmlData)
myvalues = tree.find('values')
for el in myvalues:
el[:] = sorted(el, key=lambda e: (e.tag, e.attrib['code']))
tree[:] = myvalues
xmlstr = ET.tostring(tree, encoding="utf-8", method="xml")
print(xmlstr.decode("utf-8"))
Upvotes: 1
Views: 276
Reputation: 5237
You can remove the redundant loop and pass myvalues
directly to sorted
. When you call sorted
, it will iterate over data
Element
.
The lambda
should look like this:
lambda value: value[0].get("code")
which will get the first child (field
) from the values
and return the code
to use as a sorting key.
Then, you can just regenerate the XML from myvalues
directly - there's no need to assign anything back to tree
.
The following should work for you:
import xml.etree.ElementTree as ET
xmlData = """
<data>
<values>
<field code="6">rst</field>
<show>qwerty6</show>
<chip/>
<normal/>
</values>
<values>
<field code="5">opq</field>
<show>qwerty5</show>
<chip/>
<normal/>
</values>
<values>
<field code="4">klm</field>
<show>qwerty4</show>
</values>
<values>
<field code="3">hij</field>
<show>qwerty3</show>
<chip/>
<normal/>
</values>
<values>
<field code="2">efg</field>
<show>qwerty2</show>
<chip/>
<normal/>
</values>
<values>
<field code="1">abc</field>
<show>qwerty1</show>
</values>
</data>
"""
tree = ET.ElementTree(ET.fromstring(xmlData))
myvalues = tree.getroot()
myvalues[:] = sorted(myvalues, key=lambda value: value[0].get("code"))
xmlstr = ET.tostring(myvalues, encoding="utf-8", method="xml")
print(xmlstr.decode("utf-8"))
Which gives the output:
<data>
<values>
<field code="1">abc</field>
<show>qwerty1</show>
</values>
<values>
<field code="2">efg</field>
<show>qwerty2</show>
<chip />
<normal />
</values>
<values>
<field code="3">hij</field>
<show>qwerty3</show>
<chip />
<normal />
</values>
<values>
<field code="4">klm</field>
<show>qwerty4</show>
</values>
<values>
<field code="5">opq</field>
<show>qwerty5</show>
<chip />
<normal />
</values>
<values>
<field code="6">rst</field>
<show>qwerty6</show>
<chip />
<normal />
</values>
</data>
Upvotes: 1