With ET.tostring(tree) you get a non-formatted string representation of the XML. To save it to a file:
with open("filename", "w") as f:
f.write(ET.tostring(tree))
Answer from Antti on Stack OverflowWith ET.tostring(tree) you get a non-formatted string representation of the XML. To save it to a file:
with open("filename", "w") as f:
f.write(ET.tostring(tree))
In python 3.x
The proposed solution won't work unless you specify with open("filename", "wb") as f: instead of with open("filename", "w") as f:
Creating a simple XML file using python - Stack Overflow
Python writing to an xml file - Stack Overflow
How to save an XML file to disk with python? - Stack Overflow
How to create XML file using Python? - Stack Overflow
Videos
These days, the most popular (and very simple) option is the ElementTree API, which has been included in the standard library since Python 2.5.
The available options for that are:
- ElementTree (Basic, pure-Python implementation of ElementTree. Part of the standard library since 2.5)
- cElementTree (Optimized C implementation of ElementTree. Also offered in the standard library since 2.5. Deprecated and folded into the regular ElementTree as an automatic thing as of 3.3.)
- LXML (Based on libxml2. Offers a rich superset of the ElementTree API as well XPath, CSS Selectors, and more)
Here's an example of how to generate your example document using the in-stdlib cElementTree:
import xml.etree.cElementTree as ET
root = ET.Element("root")
doc = ET.SubElement(root, "doc")
ET.SubElement(doc, "field1", name="blah").text = "some value1"
ET.SubElement(doc, "field2", name="asdfasd").text = "some vlaue2"
tree = ET.ElementTree(root)
tree.write("filename.xml")
I've tested it and it works, but I'm assuming whitespace isn't significant. If you need "prettyprint" indentation, let me know and I'll look up how to do that. (It may be an LXML-specific option. I don't use the stdlib implementation much)
For further reading, here are some useful links:
- API docs for the implementation in the Python standard library
- Introductory Tutorial (From the original author's site)
- LXML etree tutorial. (With example code for loading the best available option from all major ElementTree implementations)
As a final note, either cElementTree or LXML should be fast enough for all your needs (both are optimized C code), but in the event you're in a situation where you need to squeeze out every last bit of performance, the benchmarks on the LXML site indicate that:
- LXML clearly wins for serializing (generating) XML
- As a side-effect of implementing proper parent traversal, LXML is a bit slower than cElementTree for parsing.
The lxml library includes a very convenient syntax for XML generation, called the E-factory. Here's how I'd make the example you give:
#!/usr/bin/python
import lxml.etree
import lxml.builder
E = lxml.builder.ElementMaker()
ROOT = E.root
DOC = E.doc
FIELD1 = E.field1
FIELD2 = E.field2
the_doc = ROOT(
DOC(
FIELD1('some value1', name='blah'),
FIELD2('some value2', name='asdfasd'),
)
)
print lxml.etree.tostring(the_doc, pretty_print=True)
Output:
<root>
<doc>
<field1 name="blah">some value1</field1>
<field2 name="asdfasd">some value2</field2>
</doc>
</root>
It also supports adding to an already-made node, e.g. after the above you could say
the_doc.append(FIELD2('another value again', name='hithere'))
If you are wanting to replace a value within an existing XML file then use:
tree.write(xmlfile)
Currently you are simply overwriting your file entirely and using the incorrect method (open()). tree.write() is normally what you would want to use. It might look something like this:
tree = etree.parse(xmlfile, parser=XMLParser)
root = tree.getroot()
hardwareRevisionNode = root.find(".//hardwareRevision")
if hardwareRevisionNode.text == "5":
print "Old Tag: " + hardwareRevisionNode.text
hardwareRevisionNode.text = "DVT2"
print "New Tag: " + hardwareRevisionNode.text
tree.write(xmlfile)
↳ https://docs.python.org/2/library/xml.etree.elementtree.html
To get newlines in the output file, it looks like you need to pass pretty_print=True to your sterilization (write or tostring) call.
Side note; Normally, when you open files with python you open them like this:
with open('filename.ext', 'mode') as myfile:
myfile.write(mydata)
This way there is less risk of file descriptor leaks. The tree.write("filename.xml") method looks like a nice and easy way to avoid dealing with the file entirely.
You probably want to use Node.writexml() on the root node of your XML DOM tree. This will write your root element and all child elements to an XML file, doing all the becessary indenting etc. along the way.
See the documentation for xml.dom.minidom:
Node.writexml(writer[, indent=""[, addindent=""[, newl=""]]])Write XML to the writer object. The writer should have a
write()method which matches that of the file object interface. Theindentparameter is the indentation of the current node. Theaddindentparameter is the incremental indentation to use for subnodes of the current one. Thenewlparameter specifies the string to use to terminate newlines.For the Document node, an additional keyword argument encoding can be used to specify the encoding field of the XML header.
Changed in version 2.1: The optional keyword parameters indent, addindent, and newl were added to support pretty output.
Changed in version 2.3: For the Document node, an additional keyword argument encoding can be used to specify the encoding field of the XML header.
Usage will be somewhat like:
file_handle = open("filename.xml","wb")
Your_Root_Node.writexml(file_handle)
file_handle.close()
Read about python files, if you xml as string you can just write it to a file e.g.
xml = "<myxmldata/>"
f = open("myxmlfile.xml", "wb")
f.write(xml)
f.close()
To obtain xml string from minidom nodes you can either use
xml = Node.toxml()
or you can directly write to a object which supports write e.g. a file
Node.writexml(f)