[Checkins] SVN: Sandbox/malthe/chameleon.core/ Support template fragments, e.g. documents with more than one root element.
Malthe Borch
mborch at gmail.com
Tue Dec 2 09:53:27 EST 2008
Log message for revision 93545:
Support template fragments, e.g. documents with more than one root element.
Changed:
U Sandbox/malthe/chameleon.core/CHANGES.txt
U Sandbox/malthe/chameleon.core/src/chameleon/core/etree.py
U Sandbox/malthe/chameleon.core/src/chameleon/core/template.txt
-=-
Modified: Sandbox/malthe/chameleon.core/CHANGES.txt
===================================================================
--- Sandbox/malthe/chameleon.core/CHANGES.txt 2008-12-02 14:12:21 UTC (rev 93544)
+++ Sandbox/malthe/chameleon.core/CHANGES.txt 2008-12-02 14:53:27 UTC (rev 93545)
@@ -4,6 +4,9 @@
HEAD
~~~~
+- Support template fragments, e.g. documents with more than one
+ root element. [malthe]
+
- Added namespace prefix 'xml' to default namespace mapping. [malthe]
- Fixed root cause of issue with self-closing tags; an empty element
Modified: Sandbox/malthe/chameleon.core/src/chameleon/core/etree.py
===================================================================
--- Sandbox/malthe/chameleon.core/src/chameleon/core/etree.py 2008-12-02 14:12:21 UTC (rev 93544)
+++ Sandbox/malthe/chameleon.core/src/chameleon/core/etree.py 2008-12-02 14:53:27 UTC (rev 93545)
@@ -46,7 +46,8 @@
element with trivial body text as self-closing."""
root = None
-
+ index = None
+
# doctype
doctype = None
@@ -54,7 +55,7 @@
xml_version = None
encoding = None
standalone = None
-
+
def __init__(self, parser, body, expat):
self.parser = parser
self.body = body
@@ -63,6 +64,7 @@
def StartElementHandler(self, tag, attrs):
# update prefix to namespace mapping
if self.root is None:
+ self.index = self.expat.CurrentByteIndex
nsmap = {}
else:
nsmap = self.root.nsmap.copy()
@@ -243,26 +245,64 @@
parser = lxml.etree.XMLParser(resolve_entities=False, strip_cdata=False)
parser.setElementClassLookup(lookup)
- # set up expat parser
- expat = xml.parsers.expat.ParserCreate(None)
- expat.UseForeignDTD()
- expat.SetParamEntityParsing(
- xml.parsers.expat.XML_PARAM_ENTITY_PARSING_ALWAYS)
+ junk = ""
+ tree = None
+ parts = []
+ while tree is None:
+ # set up expat parser
+ expat = xml.parsers.expat.ParserCreate(None)
+ expat.UseForeignDTD()
+ expat.SetParamEntityParsing(
+ xml.parsers.expat.XML_PARAM_ENTITY_PARSING_ALWAYS)
- # attach expat parser methods
- parser = ExpatParser(parser, body, expat)
- for name in type(parser).__dict__.keys():
+ # attach expat parser methods
+ expatparser = ExpatParser(parser, body, expat)
+ for name in type(expatparser).__dict__.keys():
+ try:
+ setattr(expat, name, getattr(expatparser, name))
+ except AttributeError:
+ pass
+
try:
- setattr(expat, name, getattr(parser, name))
- except AttributeError:
- pass
+ # attempt to parse this body; if we're not successful,
+ # this may be because the document source consists of
+ # several 'parts'; although this is not valid XML, we do
+ # support it, being a template engine, not a XML
+ # validator :-)
+ expat.Parse(body, 1)
- # parse document body
- expat.Parse(body, 1)
+ if parts:
+ parts.append(expatparser.root)
+ root = parser.makeelement(
+ utils.meta_attr('fragments'))
+ for i, part in enumerate(parts):
+ if isinstance(part, basestring):
+ parts[i-1].tail = part
+ else:
+ root.append(part)
+ tree = root.getroottree()
+ else:
+ tree = expatparser.root.getroottree()
+ except xml.parsers.expat.ExpatError:
+ # if we are not able to find a tree root, we give up and
+ # let the exception through
+ if expatparser.root is None:
+ raise
- # return document root tree
- return parser.root.getroottree()
+ # add the root as a tree fragment and update the body
+ # source to the next possible chunk
+ parts.append(expatparser.root)
+ body = body[:expatparser.index] + body[expat.CurrentByteIndex:]
+ # a simple heuristic is used here to allow chunks of
+ # 'junk' in-between the tree fragments
+ pos = body.find('<')
+ junk = body[:pos]
+ body = body[pos:]
+ parts.append(junk)
+
+ return tree
+
def serialize(tree):
"""Serialize tree using lxml."""
Modified: Sandbox/malthe/chameleon.core/src/chameleon/core/template.txt
===================================================================
--- Sandbox/malthe/chameleon.core/src/chameleon/core/template.txt 2008-12-02 14:12:21 UTC (rev 93544)
+++ Sandbox/malthe/chameleon.core/src/chameleon/core/template.txt 2008-12-02 14:53:27 UTC (rev 93545)
@@ -67,6 +67,27 @@
</div>
</div>
+Fragmented documents
+--------------------
+
+ >>> print Template("""
+ ... <div>
+ ... Hello, world!
+ ... </div>
+ ...
+ ... Hello & goodbye!
+ ...
+ ... <div>
+ ... Hello, earth!
+ ... </div>""", mock_parser)()
+ <div>
+ Hello, world!
+ </div>
+ Hello & goodbye!
+ <div>
+ Hello, earth!
+ </div>
+
XML-support
-----------
More information about the Checkins
mailing list