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.