1 <?xml version="1.0"?> 2 <!-- 3 Copyright (C) 2005 Paul Boddie <paul@boddie.org.uk> 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 --> 19 <xsl:stylesheet version="1.0" 20 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 21 xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias" 22 xmlns:template="http://www.boddie.org.uk/ns/xmltools/template"> 23 24 <xsl:output indent="yes"/> 25 <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/> 26 27 28 29 <!-- Match the document itself. --> 30 31 <xsl:template match="/"> 32 <axsl:stylesheet version="1.0"> 33 34 <axsl:output indent="yes"/> 35 36 <!-- Make document parameters for all elements appearing to use enumerations. --> 37 <xsl:for-each select="//element[@type='multiple-choice' or @type='multiple-choice-list']"> 38 <axsl:param name="{@name}"/> 39 </xsl:for-each> 40 41 <!-- Make a document-level rule. --> 42 <axsl:template match="/"> 43 <axsl:apply-templates select="*"/> 44 </axsl:template> 45 46 <!-- Process the top-level element to make other rules. --> 47 <xsl:apply-templates select="*"/> 48 49 <!-- Replicate unknown elements. --> 50 <axsl:template match="@*|placeholder|node()"> 51 <axsl:copy> 52 <axsl:apply-templates select="@*|node()"/> 53 </axsl:copy> 54 </axsl:template> 55 56 </axsl:stylesheet> 57 </xsl:template> 58 59 60 61 <!-- Match element references. --> 62 63 <xsl:template match="element"> 64 65 <!-- Make a rule for the element. --> 66 <axsl:template match="{@name}"> 67 68 <!-- Copy the element. --> 69 <xsl:element name="{@name}"> 70 71 <!-- Process attributes. --> 72 <axsl:apply-templates select="@*"/> 73 74 <!-- Find elements and determine how to process them. --> 75 <xsl:call-template name="process-elements"/> 76 </xsl:element> 77 </axsl:template> 78 79 <!-- Make rules for nested elements. --> 80 <xsl:call-template name="process-rules"/> 81 82 </xsl:template> 83 84 85 86 <!-- Process elements. --> 87 88 <xsl:template name="process-elements"> 89 <xsl:param name="path">.</xsl:param> 90 91 <!-- To ensure "stable ordering" of elements, the initialised/static elements are 92 added first; the collection/dynamic elements are added afterwards. This may not 93 necessarily match the schema, however. --> 94 95 <xsl:for-each select="element"> 96 <!-- Define elements which do not have selectors. --> 97 <xsl:variable name="adding-selectors" select="count(//selector[@element=current()/@name])"/> 98 99 <xsl:choose> 100 <!-- Enumerations. --> 101 <xsl:when test="@type='multiple-choice-value' or @type='multiple-choice-list-value'"> 102 <xsl:call-template name="inside-enumeration"> 103 <xsl:with-param name="path" select="concat($path, '/', @name)"/> 104 </xsl:call-template> 105 </xsl:when> 106 <!-- Added elements. --> 107 <xsl:when test="(not(@init) or @init = 'auto') and $adding-selectors = 0 or @init = 'yes'"> 108 <xsl:element name="{@name}"> 109 <axsl:apply-templates select="{$path}/{@name}/@*"/> 110 <xsl:call-template name="process-elements"> 111 <xsl:with-param name="path" select="concat($path, '/', @name)"/> 112 </xsl:call-template> 113 </xsl:element> 114 </xsl:when> 115 <!-- Other elements are only added if found and must appear last - see below. --> 116 <xsl:otherwise/> 117 </xsl:choose> 118 </xsl:for-each> 119 120 <!-- Add the collection/dynamic elements at the end. This includes placeholder 121 elements which may have represented the static elements. 122 NOTE: We may wish to exclude placeholder elements in any situation where static 123 NOTE: elements are employed, since the only place where keeping them around is 124 NOTE: necessary/meaningful is in dynamic element collections. --> 125 126 <xsl:for-each select="element"> 127 <!-- Define elements which do not have selectors. --> 128 <xsl:variable name="adding-selectors" select="count(//selector[@element=current()/@name])"/> 129 130 <xsl:choose> 131 <!-- Enumerations added first - see above. --> 132 <xsl:when test="@type='multiple-choice-value' or @type='multiple-choice-list-value'"/> 133 <!-- Added elements added first - see above. --> 134 <xsl:when test="(not(@init) or @init = 'auto') and $adding-selectors = 0 or @init = 'yes'"/> 135 <!-- Other elements are only added if found. --> 136 <xsl:otherwise> 137 <axsl:apply-templates select="{$path}/{@name}|{$path}/placeholder"/> 138 </xsl:otherwise> 139 </xsl:choose> 140 </xsl:for-each> 141 </xsl:template> 142 143 144 145 <!-- Process rules. --> 146 147 <xsl:template name="process-rules"> 148 <xsl:param name="path">.</xsl:param> 149 150 <xsl:for-each select="element"> 151 <!-- Define elements which do not have selectors. --> 152 <!-- NOTE: Duplicating adding-selectors - see above. --> 153 <xsl:variable name="adding-selectors" select="count(//selector[@element=current()/@name])"/> 154 155 <xsl:choose> 156 <xsl:when test="@type='multiple-choice-value' or @type='multiple-choice-list-value'"> 157 <!-- Do not match multiple-choice values. --> 158 </xsl:when> 159 <xsl:when test="(not(@init) or @init = 'auto') and $adding-selectors = 0 or @init = 'yes'"> 160 <xsl:call-template name="process-rules"> 161 <xsl:with-param name="path" select="concat($path, '/', @name)"/> 162 </xsl:call-template> 163 </xsl:when> 164 <xsl:otherwise> 165 <xsl:apply-templates select="."/> 166 </xsl:otherwise> 167 </xsl:choose> 168 </xsl:for-each> 169 </xsl:template> 170 171 172 173 <!-- Fill in enumerations. --> 174 175 <xsl:template name="inside-enumeration"> 176 <xsl:param name="path"/> 177 178 <!-- Store multiple-choice selections, if appropriate. --> 179 <xsl:if test="../@type='multiple-choice-list'"> 180 <!-- NOTE: It is assumed here that ../attribute/@name (if it exists) == attribute/@name. --> 181 <axsl:variable name="values-{@name}" select="{$path}/@{attribute/@name}"/> 182 </xsl:if> 183 184 <!-- Select inside the enumeration source, inside an element with the field's name, the enumeration elements. --> 185 <axsl:for-each select="${../@name}/{../@name}/{@name}"> 186 <axsl:copy> 187 <axsl:apply-templates select="@*"/> 188 <xsl:if test="@type='multiple-choice-list-value'"> 189 <axsl:if test="$values-{@name}[string() = current()/@{attribute/@name}]"> 190 <axsl:attribute name="{@expr-name}">true</axsl:attribute> 191 </axsl:if> 192 </xsl:if> 193 </axsl:copy> 194 </axsl:for-each> 195 </xsl:template> 196 197 </xsl:stylesheet>