Search code examples
pythonxmlsortingexportxml.etree

sort with predifined order before exporting XML


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


Solution

  • 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>