
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1507 fd906abe-77d9-0310-91a1-e0d9ade77398
110 lines
2.9 KiB
Python
110 lines
2.9 KiB
Python
"""
|
|
Generation and manipulation of XML trees.
|
|
|
|
$Id$
|
|
"""
|
|
|
|
from cStringIO import StringIO
|
|
from lxml import etree
|
|
|
|
|
|
class Generator(object):
|
|
|
|
def __getitem__(self, name):
|
|
return Element(etree.Element(name))
|
|
|
|
def __getattr__(self, name):
|
|
return self[name]
|
|
|
|
elements = Generator()
|
|
|
|
|
|
class Element(object):
|
|
|
|
def __init__(self, baseElement):
|
|
self.baseElement = baseElement
|
|
|
|
@property
|
|
def __name__(self):
|
|
return self.baseElement.tag
|
|
|
|
@property
|
|
def children(self):
|
|
base = self.baseElement
|
|
result = []
|
|
if base.text:
|
|
result.append(base.text)
|
|
for c in base.getchildren():
|
|
result.append(Element(c))
|
|
if c.tail: # the children's tails belong to this element
|
|
result.append(c.tail)
|
|
return result
|
|
|
|
@property
|
|
def attributes(self):
|
|
return self.baseElement.attrib
|
|
|
|
def __getattr__(self, name):
|
|
if name.endswith('_'):
|
|
name = name[:-1]
|
|
return self[name]
|
|
|
|
def __getitem__(self, name):
|
|
elem = etree.Element(name)
|
|
self.baseElement.append(elem)
|
|
return Element(elem)
|
|
|
|
def __call__(self, *children, **attributes):
|
|
base = self.baseElement
|
|
for c in children:
|
|
if isinstance(c, Element):
|
|
base.append(c.baseElement)
|
|
elif not base: # no children yet, so it's the first text node
|
|
base.text = base.text and ' '.join((base.text, c)) or c
|
|
else: # if there are children, append text to the last child's tail
|
|
lastChild = base.getchildren()[-1]
|
|
lastChild.tail = lastChild.tail and ' '.join((lastChild.tail, c)) or c
|
|
for a in attributes:
|
|
if a.endswith('_'):
|
|
attr = a[:-1]
|
|
attributes[attr] = attributes[a]
|
|
del attributes[a]
|
|
for a in attributes:
|
|
base.attrib[a] = attributes[a]
|
|
return self
|
|
|
|
def render(self, level=0):
|
|
out = StringIO()
|
|
out.write(' ' * level)
|
|
out.write('<' + self.__name__)
|
|
for a in self.attributes:
|
|
attr = a
|
|
if attr.endswith('_'):
|
|
attr = attr[:-1]
|
|
out.write(' %s="%s"' % (attr, self.attributes[a]))
|
|
out.write('>\n')
|
|
for e in self.children:
|
|
if isinstance(e, Element):
|
|
out.write(e.render(level+1))
|
|
else:
|
|
out.write(' ' * (level+1))
|
|
out.write(e)
|
|
out.write('\n')
|
|
out.write(' ' * level)
|
|
out.write('</%s>' % self.__name__)
|
|
out.write('\n')
|
|
return out.getvalue()
|
|
|
|
def makeTree(self):
|
|
return etree.ElementTree(self.baseElement)
|
|
|
|
def renderTree(self):
|
|
out = StringIO()
|
|
tree = self.makeTree()
|
|
tree.write(out)
|
|
return out.getvalue()
|
|
|
|
|
|
def fromXML(xml):
|
|
elem = etree.XML(xml)
|
|
return Element(elem)
|