Python: How To Edit Element Of Xml File?
Solution 1:
Solution to replace part of an attribute (before update with new requirements):
import xml.etree.ElementTree as ETtree= ET.parse('example.xml')
for name in tree.getroot().iterfind('name'):
if name.attrib['search'].startswith('select ARG'):
name.attrib['search'] = name.attrib['search'].replace(
'select ARG', 'selected ARG')
tree.write('example.xml')
Solution to append new identical blocks with same replace on attribute as the above solution:
import xml.etree.ElementTree as ET
tree = ET.parse('example.xml')
for name in tree.getroot().iterfind('name'):
if name.attrib['search'].startswith('select ARG'):
new = ET.Element(name.tag)
new.attrib['search'] = name.attrib['search'].replace(
'select ARG', 'selected ARG')
tree.getroot().append(new)
for version in name.iterfind('version'):
new.append(version)
tree.write('example.xml')
From the ElementTree documentation:
parse(source, parser=None) Loads an external XML section into this element tree. source is a file name or file object. parser is an optional parser instance. If not given, the standard XMLParser parser is used. Returns the section root element.
getroot() Returns the root element for this tree.
iterfind(match) Finds all matching subelements, by tag name or path. Same as getroot().iterfind(match). Returns an iterable yielding all matching elements in document order.
attrib A dictionary containing the element’s attributes. Note that while the attrib value is always a real mutable Python dictionary, an ElementTree implementation may choose to use another internal representation, and create the dictionary only if someone asks for it. To take advantage of such implementations, use the dictionary methods below whenever possible.
class xml.etree.ElementTree.Element(tag, attrib={}, **extra) Element class. This class defines the Element interface, and provides a reference implementation of this interface.
The element name, attribute names, and attribute values can be either bytestrings or Unicode strings. tag is the element name. attrib is an optional dictionary, containing element attributes. extra contains additional attributes, given as keyword arguments.
append(subelement) Adds the element subelement to the end of this elements internal list of subelements
write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None, method="xml") Writes the element tree to a file, as XML. file is a file name, or a file object opened for writing. encoding [1] is the output encoding (default is US-ASCII). xml_declaration controls if an XML declaration should be added to the file. Use False for never, True for always, None for only if not US-ASCII or UTF-8 (default is None). default_namespace sets the default XML namespace (for “xmlns”). method is either "xml", "html" or "text" (default is "xml"). Returns an encoded string.
Solution 2:
The code below clone the requested elements and append them to the end of document.
55394530.xml is a file that contains the data taken from the example XML
import xml.etree.ElementTree as ET
import copy
from xml.dom import minidom
tree = ET.parse('55394530.xml')
names_to_duplicate = [e for e in tree.findall('.//name') if e.attrib.get('search').startswith('select ARG:')]
for name in names_to_duplicate:
clone = copy.deepcopy(name)
clone.attrib['search'] = clone.attrib['search'].replace('select', 'selected')
tree.getroot().append(clone)
xmlstr = minidom.parseString(ET.tostring(tree.getroot())).toprettyxml()
with open('out.xml', 'w') asout:
out.write(xmlstr)
Output
<element><namesearch="select ARG: 123"><versionid="1.1.1"><value>bla</value><method>blabla</method></version></name><namesearch="select ARG: 456"><versionid="1.1.1"><value>bla</value><method>blabla</method></version><versionid="1.1.1"><value>bla</value><method>blabla</method></version><versionid="1.1.1"><value>bla</value><method>blabla</method></version></name><namesearch="text ARG: 789"><versionid="1.1.1"><value>bla</value><method>blabla</method></version></name><namesearch="foo ARG: 444"><versionid="1.1.1"><value>bla</value><method>blabla</method></version></name><namesearch="test ARG: Cancel"><versionid="1.1.1"><value>bla</value><method>blabla</method></version></name><namesearch="selected ARG: 123"><versionid="1.1.1"><value>bla</value><method>blabla</method></version></name><namesearch="selected ARG: 456"><versionid="1.1.1"><value>bla</value><method>blabla</method></version><versionid="1.1.1"><value>bla</value><method>blabla</method></version><versionid="1.1.1"><value>bla</value><method>blabla</method></version></name></element>
Solution 3:
Using minidom, once you have the new elements, open the file in append mode a+
and write to it:
list.txt (before):
<projectversion="4"><namesearch="select ARG: write"><versionid="1.0.0"><value>myVal</value><method>myMethod</method></version></name><namesearch="select ARG: bla"><versionid="2.0.0"><value>myVal</value><method>myMethod</method></version></name></project>
Hence:
from xml.dom import minidom
xmldoc = minidom.parse('list_test.xml')
tags = xmldoc.getElementsByTagName("name")
for item in tags:
item.attributes["search"].value = item.attributes["search"].value.replace(
'select ARG', 'selected ARG')
withopen("list_test.xml", "a+") as f:
xmldoc.writexml(f)
list.txt (after):
<projectversion="4"><namesearch="select ARG: write"><versionid="1.0.0"><value>myVal</value><method>myMethod</method></version></name><namesearch="select ARG: bla"><versionid="2.0.0"><value>myVal</value><method>myMethod</method></version></name></project><?xml version="1.0" ?><projectversion="4"><namesearch="selected ARG: write"><versionid="1.0.0"><value>myVal</value><method>myMethod</method></version></name><namesearch="selected ARG: bla"><versionid="2.0.0"><value>myVal</value><method>myMethod</method></version></name></project>
Solution 4:
If you can use lxml, here's a solution that uses an XPath predicate to check the search
attribute value.
After selecting the correct name
element, it makes a copy and then updates the attribute value.
It then adds the new name
element after the original name
element.
XML Input (input.xml)
<projectversion="4"><namesearch="select ARG: write"><versionid="1.0.0"><value>myVal</value><method>myMethod</method></version></name><namesearch="select ARG: bla"><versionid="2.0.0"><value>myVal</value><method>myMethod</method></version></name></project>
Python
from lxml import etree
from copy import deepcopy
tree = etree.parse("input.xml")
for name in tree.xpath("//name[starts-with(@search,'select ARG')]"):
new_name = deepcopy(name)
new_name.attrib["search"] = name.get("search").replace("select ARG", "selected ARG")
name.addnext(new_name)
tree.write("output.xml")
XML Output (output.xml w/slight formatting changes for readability)
<projectversion="4"><namesearch="select ARG: write"><versionid="1.0.0"><value>myVal</value><method>myMethod</method></version></name><namesearch="selected ARG: write"><versionid="1.0.0"><value>myVal</value><method>myMethod</method></version></name><namesearch="select ARG: bla"><versionid="2.0.0"><value>myVal</value><method>myMethod</method></version></name><namesearch="selected ARG: bla"><versionid="2.0.0"><value>myVal</value><method>myMethod</method></version></name></project>
Post a Comment for "Python: How To Edit Element Of Xml File?"