forked from LegoStormtroopr/ramona-ddi-instrument-creator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DDI-Instrument_to_XForms.xsl
584 lines (570 loc) · 27.3 KB
/
DDI-Instrument_to_XForms.xsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:exslt="http://exslt.org/common" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ns1="ddi:instance:3_1" xmlns:a="ddi:archive:3_1" xmlns:r="ddi:reusable:3_1" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:dc="ddi:dcelements:3_1" xmlns:ns7="http://purl.org/dc/elements/1.1/" xmlns:cm="ddi:comparative:3_1" xmlns:d="ddi:datacollection:3_1" xmlns:l="ddi:logicalproduct:3_1" xmlns:c="ddi:conceptualcomponent:3_1" xmlns:ds="ddi:dataset:3_1" xmlns:p="ddi:physicaldataproduct:3_1" xmlns:pr="ddi:ddiprofile:3_1" xmlns:s="ddi:studyunit:3_1" xmlns:g="ddi:group:3_1" xmlns:pi="ddi:physicalinstance:3_1" xmlns:m3="ddi:physicaldataproduct_ncube_inline:3_1" xmlns:m1="ddi:physicaldataproduct_ncube_normal:3_1" xmlns:m2="ddi:physicaldataproduct_ncube_tabular:3_1" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:rml="http://legostormtoopr/response" xmlns:skip="http://legostormtoopr/skips" xmlns:cfg="rml:RamonaConfig_v1" exclude-result-prefixes="ns1 a r dc ns7 cm d l c ds p pr s g pi m3 m1 m2 exslt skip cfg" extension-element-prefixes="exslt">
<!-- Import the XSLT for turning a responseML document into the skip patterns needed for conditional questions. -->
<xsl:import href="./DDI_to_ResponseML.xsl"/>
<xsl:import href="./DDIReferenceResolver.xsl"/>
<xsl:import href="./configTransformations.xsl"/>
<!-- We are outputing XHTML so the output method will be XML, not HTML -->
<xsl:output method="xml"/>
<!-- Read in the configuration file. This contains information about how the XForm is to be created and displayed. Including CSS file locations and language information. -->
<xsl:variable name="config" select="document('./config.xml')/cfg:config"/>
<!-- Based on the deployer Environment, determine the correct path to the theme specific configuration file -->
<xsl:variable name="theme_file">
<xsl:choose>
<!-- If we are deployed on an eXist-db install construct the correct path to the theme config -->
<xsl:when test="$config/cfg:environment = 'exist-db'">
<xsl:copy-of select="concat('./themes/',$config/cfg:themeName,'/theme.xml')"/>
</xsl:when>
<!-- If we don't know the deployed environment assume the theme is in the default distribution directory -->
<xsl:otherwise>
<xsl:copy-of select="concat('./themes/',$config/cfg:themeName,'/theme.xml')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- The concat below is a work around to pull the correct theme file. If you just try and use this:
<xsl:variable name="theme" select="document($theme_file)/theme"/>
It will fail, for some as of yet undetermined reason.
-->
<xsl:variable name="theme" select="document(concat('',$theme_file,''))/cfg:theme"/>
<!--
Create the instrument for the XForms Model. This is represntation of the "true XML hierarchy" of the questionnaire (as opposed to the referential hiearchy of the DDI Document
This is created as a global variable as it is needed in several different places for processing.
The generated XML model of the questionnaire is needed for the data model of the final XForm, and exists as a ResponseML document.
-->
<!--
==============================
MAIN ENTRY POINT FOR TRANSFORM
==============================
This matches on the root element of the DDI Document so everything is done once. At present it searches for the instrument with a software tag of "XForms-Ramona"
In future, this may search for ALL instruments and create one XForms for each instrument or alternatively, accept a list of instrument ids in config.xml and only process those.
-->
<xsl:template match="/">
<xsl:processing-instruction name="xml-stylesheet">href="<xsl:if test="$config/cfg:xsltformsLocation/@relative=true()">
<xsl:value-of select="$config/cfg:rootURN"/>
</xsl:if>
<xsl:value-of select="$config/cfg:xsltformsLocation"/>" type="text/xsl"</xsl:processing-instruction>
<xsl:processing-instruction name="xsltforms-options">debug="no"</xsl:processing-instruction>
<xsl:apply-templates select="//d:Instrument"/>
</xsl:template>
<!--
This template matches for instruments and creates the boiler plate for the final XHTML+XForms Document.
It creates sections to hold a side menu linking within the page to all the major sections (div.majorsections), and main section for the survey itself (div.survey)
There is the assumption that whatever calls this process will construct a DDI document with only one instrument.
This assumption is based on the fact that only one survey instrument would be displayed to a respondent at a time.
Prints the instrument name and description, and processes the single, valid ControlConstruct contained within the DDI Instrument.
-->
<xsl:template match="d:Instrument">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<head>
<title>
<xsl:apply-templates select="d:InstrumentName"/>
</title>
<!-- Link to the CSS for rendering the form -->
<xsl:apply-templates select="$theme/cfg:styles/*"/>
<!-- Xforms Data model and bindings, including the ResponseML data instance. -->
<xf:model>
<xf:instance>
<xsl:call-template name="dataModelBuilder"/>
</xf:instance>
<xsl:call-template name="makeBindings"/>
<xf:submission id="saveLocally" method="put" action="file://C:/temp/saved_survey.xml"/>
<xf:submission id="saveRemotely" method="post" action="{$config/cfg:serverSubmitURI}"/>
</xf:model>
</head>
<body>
<div id="majorsections">
<xsl:apply-templates select="$theme/cfg:logo"/>
<h2>Major Sections</h2>
<ol>
<xsl:for-each select="//d:Sequence">
<xsl:if test="./r:Label">
<li>
<xsl:element name="a">
<xsl:attribute name="href">#<xsl:value-of select="@id"/></xsl:attribute>
<xsl:apply-templates select="./r:Label" mode="sidebar"/>
</xsl:element>
</li>
</xsl:if>
</xsl:for-each>
</ol>
</div>
<div id="survey">
<xsl:variable name="construct">
<xsl:value-of select="d:ControlConstructReference/r:ID"/>
</xsl:variable>
<h1>
<xsl:apply-templates select="d:InstrumentName"/>
</h1>
<div class="instrumentDescription">
<xsl:apply-templates select="r:Description"/>
</div>
<xsl:apply-templates select="//d:Sequence[@id=$construct]" mode="master"/>
<xf:submit submission="saveLocally">
<xf:label>Save data locally</xf:label>
</xf:submit>
<xf:submit submission="saveRemotely">
<xf:label>Submit</xf:label>
</xf:submit>
</div>
</body>
</html>
</xsl:template>
<!--
Process the main sequence for the Instrument. In future this will include section numbering, but for now its just like the regular sequence template
-->
<xsl:template match="d:Sequence" mode="master">
<div class="mainForm">
<xsl:comment>Start of <xsl:value-of select="@id"/>
</xsl:comment>
<xsl:apply-templates select="d:ControlConstructReference" mode="DDIReferenceResolver_3_1"/>
<xsl:comment>End of <xsl:value-of select="@id"/>
</xsl:comment>
</div>
</xsl:template>
<!--
Process a DDI Sequence.
Finds all referenced ControlConstructs and processes them.
-->
<xsl:template match="d:Sequence">
<!-- xsl:element name="xf:group" -->
<div id="{@id}" class="sequence">
<xsl:if test="r:Label">
<h2 class="sectionTitle">
<xsl:apply-templates select="r:Label"/>
</h2>
</xsl:if>
<xsl:apply-templates select="d:ControlConstructReference" mode="DDIReferenceResolver_3_1"/>
<xsl:comment>End of <xsl:value-of select="@id"/>
</xsl:comment>
</div>
<!-- /xsl:element -->
</xsl:template>
<!--
Process IfThenElse Constructs and their child Then and Else elements.
Both the Then and Else are wrapped in an XForms group. Then and Else get expressed as child XForms groups of this with bindings to allow or disallow response accordingly.
Referenced ControlConstructs in the Then and Else blocks are then processed.
At this point ElseIf constructs are ignored.
-->
<xsl:template match="d:IfThenElse">
<!-- xsl:element name="xf:group" -->
<xsl:comment>Start of <xsl:value-of select="@id"/>
</xsl:comment>
<xsl:apply-templates select="./d:ThenConstructReference">
<xsl:with-param name="ifID">
<xsl:value-of select="@id"/>
</xsl:with-param>
</xsl:apply-templates>
<xsl:apply-templates select="./d:ElseConstructReference">
<xsl:with-param name="ifID">
<xsl:value-of select="@id"/>
</xsl:with-param>
</xsl:apply-templates>
<!-- /xsl:element -->
<xsl:comment>End of <xsl:value-of select="@id"/>
</xsl:comment>
</xsl:template>
<xsl:template match="d:ThenConstructReference">
<xsl:param name="ifID"/>
<xsl:element name="xf:group">
<xsl:attribute name="class">conditionalBranch</xsl:attribute>
<xsl:attribute name="bind">bindThen-<xsl:value-of select="$ifID"/></xsl:attribute>
<xsl:comment>Start of <xsl:value-of select="@id"/></xsl:comment>
<xsl:apply-templates select="." mode="DDIReferenceResolver_3_1"/>
<xsl:comment>End of <xsl:value-of select="@id"/></xsl:comment>
</xsl:element>
</xsl:template>
<xsl:template match="d:ElseConstructReference">
<xsl:param name="ifID"/>
<xsl:element name="xf:group">
<xsl:attribute name="class">conditionalBranch</xsl:attribute>
<xsl:attribute name="bind">bindElse-<xsl:value-of select="$ifID"/></xsl:attribute>
<xsl:comment>Start of <xsl:value-of select="@id"/></xsl:comment>
<xsl:apply-templates select="." mode="DDIReferenceResolver_3_1"/>
<xsl:comment>End of <xsl:value-of select="@id"/></xsl:comment>
</xsl:element>
</xsl:template>
<!--
Processing instructions for text like objects in DDI.
Finds the text of the specified languages and prints it out.
-->
<xsl:template match="d:Instruction">
<div class="InterviewerInstruction"><em>Note:</em>
<xsl:apply-templates select="d:InstructionText"/>
</div>
</xsl:template>
<xsl:template match="r:Description">
<xsl:if test="ancestor-or-self::*[attribute::xml:lang][1]/@xml:lang=$config/cfg:language">
<xsl:apply-templates select="* | text()"/>
</xsl:if>
</xsl:template>
<xsl:template match="d:StatementItem">
<div class="statement">
<xsl:apply-templates select="./*"/>
</div>
</xsl:template>
<xsl:template match="d:InterviewerInstructionReference">
<xsl:variable name="instID">
<xsl:value-of select="r:ID"/>
</xsl:variable>
<xsl:apply-templates select="//d:Instruction[@id=$instID]"/>
</xsl:template>
<xsl:template match="d:InstrumentName | r:Label">
<xsl:if test="ancestor-or-self::*[attribute::xml:lang][1]/@xml:lang=$config/cfg:language">
<xsl:value-of select="."/>
</xsl:if>
</xsl:template>
<xsl:template match="d:InstructionText | d:DisplayText">
<xsl:if test="ancestor-or-self::*[attribute::xml:lang][1]/@xml:lang=$config/cfg:language">
<span>
<xsl:apply-templates select="*"/>
</span>
</xsl:if>
</xsl:template>
<xsl:template match="d:QuestionText">
<xsl:if test="ancestor-or-self::*[attribute::xml:lang][1]/@xml:lang=$config/cfg:language">
<span class="questionText">
<xsl:apply-templates select="*"/>
</span>
</xsl:if>
</xsl:template>
<xsl:template match="d:LiteralText">
<span class="words">
<xsl:apply-templates select="* | text()"/>
</span>
</xsl:template>
<xsl:template match="d:ConditionalText">
<span class="wordsub">
<xsl:element name="xf:output">
<xsl:attribute name="ref"><xsl:value-of select="./d:Expression/r:Code[@programmingLanguage='responseML_xpath1.0']/text()"/></xsl:attribute>
</xsl:element>
</span>
</xsl:template>
<!--
Copy XHTML tags across directly as we are making an XHTML document.
-->
<xsl:template match="xhtml:*">
<xsl:variable name="tagname">
<xsl:value-of select="local-name()"/>
</xsl:variable>
<xsl:element name="{$tagname}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="* | text()"/>
</xsl:element>
</xsl:template>
<!--
Transforms for managing Question objects - QuestionConstructs, QuestionItems, MultiQuestionItems.
These esentially reference, find and call templates to process the ResponseDomains.
-->
<xsl:template match="d:QuestionConstruct">
<xsl:variable name="qcID" select="@id"/>
<xsl:variable name="question">
<xsl:value-of select="d:QuestionReference/r:ID"/>
</xsl:variable>
<xsl:element name="div">
<xsl:attribute name="id"><xsl:value-of select="$qcID"/></xsl:attribute>
<xsl:attribute name="class">questionContainer</xsl:attribute>
<xsl:apply-templates select="d:InterviewerInstructionReference" mode="DDIReferenceResolver_3_1"/>
<xsl:apply-templates select="d:QuestionReference" mode="DDIReferenceResolver_3_1"/>
</xsl:element>
</xsl:template>
<xsl:template name="generateQuestionNumber">
<xsl:param name="qID"/>
<xsl:if test="$theme/cfg:question/@visible != false()">
<span class="questionNumber">
<xsl:value-of select="$theme/cfg:question/cfg:before"/>
<xsl:value-of select="exslt:node-set($numbers)/question[@id=$qID]"/>
<xsl:value-of select="$theme/cfg:question/cfg:after"/>
</span>
</xsl:if>
</xsl:template>
<xsl:template match="d:MultipleQuestionItem">
<xsl:variable name="id">
<xsl:value-of select="@id"/>
</xsl:variable>
<xsl:call-template name="generateQuestionNumber">
<xsl:with-param name="qID" select="@id"/>
</xsl:call-template>
<xsl:apply-templates select="d:QuestionText"/>
<ol class="subquestion">
<xsl:for-each select="d:SubQuestions/*">
<li><xsl:apply-templates select="."/></li>
</xsl:for-each>
</ol>
</xsl:template>
<xsl:template match="d:QuestionItem">
<xsl:variable name="id">
<xsl:value-of select="@id"/>
</xsl:variable>
<xsl:comment>Start of question <xsl:value-of select="@id"/>
</xsl:comment>
<xsl:if test="local-name(parent::node())!='SubQuestions'">
<xsl:call-template name="generateQuestionNumber">
<xsl:with-param name="qID" select="@id"/>
</xsl:call-template>
</xsl:if>
<xsl:apply-templates select="./d:NumericDomain | ./d:CodeDomain | ./d:TextDomain | ./d:DateTimeDomain | ./d:StructuredMixedResponseDomain | ./d:CategoryDomain">
<xsl:with-param name="qcID">
<xsl:choose>
<xsl:when test="local-name(parent::node())='SubQuestions'">
<xsl:value-of select="$id"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="exslt:node-set($instrumentModel)//*[@questionItemID=$id]/@id"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
</xsl:apply-templates>
<xsl:comment>End of question <xsl:value-of select="@id"/>
</xsl:comment>
</xsl:template>
<!--
The following chunk of templates take a ResponseDomain (eg. NumericDomain, StringDomain, CodeDomain, etc...) and output the required XForm control.
At the moment restrictions are not transformed across (eg. minimum or maximums in a range, etc...).
These restictions would not exist here however, and would be brought across as part of the binding process below, where and xml datatype and restrictions could be added.
-->
<xsl:template match="d:NumericDomain">
<xsl:param name="qcID"/>
<xsl:element name="xf:input">
<xsl:attribute name="type">xs:number</xsl:attribute>
<xsl:attribute name="bind">bindQuestion-<xsl:value-of select="$qcID"/></xsl:attribute>
<xf:label>
<xsl:apply-templates select="../d:QuestionText"/>
</xf:label>
</xsl:element>
</xsl:template>
<xsl:template match="d:StructuredMixedResponseDomain">
<xsl:param name="qcID"/>
<span>
<xsl:apply-templates select="../d:QuestionText"/>
</span>
<div style="padding-left:35px;">
<xsl:apply-templates select="./*">
<xsl:with-param name="qcID">
<xsl:value-of select="$qcID"/>
</xsl:with-param>
</xsl:apply-templates>
</div>
</xsl:template>
<!-- If the maximum length for a TextDomain is over 500, we can consdier this a text area, rather than just a simple input box -->
<xsl:template match="d:TextDomain[@maxLength>1000]">
<xsl:param name="qcID"/>
<xsl:element name="xf:textarea">
<xsl:attribute name="bind">bindQuestion-<xsl:value-of select="$qcID"/></xsl:attribute>
<xsl:attribute name="cols">50</xsl:attribute>
<xsl:attribute name="rows"><xsl:value-of select="./@maxLength div 500"/></xsl:attribute>
<xf:label>
<xsl:apply-templates select="../d:QuestionText"/>
</xf:label>
</xsl:element>
<xsl:apply-templates select="./r:Label"/>
</xsl:template> <xsl:template match="d:TextDomain">
<xsl:param name="qcID"/>
<xsl:element name="xf:input">
<xsl:attribute name="bind">bindQuestion-<xsl:value-of select="$qcID"/></xsl:attribute>
<xf:label>
<xsl:apply-templates select="../d:QuestionText"/>
</xf:label>
</xsl:element>
<xsl:apply-templates select="./r:Label"/>
</xsl:template>
<xsl:template match="d:DateTimeDomain">
<xsl:param name="qcID"/>
<xsl:element name="xf:input">
<xsl:attribute name="bind">bindQuestion-<xsl:value-of select="$qcID"/></xsl:attribute>
<xf:label>
<xsl:apply-templates select="../d:QuestionText"/>
</xf:label>
</xsl:element>
</xsl:template>
<xsl:template match="d:CodeDomain">
<xsl:param name="qcID"/>
<xsl:param name="subquestion"/>
<xsl:variable name="codeSchemeID">
<xsl:value-of select="r:CodeSchemeReference/r:ID"/>
</xsl:variable>
<xsl:element name="xf:select1">
<xsl:attribute name="bind">bindQuestion-<xsl:value-of select="$qcID"/></xsl:attribute>
<xsl:attribute name="appearance"><xsl:value-of select="$theme/cfg:codeSchemeDisplay"/></xsl:attribute>
<xf:label>
<xsl:apply-templates select="../d:QuestionText"/>
</xf:label>
<xsl:for-each select="//l:CodeScheme[@id=$codeSchemeID]/l:Code">
<xsl:variable name="value"><xsl:value-of select="l:Value"/></xsl:variable>
<xsl:variable name="categoryID">
<xsl:value-of select="l:CategoryReference/r:ID"/>
</xsl:variable>
<xsl:if test="not($categoryID = 'cat-Admin-Other')">
<xsl:element name="xf:item">
<xsl:element name="xf:label">
<xsl:apply-templates select="//l:Category[@id=$categoryID]/r:Label[not(@type)]"/>
<xsl:if test="exslt:node-set($instrumentModel)//rml:condition[@question=$qcID]">
<xsl:choose>
<xsl:when test="exslt:node-set($skips)/skip:link[@from = $qcID and @condition = $value]">
<xsl:variable name="to"><xsl:value-of select="exslt:node-set($skips)/skip:link[@from = $qcID and @condition = $value]/@to"/></xsl:variable>
<span class="skipRemark">
<xsl:element name="xf:group">
<xsl:attribute name="bind">bindThen-<xsl:value-of select="exslt:node-set($skips)/skip:link[@from = $qcID and @condition = $value]/@ifID"/></xsl:attribute>
<xsl:element name="span">
<xsl:attribute name="class">skipStatement</xsl:attribute>
<xsl:attribute name="id"></xsl:attribute>
Go to <xsl:element name="a">
<xsl:attribute name="href">#<xsl:value-of select="$to"/></xsl:attribute>
Question <xsl:value-of select="exslt:node-set($numbers)/question[@qcID = $to]"/>
</xsl:element>
</xsl:element>
</xsl:element>
</span>
</xsl:when>
<xsl:when test="exslt:node-set($skips)/skip:link[@from = $qcID and @condition = 'otherwise']">
<xsl:variable name="to"><xsl:value-of select="exslt:node-set($skips)/skip:link[@from = $qcID and @condition = 'otherwise']/@to"/></xsl:variable>
<span class="skipRemark">
<xsl:element name="xf:group">
<xsl:attribute name="bind">bindElse-<xsl:value-of select="exslt:node-set($skips)/skip:link[@from = $qcID and @condition = 'otherwise']/@ifID"/></xsl:attribute>
<xsl:element name="span">
<xsl:attribute name="class">skipStatement</xsl:attribute>
Go to <xsl:element name="a">
<xsl:attribute name="href">#<xsl:value-of select="$to"/></xsl:attribute>
Question <xsl:value-of select="exslt:node-set($numbers)/question[@qcID = $to]"/>
</xsl:element>
</xsl:element>
</xsl:element>
</span>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:element>
<xsl:element name="xf:value">
<xsl:value-of select="$value"/>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:element>
<xsl:if test="//l:CodeScheme[@id=$codeSchemeID]/l:Code/l:CategoryReference/r:ID = 'cat-Admin-Other'">
<xsl:element name="xf:input">
<xsl:attribute name="bind">bindQuestion-<xsl:value-of select="$qcID"/></xsl:attribute>
<xf:label>
<xsl:apply-templates select="//l:Category[@id='cat-Admin-Other']/r:Label"/>
</xf:label>
</xsl:element>
</xsl:if>
</xsl:template>
<xsl:template match="d:CategoryDomain">
<xsl:param name="qcID"/>
<xsl:param name="subquestion"/>
<xsl:variable name="categorySchemeID">
<xsl:value-of select="r:CategorySchemeReference/r:ID"/>
</xsl:variable>
<xsl:element name="xf:select">
<xsl:attribute name="bind">bindQuestion-<xsl:value-of select="$qcID"/></xsl:attribute>
<xsl:attribute name="appearance">full</xsl:attribute>
<xf:label>
<xsl:apply-templates select="../d:QuestionText"/>
</xf:label>
<xsl:for-each select="//l:CategoryScheme[@id=$categorySchemeID]/l:Category">
<xsl:element name="xf:item">
<xsl:element name="xf:label">
<xsl:value-of select="r:Label"/>
</xsl:element>
<xsl:element name="xf:value">
<xsl:value-of select="position()"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
<!--
At the moment the computation items are used to manage population membership, and only those that have the specific "programmingLanguage" codes are brought across.
These are turned into xforms outputs, which unfortunately display the membership value (1 or 0) a the very bottom of the form. This can be hidden with CSS, but is still a bit of a hack.
Once I figure out how XML Events work and how to capture them, I should be able to wrap this in something else.
This works by checking the readonly status of the specificly bound population (which is in turn based on one or more questions which is captured in the binding).
If this readonly status changes the value of the membership is changed to either a 0 or 1 depending on if the respondant is in or out of the given population, based on
-->
<xsl:template match="d:ComputationItem">
<xsl:element name="xf:output">
<xsl:attribute name="bind">bindCI-<xsl:value-of select="@id"/></xsl:attribute>
<xf:action ev:event="xforms-readonly">
<xsl:element name="xf:setvalue">
<xsl:attribute name="bind">bindCI-<xsl:value-of select="@id"/></xsl:attribute>
<xsl:attribute name="value">0</xsl:attribute>
</xsl:element>
</xf:action>
<xf:action ev:event="xforms-readwrite">
<xsl:element name="xf:setvalue">
<xsl:attribute name="bind">bindCI-<xsl:value-of select="@id"/></xsl:attribute>
<xsl:attribute name="value">1</xsl:attribute>
</xsl:element>
</xf:action>
</xsl:element>
</xsl:template>
<xsl:template match="d:Note"/>
<!--
=====================
BINDING BUILDING MODES
=====================
This section creates a long list of XForms bindings that give the form it's dynamicness.
This gathers all QuestionConstructs and make binding, this can be quite expensive on the client end.
A better solution is to traverse the instrument tree again, and create bindings for only the appropriate constructs.
-->
<xsl:template name="makeBindings">
<xsl:apply-templates select="//d:QuestionConstruct" mode="bindings"/>
<xsl:apply-templates select="//d:IfThenElse" mode="bindings"/>
<xsl:apply-templates select="//d:ComputationItem" mode="bindings"/>
</xsl:template>
<!--
This section is a bit of a hack because XSLTForms doesn't dynamically prune not relevant nodes from the tree.
This means that instead of having tests on the existance of a population, we have to do tests to a value inside it - i.e the membership attribute.
In the normal ComputationItem template, this is output as an XForms output which using this binding changes the value of the population membership.
-->
<xsl:template match="d:ComputationItem" mode="bindings">
<xsl:variable name="mainpopulation">
<xsl:value-of select="substring-before(./d:Code/r:Code[@programmingLanguage='xforms1.0-Ramona-Population'],',')"/>
</xsl:variable>
<xsl:variable name="subpopulation">
<xsl:value-of select="substring-after(./d:Code/r:Code[@programmingLanguage='xforms1.0-Ramona-Population'],',')"/>
</xsl:variable>
<xsl:variable name="condition">
<xsl:value-of select="./d:Code/r:Code[@programmingLanguage='xforms1.0-Ramona-Conditional']"/>
</xsl:variable>
<xsl:element name="xf:bind">
<xsl:attribute name="id">bindCI-<xsl:value-of select="@id"/></xsl:attribute>
<xsl:attribute name="nodeset">//rml:population[@id='<xsl:value-of select="$mainpopulation"/>']//rml:subpopulation[@id='<xsl:value-of select="$subpopulation"/>']/@membership</xsl:attribute>
<!-- xsl:attribute name="relevant"><xsl:value-of select="$condition"/></xsl:attribute -->
<xsl:attribute name="readonly"><xsl:value-of select="$condition"/></xsl:attribute>
</xsl:element>
</xsl:template>
<!-- If we are dealing with a MultipleQuestionItem we need to mine through it to get the sub-responses, but we don't need to create a binding for it.
This doesn't process ElseIf blocks as those haven't been included yet as a useable conrol mechanism.
-->
<xsl:template match="d:QuestionConstruct[not(ancestor::d:ElseIf)]" mode="bindings">
<xsl:variable name="Qid" select="./d:QuestionReference/r:ID"/>
<xsl:if test="//d:QuestionItem[@id=$Qid]">
<xsl:element name="xf:bind">
<xsl:attribute name="id">bindQuestion-<xsl:value-of select="@id"/></xsl:attribute>
<xsl:attribute name="nodeset">//rml:response[@id='<xsl:value-of select="@id"/>']</xsl:attribute>
</xsl:element>
</xsl:if>
<xsl:apply-templates select="//d:MultipleQuestionItem[@id=$Qid]/d:SubQuestions//d:QuestionItem" mode="bindings"/>
</xsl:template>
<xsl:template match="//d:SubQuestions/d:QuestionItem" mode="bindings">
<xsl:element name="xf:bind">
<xsl:attribute name="id">bindQuestion-<xsl:value-of select="@id"/></xsl:attribute>
<xsl:attribute name="nodeset">//rml:subresponse[@id='<xsl:value-of select="@id"/>']</xsl:attribute>
</xsl:element>
</xsl:template>
<!-- ElseIfs are excluded as their conditions still aren't being added above cause they are hard :( -->
<xsl:template match="d:IfThenElse[not(ancestor::d:ElseIf)]" mode="bindings">
<xsl:element name="xf:bind">
<xsl:attribute name="id">bindThen-<xsl:value-of select="@id"/></xsl:attribute>
<xsl:attribute name="nodeset">//rml:if[@id='<xsl:value-of select="@id"/>']/rml:then</xsl:attribute>
<xsl:attribute name="relevant"><xsl:value-of select="d:IfCondition/r:Code[@programmingLanguage='responseML_xpath1.0']/text()"/></xsl:attribute>
<xsl:attribute name="readonly">not(<xsl:value-of select="d:IfCondition/r:Code[@programmingLanguage='responseML_xpath1.0']/text()"/>)</xsl:attribute>
</xsl:element>
<xsl:element name="xf:bind">
<xsl:attribute name="id">bindElse-<xsl:value-of select="@id"/></xsl:attribute>
<xsl:attribute name="nodeset">//rml:if[@id='<xsl:value-of select="@id"/>']/rml:else</xsl:attribute>
<xsl:attribute name="relevant">not(<xsl:value-of select="./d:IfCondition/r:Code[@programmingLanguage='responseML_xpath1.0']/text()"/>)</xsl:attribute>
<xsl:attribute name="readonly"><xsl:value-of select="./d:IfCondition/r:Code[@programmingLanguage='responseML_xpath1.0']/text()"/></xsl:attribute>
</xsl:element>
</xsl:template>
</xsl:stylesheet>