| [283] | 1 | .. -*- mode: rst; encoding: utf-8 -*- |
|---|
| 2 | |
|---|
| 3 | ============================ |
|---|
| [287] | 4 | Genshi XML Template Language |
|---|
| [283] | 5 | ============================ |
|---|
| 6 | |
|---|
| [300] | 7 | Genshi provides a XML-based template language that is heavily inspired by Kid_, |
|---|
| 8 | which in turn was inspired by a number of existing template languages, namely |
|---|
| 9 | XSLT_, TAL_, and PHP_. |
|---|
| [283] | 10 | |
|---|
| 11 | .. _kid: http://kid-templating.org/ |
|---|
| 12 | .. _python: http://www.python.org/ |
|---|
| 13 | .. _xslt: http://www.w3.org/TR/xslt |
|---|
| 14 | .. _tal: http://www.zope.org/Wikis/DevSite/Projects/ZPT/TAL |
|---|
| 15 | .. _php: http://www.php.net/ |
|---|
| 16 | |
|---|
| 17 | This document describes the template language and will be most useful as |
|---|
| [300] | 18 | reference to those developing Genshi XML templates. Templates are XML files of |
|---|
| 19 | some kind (such as XHTML) that include processing directives_ (elements or |
|---|
| [283] | 20 | attributes identified by a separate namespace) that affect how the template is |
|---|
| [534] | 21 | rendered, and template expressions that are dynamically substituted by |
|---|
| [283] | 22 | variable data. |
|---|
| 23 | |
|---|
| [534] | 24 | See `Genshi Templating Basics <templates.html>`_ for general information on |
|---|
| 25 | embedding Python code in templates. |
|---|
| [283] | 26 | |
|---|
| [534] | 27 | |
|---|
| [283] | 28 | .. contents:: Contents |
|---|
| 29 | :depth: 3 |
|---|
| 30 | .. sectnum:: |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | .. _`directives`: |
|---|
| 34 | |
|---|
| 35 | ------------------- |
|---|
| 36 | Template Directives |
|---|
| 37 | ------------------- |
|---|
| 38 | |
|---|
| 39 | Directives are elements and/or attributes in the template that are identified |
|---|
| [287] | 40 | by the namespace ``http://genshi.edgewall.org/``. They can affect how the |
|---|
| 41 | template is rendered in a number of ways: Genshi provides directives for |
|---|
| [283] | 42 | conditionals and looping, among others. |
|---|
| 43 | |
|---|
| [478] | 44 | To use directives in a template, the namespace must be declared, which is |
|---|
| [614] | 45 | usually done on the root element: |
|---|
| [283] | 46 | |
|---|
| [614] | 47 | .. code-block:: genshi |
|---|
| 48 | |
|---|
| [283] | 49 | <html xmlns="http://www.w3.org/1999/xhtml" |
|---|
| [287] | 50 | xmlns:py="http://genshi.edgewall.org/" |
|---|
| [283] | 51 | lang="en"> |
|---|
| 52 | ... |
|---|
| 53 | </html> |
|---|
| 54 | |
|---|
| 55 | In this example, the default namespace is set to the XHTML namespace, and the |
|---|
| [287] | 56 | namespace for Genshi directives is bound to the prefix “py”. |
|---|
| [283] | 57 | |
|---|
| 58 | All directives can be applied as attributes, and some can also be used as |
|---|
| 59 | elements. The ``if`` directives for conditionals, for example, can be used in |
|---|
| [614] | 60 | both ways: |
|---|
| [283] | 61 | |
|---|
| [614] | 62 | .. code-block:: genshi |
|---|
| 63 | |
|---|
| [283] | 64 | <html xmlns="http://www.w3.org/1999/xhtml" |
|---|
| [287] | 65 | xmlns:py="http://genshi.edgewall.org/" |
|---|
| [283] | 66 | lang="en"> |
|---|
| 67 | ... |
|---|
| 68 | <div py:if="foo"> |
|---|
| 69 | <p>Bar</p> |
|---|
| 70 | </div> |
|---|
| 71 | ... |
|---|
| 72 | </html> |
|---|
| 73 | |
|---|
| [614] | 74 | This is basically equivalent to the following: |
|---|
| [283] | 75 | |
|---|
| [614] | 76 | .. code-block:: genshi |
|---|
| 77 | |
|---|
| [283] | 78 | <html xmlns="http://www.w3.org/1999/xhtml" |
|---|
| [287] | 79 | xmlns:py="http://genshi.edgewall.org/" |
|---|
| [283] | 80 | lang="en"> |
|---|
| 81 | ... |
|---|
| 82 | <py:if test="foo"> |
|---|
| 83 | <div> |
|---|
| 84 | <p>Bar</p> |
|---|
| 85 | </div> |
|---|
| 86 | </py:if> |
|---|
| 87 | ... |
|---|
| 88 | </html> |
|---|
| 89 | |
|---|
| 90 | The rationale behind the second form is that directives do not always map |
|---|
| 91 | naturally to elements in the template. In such cases, the ``py:strip`` |
|---|
| 92 | directive can be used to strip off the unwanted element, or the directive can |
|---|
| 93 | simply be used as an element. |
|---|
| 94 | |
|---|
| 95 | |
|---|
| [296] | 96 | Conditional Sections |
|---|
| [283] | 97 | ==================== |
|---|
| 98 | |
|---|
| [294] | 99 | .. _`py:if`: |
|---|
| [283] | 100 | |
|---|
| [294] | 101 | ``py:if`` |
|---|
| [296] | 102 | --------- |
|---|
| [283] | 103 | |
|---|
| [870] | 104 | The element and its content is only rendered if the expression evaluates to a |
|---|
| 105 | truth value: |
|---|
| [283] | 106 | |
|---|
| [614] | 107 | .. code-block:: genshi |
|---|
| 108 | |
|---|
| [294] | 109 | <div> |
|---|
| 110 | <b py:if="foo">${bar}</b> |
|---|
| 111 | </div> |
|---|
| [283] | 112 | |
|---|
| [294] | 113 | Given the data ``foo=True`` and ``bar='Hello'`` in the template context, this |
|---|
| [614] | 114 | would produce: |
|---|
| [283] | 115 | |
|---|
| [728] | 116 | .. code-block:: xml |
|---|
| [614] | 117 | |
|---|
| [294] | 118 | <div> |
|---|
| 119 | <b>Hello</b> |
|---|
| 120 | </div> |
|---|
| [283] | 121 | |
|---|
| [870] | 122 | But setting ``foo=False`` would result in the following output: |
|---|
| 123 | |
|---|
| 124 | .. code-block:: xml |
|---|
| 125 | |
|---|
| 126 | <div> |
|---|
| 127 | </div> |
|---|
| 128 | |
|---|
| [614] | 129 | This directive can also be used as an element: |
|---|
| [283] | 130 | |
|---|
| [614] | 131 | .. code-block:: genshi |
|---|
| 132 | |
|---|
| [294] | 133 | <div> |
|---|
| 134 | <py:if test="foo"> |
|---|
| 135 | <b>${bar}</b> |
|---|
| 136 | </py:if> |
|---|
| 137 | </div> |
|---|
| [283] | 138 | |
|---|
| 139 | .. _`py:choose`: |
|---|
| 140 | .. _`py:when`: |
|---|
| 141 | .. _`py:otherwise`: |
|---|
| 142 | |
|---|
| [296] | 143 | ``py:choose`` |
|---|
| 144 | ------------- |
|---|
| [283] | 145 | |
|---|
| [296] | 146 | The ``py:choose`` directive, in combination with the directives ``py:when`` |
|---|
| [496] | 147 | and ``py:otherwise`` provides advanced conditional processing for rendering one |
|---|
| [283] | 148 | of several alternatives. The first matching ``py:when`` branch is rendered, or, |
|---|
| [496] | 149 | if no ``py:when`` branch matches, the ``py:otherwise`` branch is rendered. |
|---|
| [283] | 150 | |
|---|
| 151 | If the ``py:choose`` directive is empty the nested ``py:when`` directives will |
|---|
| [614] | 152 | be tested for truth: |
|---|
| [283] | 153 | |
|---|
| [614] | 154 | .. code-block:: genshi |
|---|
| 155 | |
|---|
| [283] | 156 | <div py:choose=""> |
|---|
| 157 | <span py:when="0 == 1">0</span> |
|---|
| 158 | <span py:when="1 == 1">1</span> |
|---|
| 159 | <span py:otherwise="">2</span> |
|---|
| 160 | </div> |
|---|
| 161 | |
|---|
| [614] | 162 | This would produce the following output: |
|---|
| [283] | 163 | |
|---|
| [728] | 164 | .. code-block:: xml |
|---|
| [614] | 165 | |
|---|
| [283] | 166 | <div> |
|---|
| 167 | <span>1</span> |
|---|
| 168 | </div> |
|---|
| 169 | |
|---|
| 170 | If the ``py:choose`` directive contains an expression the nested ``py:when`` |
|---|
| [614] | 171 | directives will be tested for equality to the parent ``py:choose`` value: |
|---|
| [283] | 172 | |
|---|
| [614] | 173 | .. code-block:: genshi |
|---|
| 174 | |
|---|
| [283] | 175 | <div py:choose="1"> |
|---|
| 176 | <span py:when="0">0</span> |
|---|
| 177 | <span py:when="1">1</span> |
|---|
| 178 | <span py:otherwise="">2</span> |
|---|
| 179 | </div> |
|---|
| 180 | |
|---|
| [614] | 181 | This would produce the following output: |
|---|
| [283] | 182 | |
|---|
| [728] | 183 | .. code-block:: xml |
|---|
| [614] | 184 | |
|---|
| [283] | 185 | <div> |
|---|
| 186 | <span>1</span> |
|---|
| 187 | </div> |
|---|
| 188 | |
|---|
| [850] | 189 | These directives can also be used as elements: |
|---|
| [283] | 190 | |
|---|
| [850] | 191 | .. code-block:: genshi |
|---|
| 192 | |
|---|
| 193 | <py:choose test="1"> |
|---|
| 194 | <py:when test="0">0</py:when> |
|---|
| 195 | <py:when test="1">1</py:when> |
|---|
| 196 | <py:otherwise>2</py:otherwise> |
|---|
| 197 | </py:choose> |
|---|
| 198 | |
|---|
| [294] | 199 | Looping |
|---|
| [296] | 200 | ======= |
|---|
| [283] | 201 | |
|---|
| [294] | 202 | .. _`py:for`: |
|---|
| [283] | 203 | |
|---|
| [294] | 204 | ``py:for`` |
|---|
| [296] | 205 | ---------- |
|---|
| [283] | 206 | |
|---|
| [614] | 207 | The element is repeated for every item in an iterable: |
|---|
| [294] | 208 | |
|---|
| [614] | 209 | .. code-block:: genshi |
|---|
| 210 | |
|---|
| [283] | 211 | <ul> |
|---|
| [294] | 212 | <li py:for="item in items">${item}</li> |
|---|
| [283] | 213 | </ul> |
|---|
| 214 | |
|---|
| [614] | 215 | Given ``items=[1, 2, 3]`` in the context data, this would produce: |
|---|
| [283] | 216 | |
|---|
| [728] | 217 | .. code-block:: xml |
|---|
| [614] | 218 | |
|---|
| [283] | 219 | <ul> |
|---|
| [294] | 220 | <li>1</li><li>2</li><li>3</li> |
|---|
| [283] | 221 | </ul> |
|---|
| 222 | |
|---|
| [614] | 223 | This directive can also be used as an element: |
|---|
| [283] | 224 | |
|---|
| [614] | 225 | .. code-block:: genshi |
|---|
| 226 | |
|---|
| [294] | 227 | <ul> |
|---|
| 228 | <py:for each="item in items"> |
|---|
| 229 | <li>${item}</li> |
|---|
| 230 | </py:for> |
|---|
| 231 | </ul> |
|---|
| [283] | 232 | |
|---|
| [294] | 233 | |
|---|
| 234 | Snippet Reuse |
|---|
| [296] | 235 | ============= |
|---|
| [294] | 236 | |
|---|
| [283] | 237 | .. _`py:def`: |
|---|
| 238 | .. _`macros`: |
|---|
| 239 | |
|---|
| 240 | ``py:def`` |
|---|
| [296] | 241 | ---------- |
|---|
| [283] | 242 | |
|---|
| 243 | The ``py:def`` directive can be used to create macros, i.e. snippets of |
|---|
| 244 | template code that have a name and optionally some parameters, and that can be |
|---|
| [614] | 245 | inserted in other places: |
|---|
| [283] | 246 | |
|---|
| [614] | 247 | .. code-block:: genshi |
|---|
| 248 | |
|---|
| [283] | 249 | <div> |
|---|
| 250 | <p py:def="greeting(name)" class="greeting"> |
|---|
| 251 | Hello, ${name}! |
|---|
| 252 | </p> |
|---|
| 253 | ${greeting('world')} |
|---|
| 254 | ${greeting('everyone else')} |
|---|
| 255 | </div> |
|---|
| 256 | |
|---|
| [614] | 257 | The above would be rendered to: |
|---|
| [283] | 258 | |
|---|
| [728] | 259 | .. code-block:: xml |
|---|
| [614] | 260 | |
|---|
| [283] | 261 | <div> |
|---|
| 262 | <p class="greeting"> |
|---|
| 263 | Hello, world! |
|---|
| 264 | </p> |
|---|
| 265 | <p class="greeting"> |
|---|
| 266 | Hello, everyone else! |
|---|
| 267 | </p> |
|---|
| 268 | </div> |
|---|
| 269 | |
|---|
| [478] | 270 | If a macro doesn't require parameters, it can be defined without the |
|---|
| [614] | 271 | parenthesis. For example: |
|---|
| [283] | 272 | |
|---|
| [614] | 273 | .. code-block:: genshi |
|---|
| 274 | |
|---|
| [283] | 275 | <div> |
|---|
| 276 | <p py:def="greeting" class="greeting"> |
|---|
| 277 | Hello, world! |
|---|
| 278 | </p> |
|---|
| [478] | 279 | ${greeting()} |
|---|
| [283] | 280 | </div> |
|---|
| 281 | |
|---|
| [614] | 282 | The above would be rendered to: |
|---|
| [283] | 283 | |
|---|
| [728] | 284 | .. code-block:: xml |
|---|
| [614] | 285 | |
|---|
| [283] | 286 | <div> |
|---|
| 287 | <p class="greeting"> |
|---|
| 288 | Hello, world! |
|---|
| 289 | </p> |
|---|
| 290 | </div> |
|---|
| 291 | |
|---|
| [614] | 292 | This directive can also be used as an element: |
|---|
| [283] | 293 | |
|---|
| [614] | 294 | .. code-block:: genshi |
|---|
| 295 | |
|---|
| [283] | 296 | <div> |
|---|
| 297 | <py:def function="greeting(name)"> |
|---|
| 298 | <p class="greeting">Hello, ${name}!</p> |
|---|
| 299 | </py:def> |
|---|
| 300 | </div> |
|---|
| 301 | |
|---|
| 302 | |
|---|
| [294] | 303 | .. _Match Templates: |
|---|
| [283] | 304 | .. _`py:match`: |
|---|
| 305 | |
|---|
| 306 | ``py:match`` |
|---|
| [296] | 307 | ------------ |
|---|
| [283] | 308 | |
|---|
| 309 | This directive defines a *match template*: given an XPath expression, it |
|---|
| 310 | replaces any element in the template that matches the expression with its own |
|---|
| 311 | content. |
|---|
| 312 | |
|---|
| 313 | For example, the match template defined in the following template matches any |
|---|
| [614] | 314 | element with the tag name “greeting”: |
|---|
| [283] | 315 | |
|---|
| [614] | 316 | .. code-block:: genshi |
|---|
| 317 | |
|---|
| [283] | 318 | <div> |
|---|
| 319 | <span py:match="greeting"> |
|---|
| 320 | Hello ${select('@name')} |
|---|
| 321 | </span> |
|---|
| 322 | <greeting name="Dude" /> |
|---|
| 323 | </div> |
|---|
| 324 | |
|---|
| [614] | 325 | This would result in the following output: |
|---|
| [283] | 326 | |
|---|
| [728] | 327 | .. code-block:: xml |
|---|
| [614] | 328 | |
|---|
| [283] | 329 | <div> |
|---|
| 330 | <span> |
|---|
| 331 | Hello Dude |
|---|
| 332 | </span> |
|---|
| 333 | </div> |
|---|
| 334 | |
|---|
| 335 | Inside the body of a ``py:match`` directive, the ``select(path)`` function is |
|---|
| 336 | made available so that parts or all of the original element can be incorporated |
|---|
| [545] | 337 | in the output of the match template. See `Using XPath`_ for more information |
|---|
| 338 | about this function. |
|---|
| [283] | 339 | |
|---|
| [545] | 340 | .. _`Using XPath`: streams.html#using-xpath |
|---|
| 341 | |
|---|
| [810] | 342 | Match templates are applied both to the original markup as well to the |
|---|
| 343 | generated markup. The order in which they are applied depends on the order |
|---|
| 344 | they are declared in the template source: a match template defined after |
|---|
| 345 | another match template is applied to the output generated by the first match |
|---|
| 346 | template. The match templates basically form a pipeline. |
|---|
| 347 | |
|---|
| [614] | 348 | This directive can also be used as an element: |
|---|
| [283] | 349 | |
|---|
| [614] | 350 | .. code-block:: genshi |
|---|
| 351 | |
|---|
| [283] | 352 | <div> |
|---|
| 353 | <py:match path="greeting"> |
|---|
| 354 | <span>Hello ${select('@name')}</span> |
|---|
| 355 | </py:match> |
|---|
| 356 | <greeting name="Dude" /> |
|---|
| 357 | </div> |
|---|
| 358 | |
|---|
| [718] | 359 | When used this way, the ``py:match`` directive can also be annotated with a |
|---|
| 360 | couple of optimization hints. For example, the following informs the matching |
|---|
| 361 | engine that the match should only be applied once: |
|---|
| [283] | 362 | |
|---|
| [718] | 363 | .. code-block:: genshi |
|---|
| 364 | |
|---|
| 365 | <py:match path="body" once="true"> |
|---|
| 366 | <body py:attrs="select('@*')"> |
|---|
| 367 | <div id="header">...</div> |
|---|
| 368 | ${select("*|text()")} |
|---|
| 369 | <div id="footer">...</div> |
|---|
| 370 | </body> |
|---|
| 371 | </py:match> |
|---|
| 372 | |
|---|
| 373 | The following optimization hints are recognized: |
|---|
| 374 | |
|---|
| 375 | +---------------+-----------+-----------------------------------------------+ |
|---|
| 376 | | Attribute | Default | Description | |
|---|
| 377 | +===============+===========+===============================================+ |
|---|
| [816] | 378 | | ``buffer`` | ``true`` | Whether the matched content should be | |
|---|
| 379 | | | | buffered in memory. Buffering can improve | |
|---|
| 380 | | | | performance a bit at the cost of needing more | |
|---|
| 381 | | | | memory during rendering. Buffering is | |
|---|
| 382 | | | | ''required'' for match templates that contain | |
|---|
| 383 | | | | more than one invocation of the ``select()`` | |
|---|
| 384 | | | | function. If there is only one call, and the | |
|---|
| 385 | | | | matched content can potentially be very long, | |
|---|
| 386 | | | | consider disabling buffering to avoid | |
|---|
| 387 | | | | excessive memory use. | |
|---|
| 388 | +---------------+-----------+-----------------------------------------------+ |
|---|
| [718] | 389 | | ``once`` | ``false`` | Whether the engine should stop looking for | |
|---|
| 390 | | | | more matching elements after the first match. | |
|---|
| 391 | | | | Use this on match templates that match | |
|---|
| 392 | | | | elements that can only occur once in the | |
|---|
| 393 | | | | stream, such as the ``<head>`` or ``<body>`` | |
|---|
| 394 | | | | elements in an HTML template, or elements | |
|---|
| 395 | | | | with a specific ID. | |
|---|
| 396 | +---------------+-----------+-----------------------------------------------+ |
|---|
| 397 | | ``recursive`` | ``true`` | Whether the match template should be applied | |
|---|
| 398 | | | | to its own output. Note that ``once`` implies | |
|---|
| 399 | | | | non-recursive behavior, so this attribute | |
|---|
| 400 | | | | only needs to be set for match templates that | |
|---|
| 401 | | | | don't also have ``once`` set. | |
|---|
| 402 | +---------------+-----------+-----------------------------------------------+ |
|---|
| 403 | |
|---|
| 404 | .. note:: The ``py:match`` optimization hints were added in the 0.5 release. In |
|---|
| 405 | earlier versions, the attributes have no effect. |
|---|
| 406 | |
|---|
| 407 | |
|---|
| [294] | 408 | Variable Binding |
|---|
| [296] | 409 | ================ |
|---|
| [294] | 410 | |
|---|
| 411 | .. _`with`: |
|---|
| 412 | |
|---|
| 413 | ``py:with`` |
|---|
| [296] | 414 | ----------- |
|---|
| [294] | 415 | |
|---|
| 416 | The ``py:with`` directive lets you assign expressions to variables, which can |
|---|
| 417 | be used to make expressions inside the directive less verbose and more |
|---|
| 418 | efficient. For example, if you need use the expression ``author.posts`` more |
|---|
| 419 | than once, and that actually results in a database query, assigning the results |
|---|
| 420 | to a variable using this directive would probably help. |
|---|
| 421 | |
|---|
| [614] | 422 | For example: |
|---|
| [294] | 423 | |
|---|
| [614] | 424 | .. code-block:: genshi |
|---|
| 425 | |
|---|
| [294] | 426 | <div> |
|---|
| 427 | <span py:with="y=7; z=x+10">$x $y $z</span> |
|---|
| 428 | </div> |
|---|
| 429 | |
|---|
| [614] | 430 | Given ``x=42`` in the context data, this would produce: |
|---|
| [294] | 431 | |
|---|
| [728] | 432 | .. code-block:: xml |
|---|
| [614] | 433 | |
|---|
| [294] | 434 | <div> |
|---|
| 435 | <span>42 7 52</span> |
|---|
| 436 | </div> |
|---|
| 437 | |
|---|
| [614] | 438 | This directive can also be used as an element: |
|---|
| [294] | 439 | |
|---|
| [614] | 440 | .. code-block:: genshi |
|---|
| 441 | |
|---|
| [294] | 442 | <div> |
|---|
| 443 | <py:with vars="y=7; z=x+10">$x $y $z</py:with> |
|---|
| 444 | </div> |
|---|
| 445 | |
|---|
| 446 | Note that if a variable of the same name already existed outside of the scope |
|---|
| 447 | of the ``py:with`` directive, it will **not** be overwritten. Instead, it |
|---|
| 448 | will have the same value it had prior to the ``py:with`` assignment. |
|---|
| 449 | Effectively, this means that variables are immutable in Genshi. |
|---|
| 450 | |
|---|
| 451 | |
|---|
| 452 | Structure Manipulation |
|---|
| [296] | 453 | ====================== |
|---|
| [294] | 454 | |
|---|
| 455 | .. _`py:attrs`: |
|---|
| 456 | |
|---|
| 457 | ``py:attrs`` |
|---|
| [296] | 458 | ------------ |
|---|
| [294] | 459 | |
|---|
| [614] | 460 | This directive adds, modifies or removes attributes from the element: |
|---|
| [294] | 461 | |
|---|
| [614] | 462 | .. code-block:: genshi |
|---|
| 463 | |
|---|
| [294] | 464 | <ul> |
|---|
| 465 | <li py:attrs="foo">Bar</li> |
|---|
| 466 | </ul> |
|---|
| 467 | |
|---|
| 468 | Given ``foo={'class': 'collapse'}`` in the template context, this would |
|---|
| [614] | 469 | produce: |
|---|
| [294] | 470 | |
|---|
| [728] | 471 | .. code-block:: xml |
|---|
| [614] | 472 | |
|---|
| [294] | 473 | <ul> |
|---|
| 474 | <li class="collapse">Bar</li> |
|---|
| 475 | </ul> |
|---|
| 476 | |
|---|
| 477 | Attributes with the value ``None`` are omitted, so given ``foo={'class': None}`` |
|---|
| [614] | 478 | in the context for the same template this would produce: |
|---|
| [294] | 479 | |
|---|
| [728] | 480 | .. code-block:: xml |
|---|
| [614] | 481 | |
|---|
| [294] | 482 | <ul> |
|---|
| 483 | <li>Bar</li> |
|---|
| 484 | </ul> |
|---|
| 485 | |
|---|
| 486 | This directive can only be used as an attribute. |
|---|
| 487 | |
|---|
| 488 | |
|---|
| 489 | .. _`py:content`: |
|---|
| 490 | |
|---|
| 491 | ``py:content`` |
|---|
| [296] | 492 | -------------- |
|---|
| [294] | 493 | |
|---|
| 494 | This directive replaces any nested content with the result of evaluating the |
|---|
| [614] | 495 | expression: |
|---|
| [294] | 496 | |
|---|
| [614] | 497 | .. code-block:: genshi |
|---|
| 498 | |
|---|
| [294] | 499 | <ul> |
|---|
| 500 | <li py:content="bar">Hello</li> |
|---|
| 501 | </ul> |
|---|
| 502 | |
|---|
| [614] | 503 | Given ``bar='Bye'`` in the context data, this would produce: |
|---|
| [294] | 504 | |
|---|
| [728] | 505 | .. code-block:: xml |
|---|
| [614] | 506 | |
|---|
| [294] | 507 | <ul> |
|---|
| 508 | <li>Bye</li> |
|---|
| 509 | </ul> |
|---|
| 510 | |
|---|
| 511 | This directive can only be used as an attribute. |
|---|
| 512 | |
|---|
| 513 | |
|---|
| [283] | 514 | .. _`py:replace`: |
|---|
| 515 | |
|---|
| 516 | ``py:replace`` |
|---|
| [296] | 517 | -------------- |
|---|
| [283] | 518 | |
|---|
| 519 | This directive replaces the element itself with the result of evaluating the |
|---|
| [614] | 520 | expression: |
|---|
| [283] | 521 | |
|---|
| [614] | 522 | .. code-block:: genshi |
|---|
| 523 | |
|---|
| [283] | 524 | <div> |
|---|
| 525 | <span py:replace="bar">Hello</span> |
|---|
| 526 | </div> |
|---|
| 527 | |
|---|
| [614] | 528 | Given ``bar='Bye'`` in the context data, this would produce: |
|---|
| [283] | 529 | |
|---|
| [728] | 530 | .. code-block:: xml |
|---|
| [614] | 531 | |
|---|
| [283] | 532 | <div> |
|---|
| 533 | Bye |
|---|
| 534 | </div> |
|---|
| 535 | |
|---|
| [773] | 536 | This directive can also be used as an element (since version 0.5): |
|---|
| [283] | 537 | |
|---|
| [773] | 538 | .. code-block:: genshi |
|---|
| [283] | 539 | |
|---|
| [773] | 540 | <div> |
|---|
| 541 | <py:replace value="title">Placeholder</py:replace> |
|---|
| 542 | </div> |
|---|
| 543 | |
|---|
| 544 | |
|---|
| 545 | |
|---|
| [283] | 546 | .. _`py:strip`: |
|---|
| 547 | |
|---|
| 548 | ``py:strip`` |
|---|
| [296] | 549 | ------------ |
|---|
| [283] | 550 | |
|---|
| 551 | This directive conditionally strips the top-level element from the output. When |
|---|
| 552 | the value of the ``py:strip`` attribute evaluates to ``True``, the element is |
|---|
| [614] | 553 | stripped from the output: |
|---|
| [283] | 554 | |
|---|
| [614] | 555 | .. code-block:: genshi |
|---|
| 556 | |
|---|
| [283] | 557 | <div> |
|---|
| 558 | <div py:strip="True"><b>foo</b></div> |
|---|
| 559 | </div> |
|---|
| 560 | |
|---|
| [614] | 561 | This would be rendered as: |
|---|
| [283] | 562 | |
|---|
| [728] | 563 | .. code-block:: xml |
|---|
| [614] | 564 | |
|---|
| [283] | 565 | <div> |
|---|
| 566 | <b>foo</b> |
|---|
| 567 | </div> |
|---|
| 568 | |
|---|
| 569 | As a shorthand, if the value of the ``py:strip`` attribute is empty, that has |
|---|
| 570 | the same effect as using a truth value (i.e. the element is stripped). |
|---|
| 571 | |
|---|
| 572 | |
|---|
| 573 | .. _order: |
|---|
| 574 | |
|---|
| 575 | Processing Order |
|---|
| 576 | ================ |
|---|
| 577 | |
|---|
| 578 | It is possible to attach multiple directives to a single element, although not |
|---|
| 579 | all combinations make sense. When multiple directives are encountered, they are |
|---|
| 580 | processed in the following order: |
|---|
| 581 | |
|---|
| 582 | #. `py:def`_ |
|---|
| 583 | #. `py:match`_ |
|---|
| 584 | #. `py:when`_ |
|---|
| 585 | #. `py:otherwise`_ |
|---|
| 586 | #. `py:for`_ |
|---|
| 587 | #. `py:if`_ |
|---|
| 588 | #. `py:choose`_ |
|---|
| 589 | #. `py:with`_ |
|---|
| 590 | #. `py:replace`_ |
|---|
| 591 | #. `py:content`_ |
|---|
| 592 | #. `py:attrs`_ |
|---|
| 593 | #. `py:strip`_ |
|---|
| 594 | |
|---|
| 595 | |
|---|
| 596 | .. _includes: |
|---|
| 597 | |
|---|
| 598 | -------- |
|---|
| 599 | Includes |
|---|
| 600 | -------- |
|---|
| 601 | |
|---|
| 602 | To reuse common snippets of template code, you can include other files using |
|---|
| 603 | XInclude_. |
|---|
| 604 | |
|---|
| 605 | .. _xinclude: http://www.w3.org/TR/xinclude/ |
|---|
| 606 | |
|---|
| 607 | For this, you need to declare the XInclude namespace (commonly bound to the |
|---|
| 608 | prefix “xi”) and use the ``<xi:include>`` element where you want the external |
|---|
| [614] | 609 | file to be pulled in: |
|---|
| [283] | 610 | |
|---|
| [614] | 611 | .. code-block:: genshi |
|---|
| 612 | |
|---|
| [283] | 613 | <html xmlns="http://www.w3.org/1999/xhtml" |
|---|
| [287] | 614 | xmlns:py="http://genshi.edgewall.org/" |
|---|
| [283] | 615 | xmlns:xi="http://www.w3.org/2001/XInclude"> |
|---|
| 616 | <xi:include href="base.html" /> |
|---|
| 617 | ... |
|---|
| 618 | </html> |
|---|
| 619 | |
|---|
| 620 | Include paths are relative to the filename of the template currently being |
|---|
| 621 | processed. So if the example above was in the file "``myapp/index.html``" |
|---|
| 622 | (relative to the template search path), the XInclude processor would look for |
|---|
| 623 | the included file at "``myapp/base.html``". You can also use Unix-style |
|---|
| 624 | relative paths, for example "``../base.html``" to look in the parent directory. |
|---|
| 625 | |
|---|
| 626 | Any content included this way is inserted into the generated output instead of |
|---|
| 627 | the ``<xi:include>`` element. The included template sees the same context data. |
|---|
| 628 | `Match templates`_ and `macros`_ in the included template are also available to |
|---|
| 629 | the including template after the point it was included. |
|---|
| 630 | |
|---|
| 631 | By default, an error will be raised if an included file is not found. If that's |
|---|
| 632 | not what you want, you can specify fallback content that should be used if the |
|---|
| 633 | include fails. For example, to to make the include above fail silently, you'd |
|---|
| [614] | 634 | write: |
|---|
| [283] | 635 | |
|---|
| [614] | 636 | .. code-block:: genshi |
|---|
| 637 | |
|---|
| [283] | 638 | <xi:include href="base.html"><xi:fallback /></xi:include> |
|---|
| 639 | |
|---|
| [338] | 640 | See the `XInclude specification`_ for more about fallback content. Note though |
|---|
| 641 | that Genshi currently only supports a small subset of XInclude. |
|---|
| [283] | 642 | |
|---|
| [338] | 643 | .. _`xinclude specification`: http://www.w3.org/TR/xinclude/ |
|---|
| 644 | |
|---|
| [726] | 645 | |
|---|
| 646 | Dynamic Includes |
|---|
| 647 | ================ |
|---|
| 648 | |
|---|
| [287] | 649 | Incudes in Genshi are fully dynamic: Just like normal attributes, the `href` |
|---|
| [534] | 650 | attribute accepts expressions, and directives_ can be used on the |
|---|
| [283] | 651 | ``<xi:include />`` element just as on any other element, meaning you can do |
|---|
| [614] | 652 | things like conditional includes: |
|---|
| [283] | 653 | |
|---|
| [614] | 654 | .. code-block:: genshi |
|---|
| 655 | |
|---|
| [283] | 656 | <xi:include href="${name}.html" py:if="not in_popup" |
|---|
| 657 | py:for="name in ('foo', 'bar', 'baz')" /> |
|---|
| 658 | |
|---|
| 659 | |
|---|
| [726] | 660 | Including Text Templates |
|---|
| 661 | ======================== |
|---|
| 662 | |
|---|
| 663 | The ``parse`` attribute of the ``<xi:include>`` element can be used to specify |
|---|
| 664 | whether the included template is an XML template or a text template (using the |
|---|
| 665 | new syntax added in Genshi 0.5): |
|---|
| 666 | |
|---|
| 667 | .. code-block:: genshi |
|---|
| 668 | |
|---|
| 669 | <xi:include href="myscript.js" parse="text" /> |
|---|
| 670 | |
|---|
| 671 | This example would load the ``myscript.js`` file as a ``NewTextTemplate``. See |
|---|
| 672 | `text templates`_ for details on the syntax of text templates. |
|---|
| 673 | |
|---|
| 674 | .. _`text templates`: text-templates.html |
|---|
| 675 | |
|---|
| 676 | |
|---|
| [283] | 677 | .. _comments: |
|---|
| 678 | |
|---|
| 679 | -------- |
|---|
| 680 | Comments |
|---|
| 681 | -------- |
|---|
| 682 | |
|---|
| [614] | 683 | Normal XML/HTML comment syntax can be used in templates: |
|---|
| [283] | 684 | |
|---|
| [614] | 685 | .. code-block:: genshi |
|---|
| 686 | |
|---|
| [283] | 687 | <!-- this is a comment --> |
|---|
| 688 | |
|---|
| 689 | However, such comments get passed through the processing pipeline and are by |
|---|
| 690 | default included in the final output. If that's not desired, prefix the comment |
|---|
| [614] | 691 | text with an exclamation mark: |
|---|
| [283] | 692 | |
|---|
| [614] | 693 | .. code-block:: genshi |
|---|
| 694 | |
|---|
| [283] | 695 | <!-- !this is a comment too, but one that will be stripped from the output --> |
|---|
| 696 | |
|---|
| 697 | Note that it does not matter whether there's whitespace before or after the |
|---|
| [614] | 698 | exclamation mark, so the above could also be written as follows: |
|---|
| [283] | 699 | |
|---|
| [614] | 700 | .. code-block:: genshi |
|---|
| 701 | |
|---|
| [283] | 702 | <!--! this is a comment too, but one that will be stripped from the output --> |
|---|