1

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.

3
  • stackoverflow.com/questions/47096543/… Commented May 4, 2022 at 14:22
  • Thanks, that I found before. It's using attributes. I like to sort by {ProgramConfiguration/2.1}Description.text Commented May 4, 2022 at 14:37
  • Added my answer below. Commented May 4, 2022 at 20:04

1 Answer 1

0

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>
Sign up to request clarification or add additional context in comments.

1 Comment

@Dennis np, you can upvote the answer too if you whish.

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.