."),
+ ET.XML("And finally, here is an embedded XHTML fragment.
"),
+ )
+ )
+ )
+
+ print ET.tostring(page)
+
+ Here's a prettyprinted version of the output from the above script::
+
+
+
+ This is a sample document
+
+
+ Hello!
+ This is a paragraph with bold text in it!
+ This is another paragraph, with link.
+ Here are some reserved characters: <spam&egg>.
+ And finally, here is an embedded XHTML fragment.
+
+
+
+ For namespace support, you can pass a namespace map (``nsmap``)
+ and/or a specific target ``namespace`` to the ElementMaker class::
+
+ >>> E = ElementMaker(namespace="http://my.ns/")
+ >>> print(ET.tostring( E.test ))
+
+
+ >>> E = ElementMaker(namespace="http://my.ns/", nsmap={'p':'http://my.ns/'})
+ >>> print(ET.tostring( E.test ))
+
+ """
+
+ def __init__(self, typemap=None,
+ namespace=None, nsmap=None, makeelement=None):
+ self._namespace = '{' + namespace + '}' if namespace is not None else None
+ self._nsmap = dict(nsmap) if nsmap else None
+
+ assert makeelement is None or callable(makeelement)
+ self._makeelement = makeelement if makeelement is not None else ET.Element
+
+ # initialize the default type map functions for this element factory
+ typemap = dict(typemap) if typemap else {}
+
+ def add_text(elem, item):
+ try:
+ last_child = elem[-1]
+ except IndexError:
+ elem.text = (elem.text or "") + item
+ else:
+ last_child.tail = (last_child.tail or "") + item
+
+ def add_cdata(elem, cdata):
+ if elem.text:
+ raise ValueError("Can't add a CDATA section. Element already has some text: %r" % elem.text)
+ elem.text = cdata
+
+ if str not in typemap:
+ typemap[str] = add_text
+ if unicode not in typemap:
+ typemap[unicode] = add_text
+ if ET.CDATA not in typemap:
+ typemap[ET.CDATA] = add_cdata
+
+ def add_dict(elem, item):
+ attrib = elem.attrib
+ for k, v in item.items():
+ if isinstance(v, basestring):
+ attrib[k] = v
+ else:
+ attrib[k] = typemap[type(v)](None, v)
+
+ if dict not in typemap:
+ typemap[dict] = add_dict
+
+ self._typemap = typemap
+
+ def __call__(self, tag, *children, **attrib):
+ typemap = self._typemap
+
+ # We'll usually get a 'str', and the compiled type check is very fast.
+ if not isinstance(tag, str) and isinstance(tag, _QName):
+ # A QName is explicitly qualified, do not look at self._namespace.
+ tag = tag.text
+ elif self._namespace is not None and tag[0] != '{':
+ tag = self._namespace + tag
+ elem = self._makeelement(tag, nsmap=self._nsmap)
+ if attrib:
+ typemap[dict](elem, attrib)
+
+ for item in children:
+ if callable(item):
+ item = item()
+ t = typemap.get(type(item))
+ if t is None:
+ if ET.iselement(item):
+ elem.append(item)
+ continue
+ for basetype in type(item).__mro__:
+ # See if the typemap knows of any of this type's bases.
+ t = typemap.get(basetype)
+ if t is not None:
+ break
+ else:
+ raise TypeError("bad argument type: %s(%r)" %
+ (type(item).__name__, item))
+ v = t(elem, item)
+ if v:
+ typemap.get(type(v))(elem, v)
+
+ return elem
+
+ def __getattr__(self, tag):
+ return partial(self, tag)
+
+
+# create factory object
+E = ElementMaker()
--
cgit v1.2.3