XSLTools

XSLForms/XSL/Prepare.xsl

525:3726d27b821e
2006-03-17 paulb [project @ 2006-03-17 18:07:09 by paulb] Reordered the substitution preferences, making template:i18n more important than template:value. Added expression support to template:i18n annotations, along with a means of controlling the fallback output in cases where no translations are found for a value.
     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   xmlns:str="http://exslt.org/strings"    28   extension-element-prefixes="str">    29     30   <xsl:output indent="yes"/>    31   <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>    32     33   <!-- Fragment extraction support. -->    34   <xsl:param name="element-id"/>    35     36   <!-- Match the document itself. -->    37     38   <xsl:template match="/">    39     <axsl:stylesheet version="1.0"    40       xmlns:dyn="http://exslt.org/dynamic"    41       extension-element-prefixes="dyn">    42     43       <!-- Add support for special namespace declarations. -->    44       <xsl:for-each select="//@*[local-name() = 'expr-prefix']">    45         <xsl:attribute namespace="{namespace-uri()}" name="{name(.)}"></xsl:attribute>    46       </xsl:for-each>    47     48       <axsl:output indent="yes"/>    49     50       <!-- Include internationalisation (i18n) support if appropriate. -->    51       <axsl:param name="translations"/>    52       <axsl:param name="locale"/>    53     54       <!-- Include fragment support if appropriate. -->    55       <axsl:param name="element-path"/>    56     57       <axsl:template match="/">    58         <xsl:choose>    59           <!-- Fragment production. -->    60           <xsl:when test="$element-id != ''">    61             <axsl:for-each select="dyn:evaluate($element-path)">    62               <xsl:apply-templates select="@*|node()"/>    63             </axsl:for-each>    64           </xsl:when>    65           <!-- Whole template production. -->    66           <xsl:otherwise>    67             <xsl:apply-templates select="@*|node()"/>    68           </xsl:otherwise>    69         </xsl:choose>    70       </axsl:template>    71     72       <!-- Produce the rules for each element. -->    73     74       <xsl:apply-templates select="//*[@template:element]">    75         <xsl:with-param name="top-level">true</xsl:with-param>    76       </xsl:apply-templates>    77     78     </axsl:stylesheet>    79   </xsl:template>    80     81     82     83   <!-- Match elements referencing elements. -->    84     85   <xsl:template match="*[@template:element]" priority="1">    86     <xsl:param name="top-level">false</xsl:param>    87     <xsl:call-template name="enter-element">    88       <xsl:with-param name="top-level" select="$top-level"/>    89     </xsl:call-template>    90   </xsl:template>    91     92   <xsl:template name="enter-element">    93     <xsl:param name="top-level"/>    94     <xsl:choose>    95       <!-- Produce templates where this is a top-level definition. -->    96       <xsl:when test="$top-level = 'true'">    97         <xsl:call-template name="element-template">    98           <xsl:with-param name="element-names" select="@template:element"/>    99         </xsl:call-template>   100       </xsl:when>   101       <!-- Produce references to elements where this is within a template. -->   102       <xsl:otherwise>   103         <xsl:variable name="first-name" select="str:split(@template:element, ',')[1]"/>   104         <!-- Check to see if this is a recursive reference. -->   105         <xsl:variable name="recursive-element" select="ancestor::*[$first-name = str:split(@template:element, ',')[1]]"/>   106         <xsl:choose>   107           <!-- Generate a reference to the previous element definition. -->   108           <xsl:when test="$recursive-element">   109             <axsl:apply-templates select="{$first-name}" mode="{generate-id($recursive-element)}"/>   110           </xsl:when>   111           <!-- Generate a reference to this element definition. -->   112           <xsl:otherwise>   113             <axsl:apply-templates select="{$first-name}" mode="{generate-id(.)}"/>   114           </xsl:otherwise>   115         </xsl:choose>   116       </xsl:otherwise>   117     </xsl:choose>   118   </xsl:template>   119    120   <xsl:template name="element-template">   121     <xsl:param name="element-names"/>   122     <xsl:variable name="this-name" select="substring-before($element-names, ',')"/>   123     <xsl:variable name="next-names" select="substring-after($element-names, ',')"/>   124     <xsl:variable name="next-name" select="str:split($next-names, ',')[1]"/>   125     <xsl:choose>   126       <!-- Non-last part of a list of element names. -->   127       <!-- Produce a template referencing another template. -->   128       <xsl:when test="$this-name != ''">   129         <!-- Produce a template with a mode. -->   130         <axsl:template match="{$this-name}" mode="{generate-id(.)}">   131           <axsl:apply-templates select="{$next-name}" mode="{generate-id(.)}"/>   132         </axsl:template>   133         <!-- Produce the other elements' templates... -->   134         <xsl:call-template name="element-template">   135           <xsl:with-param name="element-names" select="$next-names"/>   136         </xsl:call-template>   137       </xsl:when>   138       <!-- Last part of a list of element names. -->   139       <!-- Produce a template with content. -->   140       <xsl:otherwise>   141         <!-- Produce a template with a mode. -->   142         <axsl:template match="{$element-names}" mode="{generate-id(.)}">   143           <xsl:call-template name="enter-attribute"/>   144         </axsl:template>   145       </xsl:otherwise>   146     </xsl:choose>   147   </xsl:template>   148    149    150    151   <!-- Match special conditional expression attributes. -->   152    153   <xsl:template match="*[@template:if]" priority="2">   154     <xsl:param name="top-level">false</xsl:param>   155     <xsl:choose>   156       <!-- Since this rule may be invoked at the top level, ignore conditions. -->   157       <xsl:when test="$top-level = 'true'">   158         <xsl:call-template name="enter-element">   159           <xsl:with-param name="top-level" select="$top-level"/>   160         </xsl:call-template>   161       </xsl:when>   162       <!-- As part of a template, generate the condition. -->   163       <xsl:otherwise>   164         <axsl:if test="{@template:if}">   165           <xsl:choose>   166             <xsl:when test="@template:element">   167               <xsl:call-template name="enter-element"/>   168             </xsl:when>   169             <xsl:otherwise>   170               <xsl:call-template name="enter-attribute"/>   171             </xsl:otherwise>   172           </xsl:choose>   173         </axsl:if>   174       </xsl:otherwise>   175     </xsl:choose>   176   </xsl:template>   177    178    179    180   <!-- Match special expression attributes. -->   181    182   <xsl:template match="*[@template:attribute or @template:value or @template:expr or @template:copy]">   183     <xsl:call-template name="enter-attribute"/>   184   </xsl:template>   185    186   <xsl:template name="enter-attribute">   187     <xsl:choose>   188       <xsl:when test="@template:attribute">   189         <axsl:choose>   190           <axsl:when test="@{@template:attribute}">   191             <axsl:variable name="this-name"><xsl:value-of select="@template:attribute"/></axsl:variable>   192             <axsl:variable name="this-value" select="@{@template:attribute}"/>   193             <xsl:call-template name="special-attributes"/>   194           </axsl:when>   195           <axsl:otherwise>   196             <axsl:variable name="this-name"><xsl:value-of select="@template:attribute"/></axsl:variable>   197             <axsl:variable name="this-value"></axsl:variable>   198             <xsl:call-template name="special-attributes"/>   199           </axsl:otherwise>   200         </axsl:choose>   201       </xsl:when>   202       <xsl:otherwise>   203         <xsl:call-template name="special-attributes"/>   204       </xsl:otherwise>   205     </xsl:choose>   206   </xsl:template>   207    208   <xsl:template name="special-attributes">   209     <xsl:choose>   210       <xsl:when test="@template:effect = 'replace'">   211         <xsl:call-template name="special-value"/>   212       </xsl:when>   213       <xsl:otherwise>   214         <xsl:copy>   215           <xsl:apply-templates select="@*"/>   216           <xsl:call-template name="expression-attributes"/>   217         </xsl:copy>   218       </xsl:otherwise>   219     </xsl:choose>   220   </xsl:template>   221    222   <xsl:template name="expression-attributes">   223     <xsl:if test="@template:expr and @template:expr-attr">   224       <axsl:if test="{@template:expr}">   225         <axsl:attribute name="{@template:expr-attr}"><xsl:value-of select="@template:expr-attr"/></axsl:attribute>   226       </axsl:if>   227     </xsl:if>   228     <xsl:call-template name="special-value"/>   229   </xsl:template>   230    231   <xsl:template name="special-value">   232     <xsl:choose>   233       <!-- Insert the translated value. -->   234       <xsl:when test="@template:i18n">   235         <xsl:call-template name="translated-value"/>   236       </xsl:when>   237       <!-- Insert the stated value. -->   238       <xsl:when test="@template:value">   239         <axsl:value-of select="{@template:value}"/>   240       </xsl:when>   241       <!-- Copy the stated expression. -->   242       <xsl:when test="@template:copy">   243         <axsl:copy-of select="{@template:copy}"/>   244       </xsl:when>   245       <!-- Just process the descendants. -->   246       <xsl:otherwise>   247         <xsl:apply-templates select="node()"/>   248       </xsl:otherwise>   249     </xsl:choose>   250   </xsl:template>   251    252    253    254   <!-- Match internationalisation attributes. -->   255    256   <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]">   257     <xsl:copy>   258       <xsl:apply-templates select="@*"/>   259       <xsl:call-template name="translated-value"/>   260     </xsl:copy>   261   </xsl:template>   262    263   <xsl:template name="translated-value">   264     <xsl:choose>   265       <!-- Look for a translation of the contents. -->   266       <xsl:when test="@template:i18n = '-'">   267         <!-- NOTE: Quoting not done completely. -->   268         <axsl:variable name="translation"   269           select="$translations/translations/locale[code/@value=$locale]/translation[@value='{text()}']/text()"/>   270         <xsl:call-template name="insert-translated-value"/>   271       </xsl:when>   272       <!-- Look for a translation based on the expression. -->   273       <xsl:when test="starts-with(@template:i18n, '{') and substring(@template:i18n, string-length(@template:i18n), 1) = '}'">   274         <!-- Select the expression. -->   275         <axsl:variable name="i18n-expr" select="{substring(@template:i18n, 2, string-length(@template:i18n) - 2)}"/>   276         <!-- Translate according to the expression. -->   277         <axsl:variable name="translation"   278           select="$translations/translations/locale[code/@value=$locale]/translation[@value=$i18n-expr]/text()"/>   279         <xsl:call-template name="insert-translated-value">   280           <xsl:with-param name="default">$i18n-expr</xsl:with-param>   281         </xsl:call-template>   282       </xsl:when>   283       <!-- Look for a named translation. -->   284       <xsl:otherwise>   285         <!-- NOTE: Quoting not done completely. -->   286         <axsl:variable name="translation"   287           select="$translations/translations/locale[code/@value=$locale]/translation[@value='{@template:i18n}']/text()"/>   288         <xsl:call-template name="insert-translated-value"/>   289       </xsl:otherwise>   290     </xsl:choose>   291   </xsl:template>   292    293   <xsl:template name="insert-translated-value">   294     <xsl:param name="default"/>   295     <axsl:choose>   296       <!-- Insert the translated value. -->   297       <axsl:when test="$translation">   298         <axsl:value-of select="$translation"/>   299       </axsl:when>   300       <!-- Otherwise, just process the descendants. -->   301       <axsl:otherwise>   302         <xsl:choose>   303           <xsl:when test="$default">   304             <axsl:value-of select="{$default}"/>   305           </xsl:when>   306           <xsl:otherwise>   307             <xsl:apply-templates select="node()"/>   308           </xsl:otherwise>   309         </xsl:choose>   310       </axsl:otherwise>   311     </axsl:choose>   312   </xsl:template>   313    314    315    316   <!-- Remove template attributes. -->   317    318   <xsl:template match="@template:element|@template:init|@template:attribute|@template:value|@template:expr|@template:expr-attr|@template:effect|@template:if|@template:i18n|@template:copy">   319   </xsl:template>   320    321    322    323   <!-- Remove special attributes for preserving namespace prefixes used in expressions. -->   324    325   <xsl:template match="@*[local-name() = 'expr-prefix']">   326   </xsl:template>   327    328    329    330   <!-- Replicate unknown elements. -->   331    332   <xsl:template match="@*|node()">   333     <xsl:copy>   334       <xsl:apply-templates select="@*|node()"/>   335     </xsl:copy>   336   </xsl:template>   337    338 </xsl:stylesheet>