XSLTools

Annotated XSLForms/XSL/Input.xsl

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