Basically, something similar to System.Xml.XmlWriter - A streaming XML Writer that doesn't incur much of a memory overhead. So that rules out xml.dom and xml.dom.minidom. Suggestions?
xml.etree.cElementTree, included in the default distribution of CPython since 2.5. Lightning fast for both reading and writing XML.
I've always had good results with lxml. It's a pain to install, as it's mostly a wrapper around libxml2, but lxml.etree
tree objects have a .write()
method that takes a file-like object to stream to.
from lxml.etree import XML
tree = XML('<root><a><b/></a></root>')
tree.write(your_file_object)
Some years ago I used MarkupWriter
from 4suite
General-purpose utility class for generating XML (may eventually be expanded to produce more output types) Sample usage: from Ft.Xml import MarkupWriter writer = MarkupWriter(indent=u"yes") writer.startDocument() writer.startElement(u'xsa') writer.startElement(u'vendor') #Element with simple text (#PCDATA) content writer.simpleElement(u'name', content=u'Centigrade systems') #Note writer.text(content) still works writer.simpleElement(u'email', content=u"[email protected]") writer.endElement(u'vendor') #Element with an attribute writer.startElement(u'product', attributes={u'id': u"100\u00B0"}) #Note writer.attribute(name, value, namespace=None) still works writer.simpleElement(u'name', content=u"100\u00B0 Server") #XML fragment writer.xmlFragment('<version>1.0</version><last-release>20030401</last-release>') #Empty element writer.simpleElement(u'changes') writer.endElement(u'product') writer.endElement(u'xsa') writer.endDocument() Note on the difference between 4Suite writers and printers Writer - module that exposes a broad public API for building output bit by bit Printer - module that simply takes a DOM and creates output from it as a whole, within one API invokation
Recently i hear a lot about how lxml is great, but I don't have first-hand experience, and I had some fun working with gnosis.
I think you'll find XMLGenerator from xml.sax.saxutils is the closest thing to what you want.
import time from xml.sax.saxutils import XMLGenerator from xml.sax.xmlreader import AttributesNSImpl LOG_LEVELS = ['DEBUG', 'WARNING', 'ERROR'] class xml_logger: def __init__(self, output, encoding): """ Set up a logger object, which takes SAX events and outputs an XML log file """ logger = XMLGenerator(output, encoding) logger.startDocument() attrs = AttributesNSImpl({}, {}) logger.startElementNS((None, u'log'), u'log', attrs) self._logger = logger self._output = output self._encoding = encoding return def write_entry(self, level, msg): """ Write a log entry to the logger level - the level of the entry msg - the text of the entry. Must be a Unicode object """ #Note: in a real application, I would use ISO 8601 for the date #asctime used here for simplicity now = time.asctime(time.localtime()) attr_vals = { (None, u'date'): now, (None, u'level'): LOG_LEVELS[level], } attr_qnames = { (None, u'date'): u'date', (None, u'level'): u'level', } attrs = AttributesNSImpl(attr_vals, attr_qnames) self._logger.startElementNS((None, u'entry'), u'entry', attrs) self._logger.characters(msg) self._logger.endElementNS((None, u'entry'), u'entry') return def close(self): """ Clean up the logger object """ self._logger.endElementNS((None, u'log'), u'log') self._logger.endDocument() return if __name__ == "__main__": #Test it out import sys xl = xml_logger(sys.stdout, 'utf-8') xl.write_entry(2, u"Vanilla log entry") xl.close()
You'll probably want to look at the rest of the article I got that from at http://www.xml.com/pub/a/2003/03/12/py-xml.html.
Second vote for ElementTree (cElementTree is a C implementation that is a little faster, like cPickle vs pickle). There's some short example code here that you can look at to give you an idea of how it works: http://effbot.org/zone/element-index.htm (this is Fredrik Lundh, who wrote the module in the first place. It's so good it got drafted into the standard library with 2.5 :-) )