Templates
A template is a named, reusable block of layout code that you invoke where
you need it. Unlike a function, a template may contain layout
actions (such as <PlaceObject> or <ClearPage>): it runs in the normal
imperative flow, exactly once, at the call site, in document order. Templates are
the right tool for reusing behaviour.
Defining and calling a template
Define a template at the top level with <Template>
and invoke it with <CallTemplate>:
<Template name="headline">
<Param name="text"/>
<PlaceObject>
<TextBlock>
<Paragraph><B><Value select="$text"/></B></Paragraph>
</TextBlock>
</PlaceObject>
</Template>
<Record match="chapter">
<CallTemplate name="headline">
<Param name="text" select="@title"/>
</CallTemplate>
</Record>Like other definitions, <Template> is collected in the setup pass, so it can be
defined anywhere in the layout file – before or after the records that call it.
Parameters
Parameters are passed with <Param> children:
- On a
<CallTemplate>, a<Param>’sselectexpression is evaluated in the caller’s context and passed as the argument. - On a
<Template>definition, a<Param>declares a parameter and may give a default viaselect, used when the caller omits that parameter.
<Template name="box">
<Param name="title"/>
<Param name="color" select="'black'"/> <!-- default -->
<PlaceObject>
<Textblock>
<Paragraph style="color: { $color }">
<Value select="$title"/>
</Paragraph>
</Textblock>
</PlaceObject>
</Template>
<CallTemplate name="box">
<Param name="title" select="@name"/>
<!-- color omitted, defaults to 'black' -->
</CallTemplate>Scoped bindings
Parameter bindings are scoped to the template body. Before the body runs, XTS saves the current value of each parameter variable, binds the parameters, runs the body, and then restores the previous values. A parameter named like an existing variable shadows it only for the duration of the call:
<SetVariable variable="text" select="'outer'"/>
<CallTemplate name="headline">
<Param name="text" select="'inner'"/> <!-- $text is 'inner' inside the body -->
</CallTemplate>
<!-- here $text is 'outer' again -->Templates versus functions
Templates and functions look similar but serve opposite purposes:
<Function> |
<Template> |
|
|---|---|---|
| Produces | a data value | a side effect (output) |
| May contain actions | no (action-free) | yes |
| Called from | an XPath expression (fn:foo(…)) |
the layout flow (<CallTemplate>) |
| Runs | lazily, when the XPath engine evaluates it | once, at the call site, in order |
| Context | frozen (caller’s arguments) | the live call-site context |
Rule of thumb: if you want a value to compute and reuse, write a function. If you want to do something – place a box, start a page, draw a header – write a template.
When to reach for what
- Reusing fixed content? Store it in a data variable and
splice it with
<CopyOf>. - Reusing a computed value? Write a function.
- Reusing behaviour with output? Write a template.
See Data vs. action for the principle behind this split.