src/doc/sphinx/xml-template.rst (10213B) - raw
1 XML templates
2 =============
3
4 Templates are pure XML, with special directives embedded in the document as
5 attributes and elements. Substitutions are also supported inside character data
6 and attribute values.
7
8 The template syntax is inspired by the `Genshi`_ templating library for Python.
9
10 .. _Genshi: http://genshi.edgewall.org/
11
12 XML namespace
13 -------------
14
15 The XML elements and attributes handled by rdftemplate are defined in
16 a dedicated namespace:
17
18 .. code-block:: none
19
20 http://code.miskinhill.com.au/rdftemplate/
21
22 By convention this namespace is mapped to the prefix ``rdf``. For example:
23
24 .. code-block:: xml
25
26 <html xmlns="http://www.w3.org/1999/xhtml"
27 xmlns:rdf="http://code.miskinhill.com.au/rdftemplate/">
28 ...
29 </html>
30
31 All declarations of the rdftemplate namespace are stripped from the resulting
32 document when a template is rendered.
33
34 Substitutions in character data and attribute values
35 ----------------------------------------------------
36
37 Templates may contain substitutions embedded in character data or in attribute
38 values. Substitutions are delimited by ``${`` and ``}`` and contain
39 a :doc:`selector expression <selector>`, which is evaluated with respect to the
40 current context node (passed to the :java:class:`TemplateInterpolator` when
41 rendering the template).
42
43 The selector expression must have exactly one result when evaluated. The type
44 of the result affects how substitution is performed:
45
46 * If the selector expression evaluates to an
47 `XML literal node <http://www.w3.org/TR/rdf-concepts/#section-XMLLiteral>`_
48 or an instance of :java:class:`XMLStream <au.id.djc.rdftemplate.XMLStream>`,
49 the entire XML tree is inserted into the resulting document. (This
50 substitution is only possible in character data; if it occurs in an attribute
51 value, an exception will be thrown.)
52
53 * If the selector expression evaluates to any other type of literal node, it
54 will be converted to a Java type using Jena’s type conversion facilities, and
55 then toString() will be called on the converted object.
56
57 * If any other Java object is encountered, toString() will be called on it.
58 This means that when a selector expression evaluates to a :java:class:`String
59 <java.lang.String>`, it will be inserted as-is.
60
61 Consider the following example of a template for describing an article in HTML.
62 It uses subtitutions in character data and in attribute values:
63
64 .. code-block:: xml
65
66 <html xmlns="http://www.w3.org/1999/xhtml"
67 xmlns:rdf="http://code.miskinhill.com.au/rdftemplate/">
68 <head>
69 <title>${dc:title#string-lv}</title>
70 <meta name="DC.creator" content="${dc:creator#string-lv}" />
71 </head>
72 <body>
73 <p>Title: ${dc:title}</p>
74 </body>
75 </html>
76
77 In this example, the object of ``dc:title`` might be an XML literal containing
78 an HTML ``<span>`` element. The ``#string-lv`` :ref:`adaptation <adaptations>`
79 is used to strip markup from XML literals in the ``<title>`` element and the
80 ``content`` attribute, where markup is not permitted. On the other hand, the
81 title’s complete XML tree will be inserted into the ``<p>`` element with all
82 markup preserved.
83
84 This example will also work correctly if the object of ``dc:title`` is a plain
85 literal rather than an XML literal, since ``#string-lv`` will pass the plain
86 literal through untouched.
87
88 Substitutions with ``rdf:content``
89 ----------------------------------
90
91 The ``rdf:content`` attribute is used to replace an element’s content with the
92 result of evaluating a selector expression. The selector expression must have
93 exactly one result when evaluated. For example:
94
95 .. code-block:: xml
96
97 <html xmlns="http://www.w3.org/1999/xhtml"
98 xmlns:rdf="http://code.miskinhill.com.au/rdftemplate/">
99 <body>
100 <h1 rdf:content="dc:title" />
101 </body>
102 </html>
103
104 The ``rdf:content`` attribute is stripped from the resulting document. The
105 substitution rules described above also apply for ``rdf:content`` (so XML
106 literals will be inserted as-is into the resulting document), with one minor
107 enhancement: if the selector expression evaluates to a literal node with
108 a language tag, that language will be set on the enclosing element in an
109 `xml:lang <http://www.w3.org/TR/REC-xml/#sec-lang-tag>`_ attribute (and also an
110 XHTML ``lang`` attribute, if the document uses the XHTML namespace).
111
112 If the object of the ``dc:title`` property is the literal ``"Война и мир"@ru``
113 in the example above, then the template would be rendered as:
114
115 .. code-block:: xml
116
117 <html xmlns="http://www.w3.org/1999/xhtml">
118 <body>
119 <h1 xml:lang="ru" lang="ru">Война и мир</h1>
120 </body>
121 </html>
122
123 Note that if the element has any content in the template, this will be
124 discarded when rendering.
125
126 Repetition with ``rdf:for``
127 ---------------------------
128
129 The ``rdf:for`` attribute can be used to loop over zero or more results from
130 a selector expression. For each node in the results, the element and its
131 subtree will be rendered using that node as the context node. All template
132 constructs may be nested inside the subtree, including other ``rdf:for`` loops.
133
134 For example, given the following RDF graph:
135
136 .. include:: example-graph.rst.inc
137
138 the following template could be used to produce an HTML listing of the people
139 who are known to a particular person:
140
141 .. code-block:: xml
142
143 <html xmlns="http://www.w3.org/1999/xhtml"
144 xmlns:rdf="http://code.miskinhill.com.au/rdftemplate/">
145 <body>
146 <h1>${foaf:name}’s buddies</h1>
147 <ul>
148 <li rdf:for="foaf:knows(foaf:name)">
149 <a href="#uri" rdf:content="foaf:name" />
150 </li>
151 </ul>
152 </body>
153 </html>
154
155 If ``<bob>`` is used as the context node, the ``foaf:knows(foaf:name)``
156 expression will select two nodes: ``<alice>`` and ``<carol>``, in that order.
157 The ``<li>`` element will therefore be rendered twice, the first time with its
158 context node set to ``<alice>``, the second time set to ``<carol>``. The
159 resulting XML would be:
160
161 .. code-block:: xml
162
163 <html xmlns="http://www.w3.org/1999/xhtml">
164 <body>
165 <h1>Bob’s buddies</h1>
166 <ul>
167 <li><a href="alice">Alice</a></li>
168 <li><a href="carol">Carol</a></li>
169 </ul>
170 </body>
171 </html>
172
173 ``rdf:for`` can also be given as an XML element, with its selector expression
174 in an attribute named ``each``. This will be rendered in the same way, except
175 that the entire ``rdf:for`` element is stripped out. In the example above,
176 ``<li rdf:for="foaf:knows(foaf:name)">...</li>`` is equivalent to ``<rdf:for
177 each="foaf:knows(foaf:name)"><li>...</li></rdf:for>``.
178
179 Because of the potential for ambiguity, it is illegal to combine ``rdf:for``
180 with other directives on the same element.
181
182 Concatenation with ``rdf:join``
183 -------------------------------
184
185 The ``rdf:join`` element behaves in the same way as the ``rdf:for`` element,
186 but it also accepts a ``separator`` attribute, which specifies a string to be
187 inserted between each repetition.
188
189 For example, here is a briefer version of the template above:
190
191 .. code-block:: xml
192
193 <html xmlns="http://www.w3.org/1999/xhtml"
194 xmlns:rdf="http://code.miskinhill.com.au/rdftemplate/">
195 <body>
196 <p>${foaf:name}’s buddies:
197 <rdf:join each="foaf:knows(foaf:name)" separator=", ">
198 <a href="#uri" rdf:content="foaf:name" />
199 </rdf:join>
200 </p>
201 </body>
202 </html>
203
204 Conditionals with ``rdf:if``
205 ----------------------------
206
207 The ``rdf:if`` attribute will cause an element and its subtree to be included
208 in the resulting document only if the selector expression evaluates to *one or
209 more* items. Use a :ref:`predicate <predicates>` in the selector expression to
210 express complex conditions. For example:
211
212 .. code-block:: xml
213
214 <html xmlns="http://www.w3.org/1999/xhtml"
215 xmlns:rdf="http://code.miskinhill.com.au/rdftemplate/">
216 <body>
217 <p rdf:if="dc:identifier[uri-prefix='urn:issn:']">
218 ISSN: ${dc:identifier#uri-slice(9)}
219 </p>
220 </body>
221 </html>
222
223 When rendering this template, the ``<p>`` element will only be included if
224 there is some object of the ``dc:identifier`` property which satisfies the
225 ``uri-prefix='urn:issn:'`` predicate.
226
227 There is also an element form of ``rdf:if``. Use the ``test`` attribute to
228 specify the selector expression to test against, or the ``not`` attribute to
229 apply an inverse test.
230
231 A pair of ``rdf:if`` elements can be used to make a choice between two
232 alternatives. For example:
233
234 .. code-block:: xml
235
236 <html xmlns="http://www.w3.org/1999/xhtml"
237 xmlns:rdf="http://code.miskinhill.com.au/rdftemplate/">
238 <body>
239 <p>
240 <rdf:if test="ex:thumbnail"><img src="${ex:thumbnail#uri}" /></rdf:if>
241 <rdf:if not="ex:thumbnail">No thumbnail available :-(</rdf:if>
242 </p>
243 </body>
244 </html>
245
246 Rendering templates
247 -------------------
248
249 .. java:class:: au.id.djc.rdftemplate.TemplateInterpolator
250
251 Use this class to render templates. Instances of this class can safely be
252 shared across threads (for example, as singleton beans in Spring).
253
254 .. java:method:: TemplateInterpolator(au.id.djc.rdftemplate.selector.SelectorFactory selectorFactory)
255
256 The given :java:class:`SelectorFactory
257 <au.id.djc.rdftemplate.selector.SelectorFactory>` will be used to
258 evaluate selector expressions when rendering templates.
259
260 .. java:method:: java.lang.String interpolate(java.io.Reader reader, com.hp.hpl.jena.rdf.model.RDFNode node)
261
262 Reads a template from the given :java:class:`Reader <java.io.Reader>`,
263 and renders it using the given node as context. The resulting XML
264 document is returned.
265
266 A number of overrides of this method also exist for advanced use cases.
267 Refer to the `Javadoc for TemplateInterpolator
268 <http://code.djc.id.au/rdftemplate/javadoc/latest/au/id/djc/rdftemplate/TemplateInterpolator.html>`_
269 for more details.