I have an XML file then need to update some value. My XML file contains the comment. I would like to keep the comment after writing the XML, but it disappeared.
Here is my XML:
<?xml version="1.0" encoding="UTF-8"?> <!-- Data System --> <process> <!-- Student Name --> <NAME source="hsfg" class="hshah" property="Name"> <VALUE type="string"></VALUE> <VALUE type="None"></VALUE> </NAME> <!-- Exercise Number --> <number source="hsfg" class="hgdgf" property="gagfa"> <VALUE type="string"></VALUE> <VALUE type="None"></VALUE> </number> <!-- Exam ID --> <id source="hsfg" class="gfdg" property="fadg"> <VALUE type="string"></VALUE> <VALUE type="None"></VALUE> </id> </process>
This is the value that I need to update
<!-- Student Name --> <NAME source="hsfg" class="hshah" property="Name"> <VALUE type="string"></VALUE> <VALUE type="None"></VALUE> </NAME>
become this:
<!-- Student Name --> <NAME source="hsfg" class="hshah" property="Name"> <VALUE type="string">new value</VALUE> <VALUE type="None"></VALUE> </NAME>
My code:
read = ET.parse('test.xml').getroot() parent = read.find('.//NAME[@property="Name"]') change = parent.find('VALUE[@type="string"]') change.text = 'new value' tree = ET.ElementTree(read) tree.write("test.xml")
The output of the test.xml file become this. the comment and <?xml version="1.0" encoding="UTF-8"?>
dissapeared.
<process> <NAME source="hsfg" class="hshah" property="Name"> <VALUE type="string">new value</VALUE> <VALUE type="None" /> </NAME> <number source="hsfg" class="hgdgf" property="gagfa"> <VALUE type="string" /> <VALUE type="None" /> </number> <id source="hsfg" class="gfdg" property="fadg"> <VALUE type="string" /> <VALUE type="None" /> </id> </process>
BUT my expectation output, the structure and the comment still the same as before update the value like this:
<?xml version="1.0" encoding="UTF-8"?> <!-- Data System --> <process> <!-- Student Name --> <NAME source="hsfg" class="hshah" property="Name"> <VALUE type="string">new value</VALUE> <VALUE type="None"></VALUE> </NAME> <!-- Exercise Number --> <number source="hsfg" class="hgdgf" property="gagfa"> <VALUE type="string"></VALUE> <VALUE type="None"></VALUE> </number> <!-- Exam ID --> <id source="hsfg" class="gfdg" property="fadg"> <VALUE type="string"></VALUE> <VALUE type="None"></VALUE> </id> </process>
Advertisement
Answer
- Use
ET.XMLParser
to preserve comments - Use
encoding
andxml_declaration
arguments inwrite()
function to write xml declaration Try the following code:
import xml.etree.ElementTree as ET parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True)) read = ET.parse('newXml.xml', parser=parser).getroot() parent = read.find('.//NAME[@property="Name"]') change = parent.find('VALUE[@type="string"]') change.text = 'new value' tree = ET.ElementTree(read) tree.write("test.xml", encoding='utf-8', xml_declaration=True)
you can also avoid variable read
and just use tree
:
import xml.etree.ElementTree as ET parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True)) tree = ET.parse('newXml.xml', parser=parser) parent = tree.find('.//NAME[@property="Name"]') change = parent.find('VALUE[@type="string"]') change.text = 'new value' tree.write("test.xml", encoding='utf-8', xml_declaration=True)