| 583 | |
| 584 | == Adding a Layout Template == |
| 585 | |
| 586 | But there's also duplication in the template files themselves: each template has to redefine the complete header and footer, and any other “decoration” markup that we may want to apply to the complete site. Now, we could simply put those commonly used markup snippets into separate HTML files and [wiki:Documentation/xml-templates.html#includes include] them in the templates where they are needed. But Genshi provides a more elegant way to apply a common structure to different templates: [wiki:Documentation/xml-templates.html#match-templates match templates]. |
| 587 | |
| 588 | Most template languages provide an inheritance mechanism to allow different templates to share some kind of common structure, such as a common header, navigation, and footer. Using this mechanism, you create a “master template” in which you declare slots that “derived templates” can fill in. The problem with this approach is that it is fairly rigid: the master needs to now which content the templates will produce, and what kind of slots need to be provided for them to stuff their content in. And derived templates need to know exactly how the master Also, a derived template is itself not a well-formed or even valid HTML file, and can not be easily previewed or edited in a WYSIWYG authoring tool. |
| 589 | |
| 590 | Match templates in Genshi turn this up side down. They are conceptually similar to running an XSLT transformation over your template output: you create rules that match elements in the template output stream based on XPath patterns. Whenever there is a match, the matched content is replaced by what the match template produces. This sounds complicated in theory, but is fairly intuitive in practice, so let's look at a concrete example. |
| 591 | |
| 592 | Let's create a layout template first: in the `geddit/templates/` directory, add a file named `layout.html`, with the following content: |
| 593 | |
| 594 | {{{ |
| 595 | #!genshi |
| 596 | <html xmlns="http://www.w3.org/1999/xhtml" |
| 597 | xmlns:py="http://genshi.edgewall.org/"> |
| 598 | |
| 599 | <py:match path="head" once="true"> |
| 600 | <head py:attrs="select('@*')"> |
| 601 | <title py:with="title = list(select('title/text()'))"> |
| 602 | <py:if test="title">${title} –</py:if> geddit |
| 603 | </title> |
| 604 | <link rel="stylesheet" href="/media/layout.css" type="text/css" /> |
| 605 | ${select('*[local-name()!="title"]')} |
| 606 | </head> |
| 607 | </py:match> |
| 608 | |
| 609 | <py:match path="body" once="true"> |
| 610 | <body py:attrs="select('@*')"><div id="wrap"> |
| 611 | <div id="header"> |
| 612 | <h1>geddit</h1> |
| 613 | </div> |
| 614 | ${select('*|text()')} |
| 615 | <div id="footer"> |
| 616 | <hr /> |
| 617 | <p class="legalese">© 2007 Edgewall Software</p> |
| 618 | </div> |
| 619 | </div></body> |
| 620 | </py:match> |
| 621 | |
| 622 | </html> |
| 623 | }}} |