Search code examples
pythonxmldatabaseloopsresx

How to edit an XML file in Python?


I have a resx file that uses XML with a bunch of data that looks like this:

<data name="key_first" xml:space="preserve">
    <value>Text 1</value>
</data>
<data name="key_second" xml:space="preserve">
    <value>Text 2</value>
</data>
<data name="key_third" xml:space="preserve">
    <value>Text 3</value>
</data>

where the name values all share a word (eg: "key"). What I wanted to do in Python was take this 'data' name value ("key+anything that follows") and add it to the 'value' text, and then save the new file but I'm very new to the XML/Python world and I'm kind of lost. I want it to look something like this:

<data name="key_first" xml:space="preserve">
    <value>[key_first] Text 1</value>
</data>
<data name="key_second" xml:space="preserve">
    <value>[key_second] Text 2</value>
</data>
<data name="key_third" xml:space="preserve">
    <value>[key_third] Text 3</value>
</data>

How do I do this? Should I use minidom or Element Tree?


Solution

  • Which XML parser to choose is up to you, but here is how you can approach this problem with xml.etree.ElementTree: the idea is to iterate over all data nodes, get the name attribute value from the .attrib dictionary, locate the value element inside and set the .text appropriately:

    import xml.etree.ElementTree as ET
    
    data = """<parent>
        <data name="key_first" xml:space="preserve">
            <value>Text 1</value>
        </data>
        <data name="key_second" xml:space="preserve">
            <value>Text 2</value>
        </data>
        <data name="key_third" xml:space="preserve">
            <value>Text 3</value>
        </data>
    </parent>"""
    
    tree = ET.fromstring(data)
    
    for data in tree.findall("data"):
        name = data.attrib["name"]
        value = data.find("value")
        value.text = "[%s] %s" % (name, value.text)
    
    print(ET.tostring(tree))
    

    Prints:

    <parent>
        <data name="key_first" xml:space="preserve">
            <value>[key_first] Text 1</value>
        </data>
        <data name="key_second" xml:space="preserve">
            <value>[key_second] Text 2</value>
        </data>
        <data name="key_third" xml:space="preserve">
            <value>[key_third] Text 3</value>
        </data>
    </parent>