0

I hope you are doing fine guys.

I am trying to sort the XML with a predefined order as a primary criteria and as a second criteria based on the "id" the XML file I am working on before exporting it. I am using "xml.etree.ElementTree", and I have added all the elements and subelements as it's required, the last portion I can't solve is the sorting.

The XML exported XML is as followed:

<List>
    <Level1>
        <LevelA id="zzz"/>
            <DO name="Info01"/>
        </LevelA >
        <LevelB id="ccc"/>
            <DO name="Info01"/>
        </LevelB>  
        <LevelA id="aaa"/>
            <DO name="Info01"/>
        </LevelA >
        <LevelC id="bbb"/>
            <DO name="Info01"/>
        </LevelC>
        <LevelA id="ddd"/>
            <DO name="Info01"/>
        </LevelA>   
        <LevelB id="aaa"/>
            <DO name="Info01"/>
        </LevelB>  
        <LevelC id="aaa"/>
            <DO name="Info01"/>
        </LevelC>         
    </Level1>
</List>

The defined order is:

predefined_order = [ 'LevelA', 'LevelB', 'LevelC']

Expected:

<List>
    <Level1>
        <LevelA id="aaa"/>
            <DO name="Info01"/>
        </LevelA >
        <LevelA id="ddd"/>
            <DO name="Info01"/>
        </LevelA>   
        <LevelA id="zzz"/>
            <DO name="Info01"/>
        </LevelA >
        <LevelB id="aaa"/>
            <DO name="Info01"/>
        </LevelB>  
        <LevelB id="ccc"/>
            <DO name="Info01"/>
        </LevelB> 
        <LevelC id="aaa"/>
            <DO name="Info01"/>
        </LevelC> 
        <LevelC id="bbb"/>
            <DO name="Info01"/>
        </LevelC>         
    </Level1>
</List>

Please help me giving me some clues.

Thanks

D

  • Attempt to solve your problem yourself before asking for help. Post your attempt and ask about where you're stuck. See [ask]. – kjhughes May 05 '22 at 03:10
  • Thanks a lot for the feedback kjhughes I will take those in consideration, I am new at programming and also asking in stackoverflow, tomorrow morning I will post my attempts, I’ve been trying for almost all the day hahaha, the maximum I did was to sort the attributes but not the subelements – DiegoSan1986 May 05 '22 at 03:48

1 Answers1

1

Try:

xml_doc = """
<List>
    <Level1>
        <LevelA id="zzz">
            <DO name="Info01"/>
        </LevelA>
        <LevelB id="ccc">
            <DO name="Info01"/>
        </LevelB>
        <LevelA id="aaa">
            <DO name="Info01"/>
        </LevelA>
        <LevelC id="bbb">
            <DO name="Info01"/>
        </LevelC>
        <LevelA id="ddd">
            <DO name="Info01"/>
        </LevelA>
        <LevelB id="aaa">
            <DO name="Info01"/>
        </LevelB>
        <LevelC id="aaa">
            <DO name="Info01"/>
        </LevelC>
    </Level1>
</List>
"""

from xml.etree.ElementTree import fromstring, tostring

myxml = fromstring(xml_doc)
predefined_order = ["LevelA", "LevelB", "LevelC"]

level1 = myxml.find(".//Level1")
level1[:] = sorted(
    level1,
    key=lambda child: (predefined_order.index(child.tag), child.get("id")),
)

print(tostring(myxml).decode("utf-8"))

Prints:

<List>
    <Level1>
        <LevelA id="aaa">
            <DO name="Info01" />
        </LevelA>
        <LevelA id="ddd">
            <DO name="Info01" />
        </LevelA>
        <LevelA id="zzz">
            <DO name="Info01" />
        </LevelA>
        <LevelB id="aaa">
            <DO name="Info01" />
        </LevelB>
        <LevelB id="ccc">
            <DO name="Info01" />
        </LevelB>
        <LevelC id="aaa">
            <DO name="Info01" />
        </LevelC>
    <LevelC id="bbb">
            <DO name="Info01" />
        </LevelC>
        </Level1>
</List>
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
  • Hello @Andrej. I am trying to understand the expression: level1[:] = sorted( level1, key=lambda child: (predefined_order.index(child.tag), child.get("id")), ) I googled the documentation of sort (https://docs.python.org/3/howto/sorting.html), and it is clear. And also now Lambdas are clear (https://docs.python.org/3/reference/expressions.html) But it is not clear to me the reason why we assign the value of the sorting to "level1[:]" Do you documentation or something that can help me to understand? Thanks a lot for your help. – DiegoSan1986 May 05 '22 at 12:09
  • @DiegoSan1986 `level1[:] = sorted(...)` means that *content* of `level1` is replaced with sorted tags. More info here: https://stackoverflow.com/questions/7677275/list-assignment-with – Andrej Kesely May 05 '22 at 12:30