cmlenz@1: # -*- coding: utf-8 -*- cmlenz@1: # cmlenz@1: # Copyright (C) 2006 Christopher Lenz cmlenz@1: # All rights reserved. cmlenz@1: # cmlenz@1: # This software is licensed as described in the file COPYING, which cmlenz@1: # you should have received as part of this distribution. The terms cmlenz@1: # are also available at http://trac.edgewall.com/license.html. cmlenz@1: # cmlenz@1: # This software consists of voluntary contributions made by many cmlenz@1: # individuals. For the exact contribution history, see the revision cmlenz@1: # history and logs, available at http://projects.edgewall.com/trac/. cmlenz@1: cmlenz@19: from markup.core import Attributes, Namespace, QName, Stream cmlenz@1: cmlenz@1: __all__ = ['Fragment', 'Element', 'tag'] cmlenz@1: cmlenz@1: cmlenz@1: class Fragment(object): cmlenz@1: __slots__ = ['children'] cmlenz@1: cmlenz@1: def __init__(self): cmlenz@1: self.children = [] cmlenz@1: cmlenz@1: def append(self, node): cmlenz@1: """Append an element or string as child node.""" cmlenz@1: if isinstance(node, (Element, basestring, int, float, long)): cmlenz@1: # For objects of a known/primitive type, we avoid the check for cmlenz@1: # whether it is iterable for better performance cmlenz@1: self.children.append(node) cmlenz@1: elif isinstance(node, Fragment): cmlenz@1: self.children += node.children cmlenz@1: elif node is not None: cmlenz@1: try: cmlenz@1: children = iter(node) cmlenz@1: except TypeError: cmlenz@1: self.children.append(node) cmlenz@1: else: cmlenz@1: for child in node: cmlenz@1: self.append(children) cmlenz@1: cmlenz@1: def __add__(self, other): cmlenz@1: return Fragment()(self, other) cmlenz@1: cmlenz@1: def __call__(self, *args): cmlenz@1: for arg in args: cmlenz@1: self.append(arg) cmlenz@1: return self cmlenz@1: cmlenz@1: def generate(self): cmlenz@1: """Generator that yield tags and text nodes as strings.""" cmlenz@1: def _generate(): cmlenz@1: for child in self.children: cmlenz@1: if isinstance(child, Fragment): cmlenz@1: for event in child.generate(): cmlenz@1: yield event cmlenz@1: else: cmlenz@17: yield Stream.TEXT, unicode(child), (-1, -1) cmlenz@1: return Stream(_generate()) cmlenz@1: cmlenz@1: def __iter__(self): cmlenz@1: return iter(self.generate()) cmlenz@1: cmlenz@1: def __str__(self): cmlenz@1: return str(self.generate()) cmlenz@1: cmlenz@1: def __unicode__(self): cmlenz@1: return unicode(self.generate()) cmlenz@1: cmlenz@1: cmlenz@1: class Element(Fragment): cmlenz@1: """Simple XML output generator based on the builder pattern. cmlenz@1: cmlenz@1: Construct XML elements by passing the tag name to the constructor: cmlenz@1: cmlenz@1: >>> print Element('strong') cmlenz@1: cmlenz@1: cmlenz@1: Attributes can be specified using keyword arguments. The values of the cmlenz@1: arguments will be converted to strings and any special XML characters cmlenz@1: escaped: cmlenz@1: cmlenz@1: >>> print Element('textarea', rows=10, cols=60) cmlenz@1: