Changeset 718
- Timestamp:
- Aug 23, 2007, 1:35:43 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
-
doc/xml-templates.txt (modified) (1 diff)
-
examples/bench/genshi/base.html (modified) (2 diffs)
-
genshi/template/directives.py (modified) (2 diffs)
-
genshi/template/markup.py (modified) (3 diffs)
-
genshi/template/tests/directives.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/xml-templates.txt
r614 r718 333 333 <greeting name="Dude" /> 334 334 </div> 335 336 When used this way, the ``py:match`` directive can also be annotated with a 337 couple of optimization hints. For example, the following informs the matching 338 engine that the match should only be applied once: 339 340 .. code-block:: genshi 341 342 <py:match path="body" once="true"> 343 <body py:attrs="select('@*')"> 344 <div id="header">...</div> 345 ${select("*|text()")} 346 <div id="footer">...</div> 347 </body> 348 </py:match> 349 350 The following optimization hints are recognized: 351 352 +---------------+-----------+-----------------------------------------------+ 353 | Attribute | Default | Description | 354 +===============+===========+===============================================+ 355 | ``once`` | ``false`` | Whether the engine should stop looking for | 356 | | | more matching elements after the first match. | 357 | | | Use this on match templates that match | 358 | | | elements that can only occur once in the | 359 | | | stream, such as the ``<head>`` or ``<body>`` | 360 | | | elements in an HTML template, or elements | 361 | | | with a specific ID. | 362 +---------------+-----------+-----------------------------------------------+ 363 | ``recursive`` | ``true`` | Whether the match template should be applied | 364 | | | to its own output. Note that ``once`` implies | 365 | | | non-recursive behavior, so this attribute | 366 | | | only needs to be set for match templates that | 367 | | | don't also have ``once`` set. | 368 +---------------+-----------+-----------------------------------------------+ 369 370 .. note:: The ``py:match`` optimization hints were added in the 0.5 release. In 371 earlier versions, the attributes have no effect. 335 372 336 373 -
trunk/examples/bench/genshi/base.html
r299 r718 7 7 </p> 8 8 9 < body py:match="body">9 <py:match path="body" once="true"><body> 10 10 <div id="header"> 11 11 <h1>${title}</h1> … … 13 13 ${select('*')} 14 14 <div id="footer" /> 15 </body> 15 </body></py:match> 16 16 17 17 </html> -
trunk/genshi/template/directives.py
r717 r718 15 15 16 16 import compiler 17 try: 18 frozenset 19 except NameError: 20 from sets import ImmutableSet as frozenset 17 21 18 22 from genshi.core import QName, Stream … … 424 428 </div> 425 429 """ 426 __slots__ = ['path', 'namespaces'] 427 428 def __init__(self, value, template, namespaces=None, lineno=-1, offset=-1): 430 __slots__ = ['path', 'namespaces', 'hints'] 431 432 def __init__(self, value, template, hints=None, namespaces=None, 433 lineno=-1, offset=-1): 429 434 Directive.__init__(self, None, template, namespaces, lineno, offset) 430 435 self.path = Path(value, template.filepath, lineno) 431 436 self.namespaces = namespaces or {} 432 433 def attach(cls, template, stream, value, namespaces, pos): 437 self.hints = hints or () 438 439 def attach(cls, template, stream, value, namespaces, pos): 440 hints = [] 434 441 if type(value) is dict: 442 if value.get('once', '').lower() == 'true': 443 hints.append('match_once') 444 if value.get('recursive', '').lower() == 'false': 445 hints.append('not_recursive') 435 446 value = value.get('path') 436 return super(MatchDirective, cls).attach(template, stream, value,437 namespaces, pos)447 return cls(value, template, frozenset(hints), namespaces, *pos[1:]), \ 448 stream 438 449 attach = classmethod(attach) 439 450 440 451 def __call__(self, stream, ctxt, directives): 441 452 ctxt._match_templates.append((self.path.test(ignore_context=True), 442 self.path, list(stream), self. namespaces,443 directives))453 self.path, list(stream), self.hints, 454 self.namespaces, directives)) 444 455 return [] 445 456 -
trunk/genshi/template/markup.py
r717 r718 262 262 continue 263 263 264 for idx, (test, path, template, namespaces, directives) in\265 enumerate(match_templates):264 for idx, (test, path, template, hints, namespaces, directives) \ 265 in enumerate(match_templates): 266 266 267 267 if test(event, namespaces, ctxt) is True: 268 if 'match_once' in hints: 269 del match_templates[idx] 270 idx -= 1 268 271 269 272 # Let the remaining match templates know about the event so … … 274 277 # Consume and store all events until an end event 275 278 # corresponding to this start event is encountered 276 content = chain([event], 277 self._match(_strip(stream), ctxt, 278 [match_templates[idx]]), 279 tail) 280 content = list(self._include(content, ctxt)) 279 inner = _strip(stream) 280 if 'match_once' not in hints \ 281 and 'not_recursive' not in hints: 282 inner = self._match(inner, ctxt, [match_templates[idx]]) 283 content = list(self._include(chain([event], inner, tail), 284 ctxt)) 281 285 282 286 for test in [mt[0] for mt in match_templates]: … … 291 295 # Recursively process the output 292 296 template = _apply_directives(template, ctxt, directives) 297 remaining = match_templates 298 if 'match_once' not in hints: 299 remaining = remaining[:idx] + remaining[idx + 1:] 293 300 for event in self._match(self._eval(self._flatten(template, 294 301 ctxt), 295 ctxt), ctxt, 296 match_templates[:idx] + 297 match_templates[idx + 1:]): 302 ctxt), ctxt, remaining): 298 303 yield event 299 304 -
trunk/genshi/template/tests/directives.py
r579 r718 843 843 </html>""", str(tmpl.generate())) 844 844 845 def test_match_with_once_attribute(self): 846 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> 847 <py:match path="body" once="true"><body> 848 <div id="wrap"> 849 ${select("*")} 850 </div> 851 </body></py:match> 852 <body> 853 <p>Foo</p> 854 </body> 855 <body> 856 <p>Bar</p> 857 </body> 858 </html>""") 859 self.assertEqual("""<html> 860 <body> 861 <div id="wrap"> 862 <p>Foo</p> 863 </div> 864 </body> 865 <body> 866 <p>Bar</p> 867 </body> 868 </html>""", str(tmpl.generate())) 869 870 def test_match_with_recursive_attribute(self): 871 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 872 <py:match path="elem" recursive="false"><elem> 873 <div class="elem"> 874 ${select('*')} 875 </div> 876 </elem></py:match> 877 <elem> 878 <subelem> 879 <elem/> 880 </subelem> 881 </elem> 882 </doc>""") 883 self.assertEqual("""<doc> 884 <elem> 885 <div class="elem"> 886 <subelem> 887 <elem/> 888 </subelem> 889 </div> 890 </elem> 891 </doc>""", str(tmpl.generate())) 892 845 893 # FIXME 846 894 #def test_match_after_step(self):
Note: See TracChangeset
for help on using the changeset viewer.
