def transform(self, stream=None, filters=[]): """ Execute the template and apply any match transformations. If stream is specified, it must be one of the following: Element A kid.Element. ElementStream An `pull.ElementStream` instance or other iterator that yields stream events. string A file or URL unless the string starts with '<' in which case it is considered an XML document and processed as if it had been an Element. By default, the `pull` method is called to obtain the stream. """ if stream is None: stream = self.pull() elif isinstance(stream, basestring): if xml_sniff(stream): stream = XML(stream, fragment=False) else: stream = document(stream) elif hasattr(stream, 'tag'): stream = ElementStream(stream) else: stream = ElementStream.ensure(stream) for f in filters + self._filters: stream = f(stream, self) return stream
def transform_filter(stream, template): templates = template._get_match_templates() def apply_func(item): return transform_filter(generate_content(item), template) stream = ElementStream.ensure(stream) return ElementStream(apply_matches(stream, template, templates, apply_func))
def pull(self): """Returns an iterator over the items in this template.""" # create stream and apply filters self.initialize() stream = ElementStream( _coalesce(self.content(), self._get_assume_encoding())) return stream
def generate_content(content): """Generate ElementStream from content.""" if content is None: return [] elif isinstance(content, basestring): return [(TEXT, content)] elif isinstance(content, (ElementStream, kid.BaseTemplate)): return content elif isinstance(content, GeneratorType): return ElementStream(content) elif hasattr(content, 'tag') and hasattr(content, 'attrib'): # if we get an Element back, make it an ElementStream return ElementStream(content) elif hasattr(content, '__iter__'): # if we get any other iterable, chain the contents together: return itertools.chain(*itertools.imap(generate_content, content)) else: return [(TEXT, unicode(content))]
def xinclude_filter(stream, template): xi = Namespace('http://www.w3.org/2001/XInclude') include = xi.include fallback = xi.fallback for ev, item in stream: if ev == START and item.tag == include: item = item.expand() href = item.get('href') try: doc = document(href, template._get_assume_encoding()) except: fallback_elm = item.find(fallback) for ev, item in ElementStream(fallback_elm).strip(1): yield ev, item else: for ev, item in doc: if ev != XML_DECL: yield ev
def apply_matches(stream, template, templates, apply_func): for ev, item in stream: if ev == START: matched = False for i in range(0, len(templates)): match, call = templates[i] if match(item): item = stream.expand() newstream = _coalesce(call(template, item, apply_func), template._get_assume_encoding()) if len(templates) < 2: for ev, item in newstream: yield ev, item else: for ev, item in apply_matches( ElementStream(newstream), template, templates[:i] + templates[i + 1:], apply_func): yield ev, item matched = True break if matched: continue yield ev, item
def test_expand_fragments(): """Testcase for expanding XML fragments (ticket #145).""" template = """<div xmlns:py="http://purl.org/kid/ns#" py:replace="stream" />""" t = Template("""\ <div xmlns:py="http://purl.org/kid/ns#"> <div py:for="i in range(3)"> <p>Hello World #$i</p> </div> </div>""") s = t.serialize(fragment=True) expected = """<div> <div> <p>Hello World #0</p> </div><div> <p>Hello World #1</p> </div><div> <p>Hello World #2</p> </div> </div>""" assert s == expected stream = ElementStream(t.transform()).expand() t2 = Template(source=template, stream=stream) s2 = t2.serialize(fragment=True) assert s2 == s t = Template("""\ <div xmlns:py="http://purl.org/kid/ns#" py:for="i in range(3)"> <p>Hello World #$i</p> </div>""") s = t.serialize(fragment=True) expected = """<div> <p>Hello World #0</p> </div><div> <p>Hello World #1</p> </div><div> <p>Hello World #2</p> </div>""" assert s == expected stream = ElementStream(t.transform()).expand() t2 = Template(source=template, stream=stream) s2 = t2.serialize(fragment=True) assert s2 == s t = Template("""\ <div xmlns:py="http://purl.org/kid/ns#"> <div py:strip="True"> <p>Hello World</p> </div> </div>""") s = t.serialize(fragment=True) expected = """<div> <p>Hello World</p> </div>""" assert s == expected stream = ElementStream(t.transform()).expand() t2 = Template(source=template, stream=stream) s2 = t2.serialize(fragment=True) assert s2 == s t = Template("""\ <div xmlns:py="http://purl.org/kid/ns#" py:strip="True"> <p>Hello World</p> </div>""") s = t.serialize(fragment=True).strip() expected = """<p>Hello World</p>""" assert s == expected stream = ElementStream(t.transform()).expand() t2 = Template(source=template, stream=stream) s2 = t2.serialize(fragment=True).strip() assert s2 == s