from elementtree.SimpleXMLWriter import XMLWriter from cStringIO import StringIO class _XmlElement(list): def __init__(self, tag): self.tag = tag self.text = None self.attrib = {} def __call__(self, text='', **kwargs): self.text = text self.attrib = kwargs return self def __repr__(self): return "<_XmlElement %s>" % self.tag def append(self, value): list.append(self, value) return value def __getattr__(self, value): if value == "add_comment": return self.append( _XmlComment() ) elif value == "add_text": return self.append( _XmlText() ) else: return self.append( _XmlElement(value) ) def _write(self, writer): #class is a keyword, so can't use it as an attribute name #use 'class_' then replace it here class_ = None for key in self.attrib.iterkeys(): if key == 'class_': class_ = self.attrib[key] del self.attrib[key] break if class_ is not None: self.attrib['class'] = class_ #now write this element if not self.__len__() and not self.text: writer.element( self.tag, None, self.attrib ) else: writer.start(self.tag, self.attrib) if self.text is not None: writer.data(self.text) #write any children if any for node in self: node._write(writer) writer.end() class _XmlText(_XmlElement): def __init__(self): self.text = '' def __call__(self, text=''): self.text = text return self def _write(self, writer): writer.data(self.text) for node in self: node._write(writer) def __repr__(self): return "<_XmlText>" class _XmlComment(_XmlText): def _write(self, writer): writer.comment(self.text) def __repr__(self): return "<_XmlComment>" class XmlFragment(_XmlElement): ''' >>> xml = XmlFragment() >>> root = xml.div() >>> print root <_XmlElement div> >>> print xml
>>> firstchild = root.p("Some text", id="1") >>> print xmlSome text
Some text
Some text
more text,
Some text
more text, and more.
Some text
more text, and more.