1 <?xml version="1.0"?> 2 <!-- 3 A stylesheet which takes lower-level template annotations and produces an output 4 stylesheet - something which is capable of transforming XML documents into Web 5 pages or other kinds of XML documents. 6 7 Copyright (C) 2005 Paul Boddie <paul@boddie.org.uk> 8 9 This library is free software; you can redistribute it and/or 10 modify it under the terms of the GNU Lesser General Public 11 License as published by the Free Software Foundation; either 12 version 2.1 of the License, or (at your option) any later version. 13 14 This library is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 Lesser General Public License for more details. 18 19 You should have received a copy of the GNU Lesser General Public 20 License along with this library; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 22 --> 23 <xsl:stylesheet version="1.0" 24 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 25 xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias" 26 xmlns:template="http://www.boddie.org.uk/ns/xmltools/template"> 27 28 <xsl:output indent="yes"/> 29 <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/> 30 31 32 33 <!-- Match the document itself. --> 34 35 <xsl:template match="/"> 36 <axsl:stylesheet version="1.0"> 37 38 <axsl:output indent="yes"/> 39 <!-- NOTE: Hard-coded doctypes to hopefully satisfy JavaScript code. --> 40 <!-- doctype-public="-//W3C//DTD XHTML 1.1//EN" 41 doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" --> 42 43 <!-- Include internationalisation (i18n) support if appropriate. --> 44 <xsl:if test="//*[@template:i18n]"> 45 <axsl:param name="translations"/> 46 <axsl:param name="locale"/> 47 </xsl:if> 48 49 <axsl:template match="/"> 50 51 <!-- Include the remaining attributes. --> 52 <xsl:apply-templates select="@*"/> 53 54 <!-- Process the elements. --> 55 <xsl:apply-templates select="*"/> 56 57 </axsl:template> 58 </axsl:stylesheet> 59 </xsl:template> 60 61 62 63 <!-- Match special conditional expression attributes. --> 64 65 <xsl:template match="*[@template:if]"> 66 <axsl:if test="{@template:if}"> 67 <xsl:choose> 68 <xsl:when test="@template:element"> 69 <xsl:call-template name="enter-element"> 70 <xsl:with-param name="other-elements" select="@template:element"/> 71 </xsl:call-template> 72 </xsl:when> 73 <xsl:otherwise> 74 <xsl:call-template name="enter-attribute"/> 75 </xsl:otherwise> 76 </xsl:choose> 77 </axsl:if> 78 </xsl:template> 79 80 81 82 <!-- Match element references. --> 83 84 <xsl:template match="*[not(@template:if) and @template:element]"> 85 <xsl:call-template name="enter-element"> 86 <xsl:with-param name="other-elements" select="@template:element"/> 87 </xsl:call-template> 88 </xsl:template> 89 90 <xsl:template name="enter-element"> 91 <xsl:param name="other-elements"/> 92 <xsl:variable name="first-element" select="substring-before($other-elements, ',')"/> 93 <xsl:variable name="remaining-elements" select="substring-after($other-elements, ',')"/> 94 <xsl:choose> 95 <xsl:when test="$first-element = ''"> 96 <xsl:call-template name="next-element"> 97 <xsl:with-param name="first-element" select="$other-elements"/> 98 </xsl:call-template> 99 </xsl:when> 100 <xsl:otherwise> 101 <xsl:call-template name="next-element"> 102 <xsl:with-param name="first-element" select="$first-element"/> 103 <xsl:with-param name="remaining-elements" select="$remaining-elements"/> 104 </xsl:call-template> 105 </xsl:otherwise> 106 </xsl:choose> 107 </xsl:template> 108 109 <xsl:template name="next-element"> 110 <xsl:param name="first-element"/> 111 <xsl:param name="remaining-elements"/> 112 <axsl:for-each select="{$first-element}"> 113 <xsl:choose> 114 <xsl:when test="$remaining-elements = ''"> 115 <xsl:call-template name="enter-attribute"/> 116 </xsl:when> 117 <xsl:otherwise> 118 <xsl:call-template name="enter-element"> 119 <xsl:with-param name="other-elements" select="$remaining-elements"/> 120 </xsl:call-template> 121 </xsl:otherwise> 122 </xsl:choose> 123 </axsl:for-each> 124 </xsl:template> 125 126 127 128 <!-- Match special expression attributes. --> 129 130 <xsl:template match="*[not(@template:if) and not(@template:element) and (@template:attribute or @template:value or @template:expr)]"> 131 <xsl:call-template name="enter-attribute"/> 132 </xsl:template> 133 134 <xsl:template name="enter-attribute"> 135 <xsl:choose> 136 <xsl:when test="@template:attribute"> 137 <axsl:choose> 138 <axsl:when test="@{@template:attribute}"> 139 <axsl:variable name="this-name"><xsl:value-of select="@template:attribute"/></axsl:variable> 140 <axsl:variable name="this-value" select="@{@template:attribute}"/> 141 <xsl:call-template name="special-attributes"/> 142 </axsl:when> 143 <axsl:otherwise> 144 <axsl:variable name="this-name"><xsl:value-of select="@template:attribute"/></axsl:variable> 145 <axsl:variable name="this-value"></axsl:variable> 146 <xsl:call-template name="special-attributes"/> 147 </axsl:otherwise> 148 </axsl:choose> 149 </xsl:when> 150 <xsl:otherwise> 151 <xsl:call-template name="special-attributes"/> 152 </xsl:otherwise> 153 </xsl:choose> 154 </xsl:template> 155 156 <xsl:template name="special-attributes"> 157 <xsl:choose> 158 <xsl:when test="@template:effect = 'replace'"> 159 <xsl:call-template name="special-value"/> 160 </xsl:when> 161 <xsl:when test="@template:i18n != '' and @template:i18n != '-'"> 162 <xsl:copy> 163 <xsl:apply-templates select="@*"/> 164 <xsl:call-template name="translated-values"> 165 <xsl:with-param name="values" select="@template:i18n"/> 166 </xsl:call-template> 167 <xsl:call-template name="expression-attributes"/> 168 </xsl:copy> 169 </xsl:when> 170 <xsl:otherwise> 171 <xsl:copy> 172 <xsl:apply-templates select="@*"/> 173 <xsl:call-template name="expression-attributes"/> 174 </xsl:copy> 175 </xsl:otherwise> 176 </xsl:choose> 177 </xsl:template> 178 179 <xsl:template name="expression-attributes"> 180 <xsl:if test="@template:expr and @template:expr-attr"> 181 <axsl:if test="{@template:expr}"> 182 <axsl:attribute name="{@template:expr-attr}"><xsl:value-of select="@template:expr-attr"/></axsl:attribute> 183 </axsl:if> 184 </xsl:if> 185 <xsl:call-template name="special-value"/> 186 </xsl:template> 187 188 <xsl:template name="special-value"> 189 <xsl:choose> 190 <!-- Insert the stated value. --> 191 <xsl:when test="@template:value"> 192 <axsl:value-of select="{@template:value}"/> 193 </xsl:when> 194 <!-- Insert the translated value. --> 195 <xsl:when test="@template:i18n = '-'"> 196 <xsl:call-template name="translated-value"> 197 <xsl:with-param name="mode">contents</xsl:with-param> 198 </xsl:call-template> 199 </xsl:when> 200 <!-- Just process the descendants. --> 201 <xsl:otherwise> 202 <xsl:apply-templates select="node()"/> 203 </xsl:otherwise> 204 </xsl:choose> 205 </xsl:template> 206 207 208 209 <!-- Match internationalisation attributes. --> 210 211 <xsl:template match="*[not(@template:if) and not(@template:element) and not(@template:attribute) and not(@template:value) and not(@template:expr) and @template:i18n]"> 212 <xsl:copy> 213 <xsl:choose> 214 <xsl:when test="@template:i18n = '-'"> 215 <xsl:apply-templates select="@*"/> 216 <xsl:call-template name="translated-value"> 217 <xsl:with-param name="mode">contents</xsl:with-param> 218 </xsl:call-template> 219 </xsl:when> 220 <xsl:otherwise> 221 <xsl:apply-templates select="@*"/> 222 <xsl:call-template name="translated-values"> 223 <xsl:with-param name="values" select="@template:i18n"/> 224 </xsl:call-template> 225 </xsl:otherwise> 226 </xsl:choose> 227 </xsl:copy> 228 </xsl:template> 229 230 <xsl:template name="translated-values"> 231 <xsl:param name="values"/> 232 <xsl:param name="this-value" select="substring-before($values, ',')"/> 233 <xsl:param name="next-values" select="substring-after($values, ',')"/> 234 <xsl:choose> 235 <xsl:when test="$this-value != ''"> 236 <xsl:call-template name="translated-value"> 237 <xsl:with-param name="mode">attribute</xsl:with-param> 238 <xsl:with-param name="attribute-name" select="$this-value"/> 239 </xsl:call-template> 240 <xsl:call-template name="translated-values"> 241 <xsl:with-param name="values" select="$next-values"/> 242 </xsl:call-template> 243 </xsl:when> 244 <xsl:when test="$values != ''"> 245 <xsl:call-template name="translated-value"> 246 <xsl:with-param name="mode">attribute</xsl:with-param> 247 <xsl:with-param name="attribute-name" select="$values"/> 248 </xsl:call-template> 249 </xsl:when> 250 <xsl:otherwise/> 251 </xsl:choose> 252 </xsl:template> 253 254 <xsl:template name="translated-value"> 255 <xsl:param name="mode"/> 256 <xsl:param name="attribute-name"/> 257 <xsl:choose> 258 <!-- Look for a translation for the contents. --> 259 <xsl:when test="$mode = 'contents'"> 260 <!-- NOTE: Quoting not done completely. --> 261 <!-- NOTE: Guard against scoping issues by generating a special name. --> 262 <axsl:variable name="translation-{$attribute-name}" 263 select="$translations/translations/locale[code/@value=$locale]/translation[@value='{text()}']/text()"/> 264 <axsl:choose> 265 <!-- Insert the translated value. --> 266 <axsl:when test="$translation-{$attribute-name}"> 267 <axsl:value-of select="$translation-{$attribute-name}"/> 268 </axsl:when> 269 <!-- Otherwise, just process the descendants. --> 270 <axsl:otherwise> 271 <xsl:apply-templates select="node()"/> 272 </axsl:otherwise> 273 </axsl:choose> 274 </xsl:when> 275 <!-- Look for a translation for an attribute. --> 276 <xsl:otherwise> 277 <!-- NOTE: Quoting not done completely. --> 278 <!-- NOTE: Guard against scoping issues by generating a special name. --> 279 <xsl:variable name="attribute-value" select="@*[local-name() = $attribute-name]"/> 280 <axsl:variable name="translation-{$attribute-name}" 281 select="$translations/translations/locale[code/@value=$locale]/translation[@value='{$attribute-value}']/text()"/> 282 <axsl:choose> 283 <!-- Insert the translated value. --> 284 <axsl:when test="$translation-{$attribute-name}"> 285 <axsl:attribute name="{$attribute-name}"><axsl:value-of select="$translation-{$attribute-name}"/></axsl:attribute> 286 </axsl:when> 287 <!-- Otherwise, just process the attribute. --> 288 <axsl:otherwise> 289 <axsl:attribute name="{$attribute-name}"><xsl:value-of select="$attribute-value"/></axsl:attribute> 290 </axsl:otherwise> 291 </axsl:choose> 292 </xsl:otherwise> 293 </xsl:choose> 294 </xsl:template> 295 296 297 298 <!-- Remove template attributes. --> 299 300 <xsl:template match="@template:element|@template:init|@template:attribute|@template:value|@template:expr|@template:expr-attr|@template:effect|@template:if|@template:i18n"> 301 </xsl:template> 302 303 304 305 <!-- Replicate unknown elements. --> 306 307 <xsl:template match="@*|node()"> 308 <xsl:copy> 309 <xsl:apply-templates select="@*|node()"/> 310 </xsl:copy> 311 </xsl:template> 312 313 </xsl:stylesheet>