Home > Mobile >  XML sorting with Python
XML sorting with Python

Time:05-06

I'm new in Python and I need some help. I try to rearrange an xml by using LXML sorting the "Rule"-Tags by the "Description". I can address the DescriptionTags by using:

for elem in root.iter('{http://www.ProgramConfiguration/2.1}Description'):
print(elem.text)

But I can't use it for sorting.

I want to transform this:

<?xml version="1.0" encoding="utf-8"?>
<ProgramConfiguration xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ProgramConfiguration/2.1">
  <Rules>
    <Rule RuleId="1" Enabled="true">
      <Description>Muster, Alex</Description>.
     <WatchDirectories>
        <WatchDirectory Path="\\server201...." WatchSubDirs="false" />
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
    <Rule RuleId="2" Enabled="true">
      <Description>Albert, Peter</Description>
      <WatchDirectories>
        <WatchDirectory Path="\\server201...." WatchSubDirs="false" />
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
    <Rule RuleId="3" Enabled="true">
      <Description>Rich, Sam</Description>
      <WatchDirectories>
        <WatchDirectory Path="\\server201...." WatchSubDirs="false" />
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
    <Rule RuleId="4" Enabled="true">
      <Description>Albert, Zack</Description>
      <WatchDirectories>
        <WatchDirectory Path="\\server201...." WatchSubDirs="false" />
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
  </Rules>
</ProgramConfiguration>

Into this:

<?xml version="1.0" encoding="utf-8"?>
<ProgramConfiguration xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ProgramConfiguration/2.1">
  <Rules>
    <Rule RuleId="2" Enabled="true">
      <Description>Albert, Peter</Description>
      <WatchDirectories>
        <WatchDirectory Path="\\server201...." WatchSubDirs="false" />
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
    <Rule RuleId="4" Enabled="true">
      <Description>Albert, Zack</Description>
      <WatchDirectories>
        <WatchDirectory Path="\\server201...." WatchSubDirs="false" />
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
    <Rule RuleId="1" Enabled="true">
      <Description>Muster, Alex</Description>
      <WatchDirectories>
        <WatchDirectory Path="\\server201...." WatchSubDirs="false" />
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
    <Rule RuleId="3" Enabled="true">
      <Description>Rich, Sam</Description>
      <WatchDirectories>
        <WatchDirectory Path="\\server201...." WatchSubDirs="false" />
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
  </Rules>
</ProgramConfiguration>

I much appreciate any help.

Dennis

Unfortunatally I can't explain more but I have to add some more details to my post then code. So I have to write some more words even I don't want this only to fill space in this. Wow I have to write a lot additional stuff to submite this question. Sorry for that, but my code example is as long as it is. so sorry again.

CodePudding user response:

Using lxml package to sort by element text

from lxml import etree
from io import BytesIO
xml_obj = BytesIO(xmlstr)

root = etree.parse(xml_obj).getroot()

# keys list before sorting
print(root.xpath('.//x:Rule/x:Description/text()', namespaces={'x': 'http://www.ProgramConfiguration/2.1'}))

for c in root.xpath('/x:ProgramConfiguration/x:Rules', namespaces={'x': 'http://www.ProgramConfiguration/2.1'}):
    c[:] = sorted(c, key=lambda child: (child.xpath('.//x:Description/text()', namespaces={'x': 'http://www.ProgramConfiguration/2.1'})))

# keys list after sorting
print(root.xpath('.//x:Rule/x:Description/text()', namespaces={'x': 'http://www.ProgramConfiguration/2.1'}))

xmlstr = etree.tostring(root, encoding="utf-8", method="xml")
print(xmlstr.decode("utf-8"))

Result:

['Muster, Alex', 'Albert, Peter', 'Rich, Sam', 'Albert, Zack']
['Albert, Peter', 'Albert, Zack', 'Muster, Alex', 'Rich, Sam']
<ProgramConfiguration xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ProgramConfiguration/2.1">
  <Rules>
    <Rule RuleId="2" Enabled="true">
      <Description>Albert, Peter</Description>
      <WatchDirectories>
        <WatchDirectory Path="\server201...." WatchSubDirs="false"/>
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
    <Rule RuleId="4" Enabled="true">
      <Description>Albert, Zack</Description>
      <WatchDirectories>
        <WatchDirectory Path="\server201...." WatchSubDirs="false"/>
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
  <Rule RuleId="1" Enabled="true">
      <Description>Muster, Alex</Description>.
     <WatchDirectories>
        <WatchDirectory Path="\server201...." WatchSubDirs="false"/>
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
    <Rule RuleId="3" Enabled="true">
      <Description>Rich, Sam</Description>
      <WatchDirectories>
        <WatchDirectory Path="\server201...." WatchSubDirs="false"/>
      </WatchDirectories>
      <Actions>
        .
        .
        .
      </Actions>
    </Rule>
    </Rules>
</ProgramConfiguration>
  • Related