 113924fb11
			
		
	
	
		113924fb11
		
	
	
	
	
		
			
			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)
 |