Created
September 8, 2011 14:09
-
-
Save simon-engledew/1203486 to your computer and use it in GitHub Desktop.
Python magic to concisely generate XML
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import xml.dom.minidom as xml | |
class Document(object): | |
""" | |
XML Document Builder | |
@author Simon Engledew | |
example: | |
dom = Document.catalog(version="1.0") | |
dom.book( | |
dom.name("The Pragmatic Programmer"), | |
dom.author("Andrew Hunt and David Thomas"), | |
dom['publish-date']("20 Oct 1999"), | |
id="1" | |
) | |
print str(dom) | |
output: | |
<?xml version="1.0" encoding="utf-8"?> | |
<catalog version="1.0"> | |
<book id="1"> | |
<name>The Pragmatic Programmer</name> | |
<author>Andrew Hunt and David Thomas</author> | |
<publish_date>20 Oct 1999</publish_date> | |
</book> | |
</catalog> | |
""" | |
class MetaClass(type): | |
def __getattr__(self, tagname, *args, **attributes): | |
return lambda *args, **attributes: Document(tagname, *args, **attributes) | |
def __dir__(self): | |
return ['__getitem__', '__getattr__', '__str__', '__unicode__', '__root__'] | |
__metaclass__=MetaClass | |
class Element(object): | |
def __init__(self, document, tagname): | |
self.__document__ = document | |
self.__document__.start_element(tagname) | |
def element(self, *args, **attributes): | |
for value in (o for o in args if o is not None): | |
if not isinstance(value, Document.Element): | |
self.__document__.append_text_node(unicode(value)) | |
self.__document__.append_attributes(attributes) | |
self.__document__.end_element() | |
return self | |
@property | |
def __root__(self): | |
return self.__stack__[-1] | |
def start_element(self, tagname): | |
element = self.__dom__.createElement(tagname) | |
self.__root__.appendChild(element) | |
self.__stack__.append(element) | |
return element | |
def append_attributes(self, attributes): | |
for key, value in attributes.items(): | |
self.__root__.setAttribute(key, unicode(value)) | |
def append_text_node(self, value): | |
self.__root__.appendChild(self.__dom__.createTextNode(unicode(value))) | |
def end_element(self): | |
self.__stack__.pop() | |
def __init__(self, tagname, *args, **attributes): | |
self.__dom__ = xml.getDOMImplementation().createDocument(None, tagname, None) | |
self.__stack__ = [] | |
self.__stack__.append(self.__dom__.documentElement) | |
self.append_attributes(attributes) | |
for value in (o for o in args if o is not None): | |
if not isinstance(value, Document.Element): | |
self.append_text_node(unicode(value)) | |
def __getitem__(self, tagname): | |
return self.__getattr__(tagname) | |
def __getattr__(self, tagname): | |
return Document.Element(self, tagname).element | |
def __str__(self, encoding='utf-8'): | |
return self.__dom__.toxml(encoding=encoding) | |
def __unicode__(self, encoding='utf-8'): | |
return self.__str__(encoding).decode(encoding) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment