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:call-template name="produce-selection"> 127 <xsl:with-param name="path" select="$path"/> 128 <xsl:with-param name="selection" select="concat($path, '/placeholder')"/> 129 <xsl:with-param name="element" select="element[1]"/> 130 </xsl:call-template> 131 132 </xsl:template> 133 134 135 136 <!-- Produce a selection of collection/dynamic elements. 137 This should produce an apply-templates instruction selecting dynamic elements. 138 For example: 139 ./placeholder|./some-element|./some-other-element --> 140 141 <xsl:template name="produce-selection"> 142 <xsl:param name="path"/> 143 <xsl:param name="selection"/> 144 <xsl:param name="element"/> 145 146 <xsl:choose> 147 <!-- After processing all elements, produce the selection instruction. --> 148 <xsl:when test="not($element)"> 149 <axsl:apply-templates select="{$selection}"/> 150 </xsl:when> 151 <!-- Otherwise, process the remaining elements. --> 152 <xsl:otherwise> 153 154 <!-- Define elements which do not have selectors. --> 155 <xsl:variable name="adding-selectors" select="count(//selector[@element=$element/@name])"/> 156 157 <xsl:choose> 158 <!-- Do not select added elements or enumerations - see process-elements. --> 159 <xsl:when test="((not($element/@init) or $element/@init = 'auto') and $adding-selectors = 0 or $element/@init = 'yes') 160 or (@type='multiple-choice-value' or @type='multiple-choice-list-value')"> 161 <xsl:call-template name="produce-selection"> 162 <xsl:with-param name="path" select="$path"/> 163 <xsl:with-param name="selection" select="$selection"/> 164 <xsl:with-param name="element" select="$element/following-sibling::element[1]"/> 165 </xsl:call-template> 166 </xsl:when> 167 <!-- Other elements are only added if found. --> 168 <xsl:otherwise> 169 <xsl:call-template name="produce-selection"> 170 <xsl:with-param name="path" select="$path"/> 171 <xsl:with-param name="selection" select="concat($selection, '|', $path, '/', $element/@name)"/> 172 <xsl:with-param name="element" select="$element/following-sibling::element[1]"/> 173 </xsl:call-template> 174 </xsl:otherwise> 175 </xsl:choose> 176 177 </xsl:otherwise> 178 </xsl:choose> 179 </xsl:template> 180 181 182 183 <!-- Process rules. --> 184 185 <xsl:template name="process-rules"> 186 <xsl:param name="path">.</xsl:param> 187 188 <xsl:for-each select="element"> 189 <!-- Define elements which do not have selectors. --> 190 <!-- NOTE: Duplicating adding-selectors - see above. --> 191 <xsl:variable name="adding-selectors" select="count(//selector[@element=current()/@name])"/> 192 193 <xsl:choose> 194 <xsl:when test="@type='multiple-choice-value' or @type='multiple-choice-list-value'"> 195 <!-- Do not match multiple-choice values. --> 196 </xsl:when> 197 <xsl:when test="(not(@init) or @init = 'auto') and $adding-selectors = 0 or @init = 'yes'"> 198 <xsl:call-template name="process-rules"> 199 <xsl:with-param name="path" select="concat($path, '/', @name)"/> 200 </xsl:call-template> 201 </xsl:when> 202 <xsl:otherwise> 203 <xsl:apply-templates select="."/> 204 </xsl:otherwise> 205 </xsl:choose> 206 </xsl:for-each> 207 </xsl:template> 208 209 210 211 <!-- Fill in enumerations. --> 212 213 <xsl:template name="inside-enumeration"> 214 <xsl:param name="path"/> 215 216 <!-- Store multiple-choice selections, if appropriate. --> 217 <xsl:if test="../@type='multiple-choice-list'"> 218 <!-- NOTE: It is assumed here that ../attribute/@name (if it exists) == attribute/@name. --> 219 <axsl:variable name="values-{@name}" select="{$path}/@{attribute/@name}"/> 220 </xsl:if> 221 222 <!-- Select inside the enumeration source, inside an element with the field's name, the enumeration elements. --> 223 <axsl:for-each select="${../@name}/{../@name}/{@name}"> 224 <axsl:copy> 225 <axsl:apply-templates select="@*"/> 226 <xsl:if test="@type='multiple-choice-list-value'"> 227 <axsl:if test="$values-{@name}[string() = current()/@{attribute/@name}]"> 228 <axsl:attribute name="{@expr-name}">true</axsl:attribute> 229 </axsl:if> 230 </xsl:if> 231 </axsl:copy> 232 </axsl:for-each> 233 </xsl:template> 234 235 </xsl:stylesheet>