Reputation: 117
I have input XML as country.xml:-
<root>
<set>
<name>Countries</name>
<elements>
<name>US</name>
<city>
<val>New York</val>
<val>Las Vegas</val>
</city>
</elements>
<elements>
<name>UK</name>
<city>
<val>London</val>
</city>
</elements>
</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':['New York', 'Chicago'], 'UK':['OXFORD', 'London']}
source = etree.getroot()
for key,value in diction.items()
countrylist = source.xpath('./elements/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]
else:
countinue
# 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>Countries</name>
<elements>
<name>US</name>
<city>
<val>New York</val>
<val>Chicago</val>
</city>
</elements>
<elements>
<name>UK</name>
<city>
<val>OXFORD</val>
<val>London</val>
</city>
</elements>
</set>
</root>
Upvotes: 1
Views: 648
Reputation: 15533
Comment: What if
diction:{'AUSTRALIA': ['MELBOURNE']}
? And I want to keep both the things from dictionary as well as from input xml into output xml?
Add a condition around .clear
if name.text in ['AUSTRALIA']:
# Keep the values
pass
else:
table_category.clear()
Question: How to update existing xml element with new given
<val>...</val>
?
Documentation: The lxml.etree Tutorial - The E-factory
Python Documentation -The ElementTree XML API - Modifying an XML File
Example using lxml
from lxml import etree
from lxml.builder import ElementMaker
Data dict
diction = {'US': ['New York', 'Chicago'], 'UK': ['OXFORD', 'London']}
Instantiate a ElementMaker
object and a new <val>...</val>
object.
E = ElementMaker()
VAL = E.val
Parse the source xml
tree = etree.parse(io.StringIO(xmlf))
root = tree.getroot()
Parse all set/elements
for element in root.findall('set/elements'):
Get the name
of this element
name = element.find('name')
Get the table_category
of this element
and .clear
it
table_category = element.find('table_category')
table_category.clear()
Loop all items from the list
in diction
defined for [name.text]
.
for val in diction[name.text]:
Append a new <val>val</val>
to table_category
table_category.append(VAL(val))
Output:
print('{}'.format(etree.tostring(root, pretty_print=True).decode()))
<configroot version="8.0"> <set> <name>Countries</name> <elements> <name>US</name> <table_category><val>New York</val><val>Chicago</val></table_category></elements> <elements> <name>UK</name> <table_category><val>OXFORD</val><val>London</val></table_category></elements> </set> </configroot>
Tested with Python: 3.5
Upvotes: 1