Pyjava
Pyjava

Reputation: 117

How to update existing xml element values and attributes?

I have input XML as country.xml:-

<root>
<set>
    <name>US</name>
    <stringval>New York</stringval>
</set>
<set>
    <name>UK</name>
    <integerval>12</integerval>
</set>
</root>

I am parsing xml and taking it into a list and i have a dictionary based on which I am comparing and adding xml elements.

diction: dict = {'US':'Chicago', 'UK':'London'}
source = etree.getroot()
for key,value in diction.items()
    countrylist = source.xpath('./set/name[text()=\'{}\']/..'.format(key))
    if len(countrylist) == 0:
        # creating new string and element
        # appending element to original tree
    elif len(countrylist) == 1:   ###This is problematic case what to expect here to update key,value from dictionary only and replace the tag already present in xml
        key = countrylist[0]
        e = ElementMarker()
        stringval = e.stringval
        integerval = e.integerval
        for element in source.findall('./set'):
            name = element.find('name')
            integervalue = element.find('integerval')
            stringvalue = element.find('stringval')
            if stringvalue is None:
                source.clear()
            for val in diction[name.text]:
                source.append(stringval(val))

    else:
        continue

    # writebacktoxml(source,"country.xml")

Output I am getting is original input condition as it is in output for specific condition. Expected output is below:-

<root>
<set>
    <name>US</name>
    <stringval>Chicago</stringval>
</set>
<set>
    <name>UK</name>
    <stringval>London</stringval>
</set>
</root>

Upvotes: 0

Views: 705

Answers (1)

Isma
Isma

Reputation: 15190

Perhaps you could duplicate the XML file and then modify it, also, I think it's better to iterate the XML once and compare against your dictionary rather than iterating your dictionary and reading the XML file every time (which can lead to performance issues), here is an example:

import xml.etree.ElementTree as ET

xml_file = 'c:/temp/input.xml'
xml_file_output = 'c:/temp/output.xml'
values = {'US': 'Chicago', 'UK': 'London'}

with open(xml_file, 'r') as fin:
    data = fin.read().splitlines(True)
with open(xml_file_output, 'w') as fout:
    fout.writelines(data)

tree = ET.parse(xml_file_output)
xml_root = tree.getroot()

for set in xml_root.iter("set"):
    country = set.find('name').text
    if country in values:
        value = values[set.find('name').text]

        integerval = set.find('integerval')
        if integerval is not None:
            set.remove(integerval)

        stringval = set.find('stringval')
        if stringval is not None:
            set.remove(stringval)

        stringval = ET.Element('stringval')
        stringval.text = value

        set.append(stringval)

tree.write(xml_file_output)

This is the output:

<configroot version="8.0">
    <set>
        <name>US</name>
        <stringval>Chicago</stringval>
    </set>
    <set>
        <name>UK</name>
        <stringval>London</stringval>
    </set>
</configroot>

Note that if the country name is not found in your dictionary the "set" entry will not be modified.

Upvotes: 2

Related Questions