1
|
<!--
|
2
|
|
3
|
********************************
|
4
|
The FunctX XSLT Function Library
|
5
|
********************************
|
6
|
|
7
|
Copyright (C) 2007 Datypic
|
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.
|
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
|
For more information on the FunctX XSLT library, contact contrib@functx.com.
|
24
|
|
25
|
@version 1.0
|
26
|
@see http://www.xsltfunctions.com
|
27
|
-->
|
28
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dxmlf="http://www.datypic.com/xmlf" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:local="http://www.datypic.com/local" xmlns:functx="http://www.functx.com" exclude-result-prefixes="dxmlf xs" version="2.0">
|
29
|
|
30
|
<!--
|
31
|
Adds attributes to XML elements
|
32
|
|
33
|
@author Priscilla Walmsley, Datypic
|
34
|
@version 1.0
|
35
|
@see http://www.xsltfunctions.com/xsl/functx_add-attributes.html
|
36
|
@param $elements the element(s) to which you wish to add the attribute
|
37
|
@param $attrNames the name(s) of the attribute(s) to add
|
38
|
@param $attrValues the value(s) of the attribute(s) to add
|
39
|
-->
|
40
|
<xsl:function name="functx:add-attributes" as="element()?" xmlns:functx="http://www.functx.com">
|
41
|
<xsl:param name="elements" as="element()*"/>
|
42
|
<xsl:param name="attrNames" as="xs:QName*"/>
|
43
|
<xsl:param name="attrValues" as="xs:anyAtomicType*"/>
|
44
|
|
45
|
<xsl:for-each select="$elements">
|
46
|
<xsl:variable name="element" select="."/>
|
47
|
<xsl:copy>
|
48
|
<xsl:for-each select="$attrNames">
|
49
|
<xsl:variable name="seq" select="position()"/>
|
50
|
<xsl:if test="not($element/@*[node-name(.) = current()])">
|
51
|
<xsl:attribute name="{.}" namespace="{namespace-uri-from-QName(.)}" select="$attrValues[$seq]"/>
|
52
|
</xsl:if>
|
53
|
</xsl:for-each>
|
54
|
<xsl:copy-of select="@*|node()"/>
|
55
|
</xsl:copy>
|
56
|
</xsl:for-each>
|
57
|
|
58
|
</xsl:function>
|
59
|
|
60
|
|
61
|
<!--
|
62
|
Adds months to a date
|
63
|
|
64
|
@author Priscilla Walmsley, Datypic
|
65
|
@version 1.0
|
66
|
@see http://www.xsltfunctions.com/xsl/functx_add-months.html
|
67
|
@param $date the date
|
68
|
@param $months the number of months to add
|
69
|
-->
|
70
|
<xsl:function name="functx:add-months" as="xs:date?" xmlns:functx="http://www.functx.com">
|
71
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
72
|
<xsl:param name="months" as="xs:integer"/>
|
73
|
|
74
|
<xsl:sequence select=" xs:date($date) + functx:yearMonthDuration(0,$months) "/>
|
75
|
|
76
|
</xsl:function>
|
77
|
|
78
|
|
79
|
<!--
|
80
|
Adds attributes to XML elements
|
81
|
|
82
|
@author Priscilla Walmsley, Datypic
|
83
|
@version 1.0
|
84
|
@see http://www.xsltfunctions.com/xsl/functx_add-or-update-attributes.html
|
85
|
@param $elements the element(s) to which you wish to add the attribute
|
86
|
@param $attrNames the name(s) of the attribute(s) to add
|
87
|
@param $attrValues the value(s) of the attribute(s) to add
|
88
|
-->
|
89
|
<xsl:function name="functx:add-or-update-attributes" as="element()?" xmlns:functx="http://www.functx.com">
|
90
|
<xsl:param name="elements" as="element()*"/>
|
91
|
<xsl:param name="attrNames" as="xs:QName*"/>
|
92
|
<xsl:param name="attrValues" as="xs:anyAtomicType*"/>
|
93
|
|
94
|
<xsl:for-each select="$elements">
|
95
|
<xsl:copy>
|
96
|
<xsl:for-each select="$attrNames">
|
97
|
<xsl:variable name="seq" select="position()"/>
|
98
|
<xsl:attribute name="{.}" namespace="{namespace-uri-from-QName(.)}" select="$attrValues[$seq]"/>
|
99
|
</xsl:for-each>
|
100
|
<xsl:copy-of select="@*[not(node-name(.) = $attrNames)]|node()"/>
|
101
|
</xsl:copy>
|
102
|
</xsl:for-each>
|
103
|
|
104
|
</xsl:function>
|
105
|
|
106
|
|
107
|
<!--
|
108
|
Whether a value is all whitespace or a zero-length string
|
109
|
|
110
|
@author Priscilla Walmsley, Datypic
|
111
|
@version 1.0
|
112
|
@see http://www.xsltfunctions.com/xsl/functx_all-whitespace.html
|
113
|
@param $arg the string (or node) to test
|
114
|
-->
|
115
|
<xsl:function name="functx:all-whitespace" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
116
|
<xsl:param name="arg" as="xs:string?"/>
|
117
|
|
118
|
<xsl:sequence select=" normalize-space($arg) = '' "/>
|
119
|
|
120
|
</xsl:function>
|
121
|
|
122
|
|
123
|
<!--
|
124
|
Whether all the values in a sequence are distinct
|
125
|
|
126
|
@author Priscilla Walmsley, Datypic
|
127
|
@version 1.0
|
128
|
@see http://www.xsltfunctions.com/xsl/functx_are-distinct-values.html
|
129
|
@param $seq the sequence of values
|
130
|
-->
|
131
|
<xsl:function name="functx:are-distinct-values" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
132
|
<xsl:param name="seq" as="xs:anyAtomicType*"/>
|
133
|
|
134
|
<xsl:sequence select=" count(distinct-values($seq)) = count($seq) "/>
|
135
|
|
136
|
</xsl:function>
|
137
|
|
138
|
|
139
|
<!--
|
140
|
The built-in type of an atomic value
|
141
|
|
142
|
@author Priscilla Walmsley, Datypic
|
143
|
@version 1.0
|
144
|
@see http://www.xsltfunctions.com/xsl/functx_atomic-type.html
|
145
|
@param $values the value(s) whose type you want to determine
|
146
|
-->
|
147
|
<xsl:function name="functx:atomic-type" as="xs:string*" xmlns:functx="http://www.functx.com">
|
148
|
<xsl:param name="values" as="xs:anyAtomicType*"/>
|
149
|
|
150
|
<xsl:sequence select=" for $val in $values return (if ($val instance of xs:untypedAtomic) then 'xs:untypedAtomic' else if ($val instance of xs:anyURI) then 'xs:anyURI' else if ($val instance of xs:string) then 'xs:string' else if ($val instance of xs:QName) then 'xs:QName' else if ($val instance of xs:boolean) then 'xs:boolean' else if ($val instance of xs:base64Binary) then 'xs:base64Binary' else if ($val instance of xs:hexBinary) then 'xs:hexBinary' else if ($val instance of xs:integer) then 'xs:integer' else if ($val instance of xs:decimal) then 'xs:decimal' else if ($val instance of xs:float) then 'xs:float' else if ($val instance of xs:double) then 'xs:double' else if ($val instance of xs:date) then 'xs:date' else if ($val instance of xs:time) then 'xs:time' else if ($val instance of xs:dateTime) then 'xs:dateTime' else if ($val instance of xs:dayTimeDuration) then 'xs:dayTimeDuration' else if ($val instance of xs:yearMonthDuration) then 'xs:yearMonthDuration' else if ($val instance of xs:duration) then 'xs:duration' else if ($val instance of xs:gMonth) then 'xs:gMonth' else if ($val instance of xs:gYear) then 'xs:gYear' else if ($val instance of xs:gYearMonth) then 'xs:gYearMonth' else if ($val instance of xs:gDay) then 'xs:gDay' else if ($val instance of xs:gMonthDay) then 'xs:gMonthDay' else 'unknown') "/>
|
151
|
|
152
|
</xsl:function>
|
153
|
|
154
|
|
155
|
<!--
|
156
|
The average, counting "empty" values as zero
|
157
|
|
158
|
@author Priscilla Walmsley, Datypic
|
159
|
@version 1.0
|
160
|
@see http://www.xsltfunctions.com/xsl/functx_avg-empty-is-zero.html
|
161
|
@param $values the values to be averaged
|
162
|
@param $allNodes the sequence of all nodes to find the average over
|
163
|
-->
|
164
|
<xsl:function name="functx:avg-empty-is-zero" as="xs:double" xmlns:functx="http://www.functx.com">
|
165
|
<xsl:param name="values" as="xs:anyAtomicType*"/>
|
166
|
<xsl:param name="allNodes" as="node()*"/>
|
167
|
|
168
|
<xsl:sequence select=" if (empty($allNodes)) then 0 else sum($values[string(.) != '']) div count($allNodes) "/>
|
169
|
|
170
|
</xsl:function>
|
171
|
|
172
|
|
173
|
<!--
|
174
|
Whether a value is between two provided values
|
175
|
|
176
|
@author Priscilla Walmsley, Datypic
|
177
|
@version 1.0
|
178
|
@see http://www.xsltfunctions.com/xsl/functx_between-exclusive.html
|
179
|
@param $value the value to be tested
|
180
|
@param $minValue the minimum value
|
181
|
@param $maxValue the maximum value
|
182
|
-->
|
183
|
<xsl:function name="functx:between-exclusive" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
184
|
<xsl:param name="value" as="xs:anyAtomicType?"/>
|
185
|
<xsl:param name="minValue" as="xs:anyAtomicType"/>
|
186
|
<xsl:param name="maxValue" as="xs:anyAtomicType"/>
|
187
|
|
188
|
<xsl:sequence select=" $value > $minValue and $value < $maxValue "/>
|
189
|
|
190
|
</xsl:function>
|
191
|
|
192
|
|
193
|
<!--
|
194
|
Whether a value is between two provided values, or equal to one of them
|
195
|
|
196
|
@author Priscilla Walmsley, Datypic
|
197
|
@version 1.0
|
198
|
@see http://www.xsltfunctions.com/xsl/functx_between-inclusive.html
|
199
|
@param $value the value to be tested
|
200
|
@param $minValue the minimum value
|
201
|
@param $maxValue the maximum value
|
202
|
-->
|
203
|
<xsl:function name="functx:between-inclusive" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
204
|
<xsl:param name="value" as="xs:anyAtomicType?"/>
|
205
|
<xsl:param name="minValue" as="xs:anyAtomicType"/>
|
206
|
<xsl:param name="maxValue" as="xs:anyAtomicType"/>
|
207
|
|
208
|
<xsl:sequence select=" $value >= $minValue and $value <= $maxValue "/>
|
209
|
|
210
|
</xsl:function>
|
211
|
|
212
|
|
213
|
<!--
|
214
|
Turns a camelCase string into space-separated words
|
215
|
|
216
|
@author Priscilla Walmsley, Datypic
|
217
|
@version 1.0
|
218
|
@see http://www.xsltfunctions.com/xsl/functx_camel-case-to-words.html
|
219
|
@param $arg the string to modify
|
220
|
@param $delim the delimiter for the words (e.g. a space)
|
221
|
-->
|
222
|
<xsl:function name="functx:camel-case-to-words" as="xs:string" xmlns:functx="http://www.functx.com">
|
223
|
<xsl:param name="arg" as="xs:string?"/>
|
224
|
<xsl:param name="delim" as="xs:string"/>
|
225
|
|
226
|
<xsl:sequence select=" concat(substring($arg,1,1), replace(substring($arg,2),'(\p{Lu})', concat($delim, '$1'))) "/>
|
227
|
|
228
|
</xsl:function>
|
229
|
|
230
|
|
231
|
<!--
|
232
|
Capitalizes the first character of a string
|
233
|
|
234
|
@author Priscilla Walmsley, Datypic
|
235
|
@version 1.0
|
236
|
@see http://www.xsltfunctions.com/xsl/functx_capitalize-first.html
|
237
|
@param $arg the word or phrase to capitalize
|
238
|
-->
|
239
|
<xsl:function name="functx:capitalize-first" as="xs:string?" xmlns:functx="http://www.functx.com">
|
240
|
<xsl:param name="arg" as="xs:string?"/>
|
241
|
|
242
|
<xsl:sequence select=" concat(upper-case(substring($arg,1,1)), substring($arg,2)) "/>
|
243
|
|
244
|
</xsl:function>
|
245
|
|
246
|
|
247
|
<!--
|
248
|
Changes the names of elements in an XML fragment
|
249
|
|
250
|
@author Priscilla Walmsley, Datypic
|
251
|
@version 1.0
|
252
|
@see http://www.xsltfunctions.com/xsl/functx_change-element-names-deep.html
|
253
|
@param $nodes the element(s) to change
|
254
|
@param $oldNames the sequence of names to change from
|
255
|
@param $newNames the sequence of names to change to
|
256
|
-->
|
257
|
<xsl:function name="functx:change-element-names-deep" as="node()*" xmlns:functx="http://www.functx.com">
|
258
|
<xsl:param name="nodes" as="node()*"/>
|
259
|
<xsl:param name="oldNames" as="xs:QName*"/>
|
260
|
<xsl:param name="newNames" as="xs:QName*"/>
|
261
|
|
262
|
<xsl:if test="count($oldNames) != count($newNames)">
|
263
|
<xsl:sequence select="error( xs:QName('functx:Different_number_of_names'))"/>
|
264
|
</xsl:if>
|
265
|
<xsl:for-each select="$nodes">
|
266
|
<xsl:variable name="node" select="."/>
|
267
|
<xsl:choose>
|
268
|
<xsl:when test="$node instance of element()">
|
269
|
<xsl:variable name="theName" select="functx:if-empty ($newNames[index-of($oldNames, node-name($node))], node-name($node))"/>
|
270
|
<xsl:element name="{$theName}" namespace="{namespace-uri-from-QName($theName)}">
|
271
|
<xsl:sequence select="($node/@*, functx:change-element-names-deep($node/node(), $oldNames, $newNames))"/>
|
272
|
</xsl:element>
|
273
|
</xsl:when>
|
274
|
<xsl:when test="$node instance of document-node()">
|
275
|
<xsl:document>
|
276
|
<xsl:sequence select="functx:change-element-names-deep( $node/node(), $oldNames, $newNames)"/>
|
277
|
</xsl:document>
|
278
|
</xsl:when>
|
279
|
<xsl:otherwise>
|
280
|
<xsl:sequence select="$node"/>
|
281
|
</xsl:otherwise>
|
282
|
</xsl:choose>
|
283
|
</xsl:for-each>
|
284
|
|
285
|
</xsl:function>
|
286
|
|
287
|
|
288
|
<!--
|
289
|
Changes the namespace of XML elements and its descendants
|
290
|
|
291
|
@author Priscilla Walmsley, Datypic
|
292
|
@version 1.0
|
293
|
@see http://www.xsltfunctions.com/xsl/functx_change-element-ns-deep.html
|
294
|
@param $nodes the nodes to change
|
295
|
@param $newns the new namespace
|
296
|
@param $prefix the prefix to use for the new namespace
|
297
|
-->
|
298
|
<xsl:function name="functx:change-element-ns-deep" as="node()*" xmlns:functx="http://www.functx.com">
|
299
|
<xsl:param name="nodes" as="node()*"/>
|
300
|
<xsl:param name="newns" as="xs:string"/>
|
301
|
<xsl:param name="prefix" as="xs:string"/>
|
302
|
|
303
|
<xsl:for-each select="$nodes">
|
304
|
<xsl:variable name="node" select="."/>
|
305
|
<xsl:choose>
|
306
|
<xsl:when test="$node instance of element()">
|
307
|
<xsl:element name="{concat($prefix, if ($prefix = '') then '' else ':', local-name($node))}" namespace="{$newns}">
|
308
|
<xsl:sequence select="($node/@*, functx:change-element-ns-deep($node/node(), $newns, $prefix))"/>
|
309
|
</xsl:element>
|
310
|
</xsl:when>
|
311
|
<xsl:when test="$node instance of document-node()">
|
312
|
<xsl:document>
|
313
|
<xsl:sequence select="functx:change-element-ns-deep( $node/node(), $newns, $prefix)"/>
|
314
|
</xsl:document>
|
315
|
</xsl:when>
|
316
|
<xsl:otherwise>
|
317
|
<xsl:sequence select="$node"/>
|
318
|
</xsl:otherwise>
|
319
|
</xsl:choose>
|
320
|
</xsl:for-each>
|
321
|
|
322
|
</xsl:function>
|
323
|
|
324
|
|
325
|
<!--
|
326
|
Changes the namespace of XML elements
|
327
|
|
328
|
@author Priscilla Walmsley, Datypic
|
329
|
@version 1.0
|
330
|
@see http://www.xsltfunctions.com/xsl/functx_change-element-ns.html
|
331
|
@param $elements the elements to change
|
332
|
@param $newns the new namespace
|
333
|
@param $prefix the prefix to use for the new namespace
|
334
|
-->
|
335
|
<xsl:function name="functx:change-element-ns" as="element()?" xmlns:functx="http://www.functx.com">
|
336
|
<xsl:param name="elements" as="element()*"/>
|
337
|
<xsl:param name="newns" as="xs:string"/>
|
338
|
<xsl:param name="prefix" as="xs:string"/>
|
339
|
|
340
|
<xsl:for-each select="$elements">
|
341
|
<xsl:variable name="element" select="."/>
|
342
|
<xsl:element name="{concat($prefix, if ($prefix = '') then '' else ':', local-name($element))}" namespace="{$newns}">
|
343
|
<xsl:sequence select="$element/@*, $element/node()"/>
|
344
|
</xsl:element>
|
345
|
</xsl:for-each>
|
346
|
|
347
|
</xsl:function>
|
348
|
|
349
|
|
350
|
<!--
|
351
|
Converts a string to a sequence of characters
|
352
|
|
353
|
@author Priscilla Walmsley, Datypic
|
354
|
@version 1.0
|
355
|
@see http://www.xsltfunctions.com/xsl/functx_chars.html
|
356
|
@param $arg the string to split
|
357
|
-->
|
358
|
<xsl:function name="functx:chars" as="xs:string*" xmlns:functx="http://www.functx.com">
|
359
|
<xsl:param name="arg" as="xs:string?"/>
|
360
|
|
361
|
<xsl:sequence select=" for $ch in string-to-codepoints($arg) return codepoints-to-string($ch) "/>
|
362
|
|
363
|
</xsl:function>
|
364
|
|
365
|
|
366
|
<!--
|
367
|
Whether a string contains any of a sequence of strings
|
368
|
|
369
|
@author Priscilla Walmsley, Datypic
|
370
|
@version 1.0
|
371
|
@see http://www.xsltfunctions.com/xsl/functx_contains-any-of.html
|
372
|
@param $arg the string to test
|
373
|
@param $searchStrings the strings to look for
|
374
|
-->
|
375
|
<xsl:function name="functx:contains-any-of" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
376
|
<xsl:param name="arg" as="xs:string?"/>
|
377
|
<xsl:param name="searchStrings" as="xs:string*"/>
|
378
|
|
379
|
<xsl:sequence select=" some $searchString in $searchStrings satisfies contains($arg,$searchString) "/>
|
380
|
|
381
|
</xsl:function>
|
382
|
|
383
|
|
384
|
<!--
|
385
|
Whether one string contains another, without regard to case
|
386
|
|
387
|
@author Priscilla Walmsley, Datypic
|
388
|
@version 1.0
|
389
|
@see http://www.xsltfunctions.com/xsl/functx_contains-case-insensitive.html
|
390
|
@param $arg the string to search
|
391
|
@param $substring the substring to find
|
392
|
-->
|
393
|
<xsl:function name="functx:contains-case-insensitive" as="xs:boolean?" xmlns:functx="http://www.functx.com">
|
394
|
<xsl:param name="arg" as="xs:string?"/>
|
395
|
<xsl:param name="substring" as="xs:string"/>
|
396
|
|
397
|
<xsl:sequence select=" contains(upper-case($arg), upper-case($substring)) "/>
|
398
|
|
399
|
</xsl:function>
|
400
|
|
401
|
|
402
|
<!--
|
403
|
Whether one string contains another, as a separate word
|
404
|
|
405
|
@author Priscilla Walmsley, Datypic
|
406
|
@version 1.0
|
407
|
@see http://www.xsltfunctions.com/xsl/functx_contains-word.html
|
408
|
@param $arg the string to search
|
409
|
@param $word the word to find
|
410
|
-->
|
411
|
<xsl:function name="functx:contains-word" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
412
|
<xsl:param name="arg" as="xs:string?"/>
|
413
|
<xsl:param name="word" as="xs:string"/>
|
414
|
|
415
|
<xsl:sequence select=" matches(upper-case($arg), concat('^(.*\W)?', upper-case(functx:escape-for-regex($word)), '(\W.*)?$')) "/>
|
416
|
|
417
|
</xsl:function>
|
418
|
|
419
|
|
420
|
<!--
|
421
|
Copies attributes from one element to another
|
422
|
|
423
|
@author Priscilla Walmsley, Datypic
|
424
|
@version 1.0
|
425
|
@see http://www.xsltfunctions.com/xsl/functx_copy-attributes.html
|
426
|
@param $copyTo the element to copy attributes to
|
427
|
@param $copyFrom the element to copy attributes from
|
428
|
-->
|
429
|
<xsl:function name="functx:copy-attributes" as="element()" xmlns:functx="http://www.functx.com">
|
430
|
<xsl:param name="copyTo" as="element()"/>
|
431
|
<xsl:param name="copyFrom" as="element()"/>
|
432
|
|
433
|
<xsl:element name="{node-name($copyTo)}">
|
434
|
<xsl:sequence select=" ($copyTo/@*[not(node-name(.) = $copyFrom/@*/node-name(.))], $copyFrom/@*, $copyTo/node())"/>
|
435
|
</xsl:element>
|
436
|
|
437
|
</xsl:function>
|
438
|
|
439
|
|
440
|
<!--
|
441
|
Construct a date from a year, month and day
|
442
|
|
443
|
@author Priscilla Walmsley, Datypic
|
444
|
@version 1.0
|
445
|
@see http://www.xsltfunctions.com/xsl/functx_date.html
|
446
|
@param $year the year
|
447
|
@param $month the month
|
448
|
@param $day the day
|
449
|
-->
|
450
|
<xsl:function name="functx:date" as="xs:date" xmlns:functx="http://www.functx.com">
|
451
|
<xsl:param name="year" as="xs:anyAtomicType"/>
|
452
|
<xsl:param name="month" as="xs:anyAtomicType"/>
|
453
|
<xsl:param name="day" as="xs:anyAtomicType"/>
|
454
|
|
455
|
<xsl:sequence select=" xs:date( concat( functx:pad-integer-to-length(xs:integer($year),4),'-', functx:pad-integer-to-length(xs:integer($month),2),'-', functx:pad-integer-to-length(xs:integer($day),2))) "/>
|
456
|
|
457
|
</xsl:function>
|
458
|
|
459
|
|
460
|
<!--
|
461
|
Construct a date/time from individual components
|
462
|
|
463
|
@author Priscilla Walmsley, Datypic
|
464
|
@version 1.0
|
465
|
@see http://www.xsltfunctions.com/xsl/functx_datetime.html
|
466
|
@param $year the year
|
467
|
@param $month the month
|
468
|
@param $day the day
|
469
|
@param $hour the hour
|
470
|
@param $minute the minute
|
471
|
@param $second the second
|
472
|
-->
|
473
|
<xsl:function name="functx:dateTime" as="xs:dateTime" xmlns:functx="http://www.functx.com">
|
474
|
<xsl:param name="year" as="xs:anyAtomicType"/>
|
475
|
<xsl:param name="month" as="xs:anyAtomicType"/>
|
476
|
<xsl:param name="day" as="xs:anyAtomicType"/>
|
477
|
<xsl:param name="hour" as="xs:anyAtomicType"/>
|
478
|
<xsl:param name="minute" as="xs:anyAtomicType"/>
|
479
|
<xsl:param name="second" as="xs:anyAtomicType"/>
|
480
|
|
481
|
<xsl:sequence select=" xs:dateTime( concat(functx:date($year,$month,$day),'T', functx:time($hour,$minute,$second))) "/>
|
482
|
|
483
|
</xsl:function>
|
484
|
|
485
|
|
486
|
<!--
|
487
|
The day of the year (a number between 1 and 366)
|
488
|
|
489
|
@author Priscilla Walmsley, Datypic
|
490
|
@version 1.0
|
491
|
@see http://www.xsltfunctions.com/xsl/functx_day-in-year.html
|
492
|
@param $date the date
|
493
|
-->
|
494
|
<xsl:function name="functx:day-in-year" as="xs:integer?" xmlns:functx="http://www.functx.com">
|
495
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
496
|
|
497
|
<xsl:sequence select=" days-from-duration( xs:date($date) - functx:first-day-of-year($date)) + 1 "/>
|
498
|
|
499
|
</xsl:function>
|
500
|
|
501
|
|
502
|
<!--
|
503
|
The abbreviated day of the week, from a date, in English
|
504
|
|
505
|
@author Priscilla Walmsley, Datypic
|
506
|
@version 1.0
|
507
|
@see http://www.xsltfunctions.com/xsl/functx_day-of-week-abbrev-en.html
|
508
|
@param $date the date
|
509
|
-->
|
510
|
<xsl:function name="functx:day-of-week-abbrev-en" as="xs:string?" xmlns:functx="http://www.functx.com">
|
511
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
512
|
|
513
|
<xsl:sequence select=" ('Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat') [functx:day-of-week($date) + 1] "/>
|
514
|
|
515
|
</xsl:function>
|
516
|
|
517
|
|
518
|
<!--
|
519
|
The name of the day of the week, from a date, in English
|
520
|
|
521
|
@author Priscilla Walmsley, Datypic
|
522
|
@version 1.0
|
523
|
@see http://www.xsltfunctions.com/xsl/functx_day-of-week-name-en.html
|
524
|
@param $date the date
|
525
|
-->
|
526
|
<xsl:function name="functx:day-of-week-name-en" as="xs:string?" xmlns:functx="http://www.functx.com">
|
527
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
528
|
|
529
|
<xsl:sequence select=" ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday') [functx:day-of-week($date) + 1] "/>
|
530
|
|
531
|
</xsl:function>
|
532
|
|
533
|
|
534
|
<!--
|
535
|
The day of the week, from a date
|
536
|
|
537
|
@author Priscilla Walmsley, Datypic
|
538
|
@version 1.0
|
539
|
@see http://www.xsltfunctions.com/xsl/functx_day-of-week.html
|
540
|
@param $date the date
|
541
|
-->
|
542
|
<xsl:function name="functx:day-of-week" as="xs:integer?" xmlns:functx="http://www.functx.com">
|
543
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
544
|
|
545
|
<xsl:sequence select=" if (empty($date)) then () else xs:integer((xs:date($date) - xs:date('1901-01-06')) div xs:dayTimeDuration('P1D')) mod 7 "/>
|
546
|
|
547
|
</xsl:function>
|
548
|
|
549
|
|
550
|
<!--
|
551
|
Construct a dayTimeDuration from a number of days, hours, etc.
|
552
|
|
553
|
@author Priscilla Walmsley, Datypic
|
554
|
@version 1.0
|
555
|
@see http://www.xsltfunctions.com/xsl/functx_daytimeduration.html
|
556
|
@param $days the number of days
|
557
|
@param $hours the number of hours
|
558
|
@param $minutes the number of minutes
|
559
|
@param $seconds the number of seconds
|
560
|
-->
|
561
|
<xsl:function name="functx:dayTimeDuration" as="xs:dayTimeDuration" xmlns:functx="http://www.functx.com">
|
562
|
<xsl:param name="days" as="xs:decimal?"/>
|
563
|
<xsl:param name="hours" as="xs:decimal?"/>
|
564
|
<xsl:param name="minutes" as="xs:decimal?"/>
|
565
|
<xsl:param name="seconds" as="xs:decimal?"/>
|
566
|
|
567
|
<xsl:sequence select=" (xs:dayTimeDuration('P1D') * functx:if-empty($days,0)) + (xs:dayTimeDuration('PT1H') * functx:if-empty($hours,0)) + (xs:dayTimeDuration('PT1M') * functx:if-empty($minutes,0)) + (xs:dayTimeDuration('PT1S') * functx:if-empty($seconds,0)) "/>
|
568
|
|
569
|
</xsl:function>
|
570
|
|
571
|
|
572
|
<!--
|
573
|
Number of days in the month
|
574
|
|
575
|
@author Priscilla Walmsley, Datypic
|
576
|
@version 1.0
|
577
|
@see http://www.xsltfunctions.com/xsl/functx_days-in-month.html
|
578
|
@param $date the date
|
579
|
-->
|
580
|
<xsl:function name="functx:days-in-month" as="xs:integer?" xmlns:functx="http://www.functx.com">
|
581
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
582
|
|
583
|
<xsl:sequence select=" if (month-from-date(xs:date($date)) = 2 and functx:is-leap-year($date)) then 29 else (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) [month-from-date(xs:date($date))] "/>
|
584
|
|
585
|
</xsl:function>
|
586
|
|
587
|
|
588
|
<!--
|
589
|
The depth (level) of a node in an XML tree
|
590
|
|
591
|
@author Priscilla Walmsley, Datypic
|
592
|
@version 1.0
|
593
|
@see http://www.xsltfunctions.com/xsl/functx_depth-of-node.html
|
594
|
@param $node the node to check
|
595
|
-->
|
596
|
<xsl:function name="functx:depth-of-node" as="xs:integer" xmlns:functx="http://www.functx.com">
|
597
|
<xsl:param name="node" as="node()?"/>
|
598
|
|
599
|
<xsl:sequence select=" count($node/ancestor-or-self::node()) "/>
|
600
|
|
601
|
</xsl:function>
|
602
|
|
603
|
|
604
|
<!--
|
605
|
The distinct names of all attributes in an XML fragment
|
606
|
|
607
|
@author Priscilla Walmsley, Datypic
|
608
|
@version 1.0
|
609
|
@see http://www.xsltfunctions.com/xsl/functx_distinct-attribute-names.html
|
610
|
@param $nodes the root to start from
|
611
|
-->
|
612
|
<xsl:function name="functx:distinct-attribute-names" as="xs:string*" xmlns:functx="http://www.functx.com">
|
613
|
<xsl:param name="nodes" as="node()*"/>
|
614
|
|
615
|
<xsl:sequence select=" distinct-values($nodes//@*/name(.)) "/>
|
616
|
|
617
|
</xsl:function>
|
618
|
|
619
|
|
620
|
<!--
|
621
|
The XML nodes with distinct values, taking into account attributes and descendants
|
622
|
|
623
|
@author Priscilla Walmsley, Datypic
|
624
|
@version 1.0
|
625
|
@see http://www.xsltfunctions.com/xsl/functx_distinct-deep.html
|
626
|
@param $nodes the sequence of nodes to test
|
627
|
-->
|
628
|
<xsl:function name="functx:distinct-deep" as="node()*" xmlns:functx="http://www.functx.com">
|
629
|
<xsl:param name="nodes" as="node()*"/>
|
630
|
|
631
|
<xsl:sequence select=" for $seq in (1 to count($nodes)) return $nodes[$seq][not(functx:is-node-in-sequence-deep-equal( .,$nodes[position() < $seq]))] "/>
|
632
|
|
633
|
</xsl:function>
|
634
|
|
635
|
|
636
|
<!--
|
637
|
The distinct names of all elements in an XML fragment
|
638
|
|
639
|
@author Priscilla Walmsley, Datypic
|
640
|
@version 1.0
|
641
|
@see http://www.xsltfunctions.com/xsl/functx_distinct-element-names.html
|
642
|
@param $nodes the root(s) to start from
|
643
|
-->
|
644
|
<xsl:function name="functx:distinct-element-names" as="xs:string*" xmlns:functx="http://www.functx.com">
|
645
|
<xsl:param name="nodes" as="node()*"/>
|
646
|
|
647
|
<xsl:sequence select=" distinct-values($nodes/descendant-or-self::*/name(.)) "/>
|
648
|
|
649
|
</xsl:function>
|
650
|
|
651
|
|
652
|
<!--
|
653
|
The distinct paths of all descendant elements in an XML fragment
|
654
|
|
655
|
@author Priscilla Walmsley, Datypic
|
656
|
@version 1.0
|
657
|
@see http://www.xsltfunctions.com/xsl/functx_distinct-element-paths.html
|
658
|
@param $nodes the root(s) to start from
|
659
|
-->
|
660
|
<xsl:function name="functx:distinct-element-paths" as="xs:string*" xmlns:functx="http://www.functx.com">
|
661
|
<xsl:param name="nodes" as="node()*"/>
|
662
|
|
663
|
<xsl:sequence select=" distinct-values(functx:path-to-node($nodes/descendant-or-self::*)) "/>
|
664
|
|
665
|
</xsl:function>
|
666
|
|
667
|
|
668
|
<!--
|
669
|
The distinct XML nodes in a sequence (by node identity)
|
670
|
|
671
|
@author Priscilla Walmsley, Datypic
|
672
|
@version 1.0
|
673
|
@see http://www.xsltfunctions.com/xsl/functx_distinct-nodes.html
|
674
|
@param $nodes the node sequence
|
675
|
-->
|
676
|
<xsl:function name="functx:distinct-nodes" as="node()*" xmlns:functx="http://www.functx.com">
|
677
|
<xsl:param name="nodes" as="node()*"/>
|
678
|
|
679
|
<xsl:sequence select=" for $seq in (1 to count($nodes)) return $nodes[$seq][not(functx:is-node-in-sequence( .,$nodes[position() < $seq]))] "/>
|
680
|
|
681
|
</xsl:function>
|
682
|
|
683
|
|
684
|
<!--
|
685
|
Converts a timezone like "-05:00" or "Z" into xs:dayTimeDuration
|
686
|
|
687
|
@author Priscilla Walmsley, Datypic
|
688
|
@version 1.0
|
689
|
@see http://www.xsltfunctions.com/xsl/functx_duration-from-timezone.html
|
690
|
@param $timezone the time zone, in (+|-)HH:MM format
|
691
|
-->
|
692
|
<xsl:function name="functx:duration-from-timezone" as="xs:dayTimeDuration" xmlns:functx="http://www.functx.com">
|
693
|
<xsl:param name="timezone" as="xs:string"/>
|
694
|
|
695
|
<xsl:sequence select=" xs:dayTimeDuration( if (not(matches($timezone,'Z|[\+\-]\d{2}:\d{2}'))) then error(xs:QName('functx:Invalid_Timezone_Value')) else if ($timezone = 'Z') then 'PT0S' else replace($timezone,'\+?(\d{2}):\d{2}','PT$1H') ) "/>
|
696
|
|
697
|
</xsl:function>
|
698
|
|
699
|
|
700
|
<!--
|
701
|
Dynamically evaluates a simple XPath path
|
702
|
|
703
|
@author Priscilla Walmsley, Datypic
|
704
|
@version 1.0
|
705
|
@see http://www.xsltfunctions.com/xsl/functx_dynamic-path.html
|
706
|
@param $parent the root to start from
|
707
|
@param $path the path expression
|
708
|
-->
|
709
|
<xsl:function name="functx:dynamic-path" as="item()*" xmlns:functx="http://www.functx.com">
|
710
|
<xsl:param name="parent" as="node()"/>
|
711
|
<xsl:param name="path" as="xs:string"/>
|
712
|
|
713
|
<xsl:variable name="nextStep" select="functx:substring-before-if-contains($path,'/')"/>
|
714
|
<xsl:variable name="restOfSteps" select="substring-after($path,'/')"/>
|
715
|
<xsl:for-each select=" ($parent/*[functx:name-test(name(),$nextStep)], $parent/@*[functx:name-test(name(), substring-after($nextStep,'@'))])">
|
716
|
<xsl:variable name="child" select="."/>
|
717
|
<xsl:sequence select="if ($restOfSteps) then functx:dynamic-path($child, $restOfSteps) else $child"/>
|
718
|
</xsl:for-each>
|
719
|
|
720
|
</xsl:function>
|
721
|
|
722
|
|
723
|
<!--
|
724
|
Escapes regex special characters
|
725
|
|
726
|
@author Priscilla Walmsley, Datypic
|
727
|
@version 1.0
|
728
|
@see http://www.xsltfunctions.com/xsl/functx_escape-for-regex.html
|
729
|
@param $arg the string to escape
|
730
|
-->
|
731
|
<xsl:function name="functx:escape-for-regex" as="xs:string" xmlns:functx="http://www.functx.com">
|
732
|
<xsl:param name="arg" as="xs:string?"/>
|
733
|
|
734
|
<xsl:sequence select=" replace($arg, '(\.|\[|\]|\\|\||\-|\^|\$|\?|\*|\+|\{|\}|\(|\))','\\$1') "/>
|
735
|
|
736
|
</xsl:function>
|
737
|
|
738
|
|
739
|
<!--
|
740
|
Whether one (and only one) of two boolean values is true
|
741
|
|
742
|
@author Priscilla Walmsley, Datypic
|
743
|
@version 1.0
|
744
|
@see http://www.xsltfunctions.com/xsl/functx_exclusive-or.html
|
745
|
@param $arg1 the first boolean value
|
746
|
@param $arg2 the second boolean value
|
747
|
-->
|
748
|
<xsl:function name="functx:exclusive-or" as="xs:boolean?" xmlns:functx="http://www.functx.com">
|
749
|
<xsl:param name="arg1" as="xs:boolean?"/>
|
750
|
<xsl:param name="arg2" as="xs:boolean?"/>
|
751
|
|
752
|
<xsl:sequence select=" $arg1 != $arg2 "/>
|
753
|
|
754
|
</xsl:function>
|
755
|
|
756
|
|
757
|
<!--
|
758
|
The first day of the month of a date
|
759
|
|
760
|
@author Priscilla Walmsley, Datypic
|
761
|
@version 1.0
|
762
|
@see http://www.xsltfunctions.com/xsl/functx_first-day-of-month.html
|
763
|
@param $date the date
|
764
|
-->
|
765
|
<xsl:function name="functx:first-day-of-month" as="xs:date?" xmlns:functx="http://www.functx.com">
|
766
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
767
|
|
768
|
<xsl:sequence select=" functx:date(year-from-date(xs:date($date)), month-from-date(xs:date($date)), 1) "/>
|
769
|
|
770
|
</xsl:function>
|
771
|
|
772
|
|
773
|
<!--
|
774
|
The first day of the year of a date
|
775
|
|
776
|
@author Priscilla Walmsley, Datypic
|
777
|
@version 1.0
|
778
|
@see http://www.xsltfunctions.com/xsl/functx_first-day-of-year.html
|
779
|
@param $date the date
|
780
|
-->
|
781
|
<xsl:function name="functx:first-day-of-year" as="xs:date?" xmlns:functx="http://www.functx.com">
|
782
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
783
|
|
784
|
<xsl:sequence select=" functx:date(year-from-date(xs:date($date)), 1, 1) "/>
|
785
|
|
786
|
</xsl:function>
|
787
|
|
788
|
|
789
|
<!--
|
790
|
The XML node in a sequence that appears first in document order
|
791
|
|
792
|
@author Priscilla Walmsley, Datypic
|
793
|
@version 1.0
|
794
|
@see http://www.xsltfunctions.com/xsl/functx_first-node.html
|
795
|
@param $nodes the sequence of nodes
|
796
|
-->
|
797
|
<xsl:function name="functx:first-node" as="node()?" xmlns:functx="http://www.functx.com">
|
798
|
<xsl:param name="nodes" as="node()*"/>
|
799
|
|
800
|
<xsl:sequence select=" ($nodes/.)[1] "/>
|
801
|
|
802
|
</xsl:function>
|
803
|
|
804
|
|
805
|
<!--
|
806
|
Whether an XML node follows another without being its descendant
|
807
|
|
808
|
@author W3C XML Query Working Group
|
809
|
@version 1.0
|
810
|
@see http://www.xsltfunctions.com/xsl/functx_follows-not-descendant.html
|
811
|
@param $a the first node
|
812
|
@param $b the second node
|
813
|
-->
|
814
|
<xsl:function name="functx:follows-not-descendant" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
815
|
<xsl:param name="a" as="node()?"/>
|
816
|
<xsl:param name="b" as="node()?"/>
|
817
|
|
818
|
<xsl:sequence select=" $a >> $b and empty($b intersect $a/ancestor::node()) "/>
|
819
|
|
820
|
</xsl:function>
|
821
|
|
822
|
|
823
|
<!--
|
824
|
Moves title words like "the" and "a" to the end of strings
|
825
|
|
826
|
@author Priscilla Walmsley, Datypic
|
827
|
@version 1.0
|
828
|
@see http://www.xsltfunctions.com/xsl/functx_format-as-title-en.html
|
829
|
@param $titles the titles to format
|
830
|
-->
|
831
|
<xsl:function name="functx:format-as-title-en" as="xs:string*" xmlns:functx="http://www.functx.com">
|
832
|
<xsl:param name="titles" as="xs:string*"/>
|
833
|
|
834
|
<xsl:variable name="wordsToMoveToEnd" select="('A', 'An', 'The')"/>
|
835
|
<xsl:for-each select="$titles">
|
836
|
<xsl:variable name="title" select="."/>
|
837
|
<xsl:variable name="firstWord" select="functx:substring-before-match($title,'\W')"/>
|
838
|
<xsl:sequence select="if ($firstWord = $wordsToMoveToEnd) then replace($title,'(.*?)\W(.*)', '$2, $1') else $title"/>
|
839
|
</xsl:for-each>
|
840
|
|
841
|
</xsl:function>
|
842
|
|
843
|
|
844
|
<!--
|
845
|
Returns the fragment from a URI
|
846
|
|
847
|
@author Priscilla Walmsley, Datypic
|
848
|
@version 1.0
|
849
|
@see http://www.xsltfunctions.com/xsl/functx_fragment-from-uri.html
|
850
|
@param $uri the URI
|
851
|
-->
|
852
|
<xsl:function name="functx:fragment-from-uri" as="xs:string?" xmlns:functx="http://www.functx.com">
|
853
|
<xsl:param name="uri" as="xs:string?"/>
|
854
|
|
855
|
<xsl:sequence select=" substring-after($uri,'#') "/>
|
856
|
|
857
|
</xsl:function>
|
858
|
|
859
|
|
860
|
<!--
|
861
|
Whether an element has element-only content
|
862
|
|
863
|
@author Priscilla Walmsley, Datypic
|
864
|
@version 1.0
|
865
|
@see http://www.xsltfunctions.com/xsl/functx_has-element-only-content.html
|
866
|
@param $element the XML element to test
|
867
|
-->
|
868
|
<xsl:function name="functx:has-element-only-content" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
869
|
<xsl:param name="element" as="element()"/>
|
870
|
|
871
|
<xsl:sequence select=" not($element/text()[normalize-space(.) != '']) and $element/* "/>
|
872
|
|
873
|
</xsl:function>
|
874
|
|
875
|
|
876
|
<!--
|
877
|
Whether an element has empty content
|
878
|
|
879
|
@author Priscilla Walmsley, Datypic
|
880
|
@version 1.0
|
881
|
@see http://www.xsltfunctions.com/xsl/functx_has-empty-content.html
|
882
|
@param $element the XML element to test
|
883
|
-->
|
884
|
<xsl:function name="functx:has-empty-content" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
885
|
<xsl:param name="element" as="element()"/>
|
886
|
|
887
|
<xsl:sequence select=" not($element/node()) "/>
|
888
|
|
889
|
</xsl:function>
|
890
|
|
891
|
|
892
|
<!--
|
893
|
Whether an element has mixed content
|
894
|
|
895
|
@author Priscilla Walmsley, Datypic
|
896
|
@version 1.0
|
897
|
@see http://www.xsltfunctions.com/xsl/functx_has-mixed-content.html
|
898
|
@param $element the XML element to test
|
899
|
-->
|
900
|
<xsl:function name="functx:has-mixed-content" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
901
|
<xsl:param name="element" as="element()"/>
|
902
|
|
903
|
<xsl:sequence select=" $element/text()[normalize-space(.) != ''] and $element/* "/>
|
904
|
|
905
|
</xsl:function>
|
906
|
|
907
|
|
908
|
<!--
|
909
|
Whether an element has simple content
|
910
|
|
911
|
@author Priscilla Walmsley, Datypic
|
912
|
@version 1.0
|
913
|
@see http://www.xsltfunctions.com/xsl/functx_has-simple-content.html
|
914
|
@param $element the XML element to test
|
915
|
-->
|
916
|
<xsl:function name="functx:has-simple-content" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
917
|
<xsl:param name="element" as="element()"/>
|
918
|
|
919
|
<xsl:sequence select=" $element/text() and not($element/*) "/>
|
920
|
|
921
|
</xsl:function>
|
922
|
|
923
|
|
924
|
<!--
|
925
|
Gets the ID of an XML element
|
926
|
|
927
|
@author Priscilla Walmsley, Datypic
|
928
|
@version 1.0
|
929
|
@see http://www.xsltfunctions.com/xsl/functx_id-from-element.html
|
930
|
@param $element the element
|
931
|
-->
|
932
|
<xsl:function name="functx:id-from-element" as="xs:string?" xmlns:functx="http://www.functx.com">
|
933
|
<xsl:param name="element" as="element()?"/>
|
934
|
|
935
|
<xsl:sequence select=" data(($element/@*[id(.) is ..])[1]) "/>
|
936
|
|
937
|
</xsl:function>
|
938
|
|
939
|
|
940
|
<!--
|
941
|
Gets XML element(s) that have an attribute with a particular value
|
942
|
|
943
|
@author Priscilla Walmsley, Datypic
|
944
|
@version 1.0
|
945
|
@see http://www.xsltfunctions.com/xsl/functx_id-untyped.html
|
946
|
@param $node the root node(s) to start from
|
947
|
@param $id the "id" to find
|
948
|
-->
|
949
|
<xsl:function name="functx:id-untyped" as="element()*" xmlns:functx="http://www.functx.com">
|
950
|
<xsl:param name="node" as="node()*"/>
|
951
|
<xsl:param name="id" as="xs:anyAtomicType"/>
|
952
|
|
953
|
<xsl:sequence select=" $node//*[@* = $id] "/>
|
954
|
|
955
|
</xsl:function>
|
956
|
|
957
|
|
958
|
<!--
|
959
|
The first argument if it is not empty, otherwise the second argument
|
960
|
|
961
|
@author W3C XML Query WG
|
962
|
@version 1.0
|
963
|
@see http://www.xsltfunctions.com/xsl/functx_if-absent.html
|
964
|
@param $arg the item(s) that may be absent
|
965
|
@param $value the item(s) to use if the item is absent
|
966
|
-->
|
967
|
<xsl:function name="functx:if-absent" as="item()*" xmlns:functx="http://www.functx.com">
|
968
|
<xsl:param name="arg" as="item()*"/>
|
969
|
<xsl:param name="value" as="item()*"/>
|
970
|
|
971
|
<xsl:sequence select=" if (exists($arg)) then $arg else $value "/>
|
972
|
|
973
|
</xsl:function>
|
974
|
|
975
|
|
976
|
<!--
|
977
|
The first argument if it is not blank, otherwise the second argument
|
978
|
|
979
|
@author Priscilla Walmsley, Datypic
|
980
|
@version 1.0
|
981
|
@see http://www.xsltfunctions.com/xsl/functx_if-empty.html
|
982
|
@param $arg the node that may be empty
|
983
|
@param $value the item(s) to use if the node is empty
|
984
|
-->
|
985
|
<xsl:function name="functx:if-empty" as="item()*" xmlns:functx="http://www.functx.com">
|
986
|
<xsl:param name="arg" as="item()?"/>
|
987
|
<xsl:param name="value" as="item()*"/>
|
988
|
|
989
|
<xsl:sequence select=" if (string($arg) != '') then data($arg) else $value "/>
|
990
|
|
991
|
</xsl:function>
|
992
|
|
993
|
|
994
|
<!--
|
995
|
The position of a node in a sequence, based on contents and attributes
|
996
|
|
997
|
@author Priscilla Walmsley, Datypic
|
998
|
@version 1.0
|
999
|
@see http://www.xsltfunctions.com/xsl/functx_index-of-deep-equal-node.html
|
1000
|
@param $nodes the node sequence
|
1001
|
@param $nodeToFind the node to find in the sequence
|
1002
|
-->
|
1003
|
<xsl:function name="functx:index-of-deep-equal-node" as="xs:integer*" xmlns:functx="http://www.functx.com">
|
1004
|
<xsl:param name="nodes" as="node()*"/>
|
1005
|
<xsl:param name="nodeToFind" as="node()"/>
|
1006
|
|
1007
|
<xsl:sequence select=" for $seq in (1 to count($nodes)) return $seq[deep-equal($nodes[$seq],$nodeToFind)] "/>
|
1008
|
|
1009
|
</xsl:function>
|
1010
|
|
1011
|
|
1012
|
<!--
|
1013
|
The first position of a matching substring
|
1014
|
|
1015
|
@author Priscilla Walmsley, Datypic
|
1016
|
@version 1.0
|
1017
|
@see http://www.xsltfunctions.com/xsl/functx_index-of-match-first.html
|
1018
|
@param $arg the string
|
1019
|
@param $pattern the pattern to match
|
1020
|
-->
|
1021
|
<xsl:function name="functx:index-of-match-first" as="xs:integer?" xmlns:functx="http://www.functx.com">
|
1022
|
<xsl:param name="arg" as="xs:string?"/>
|
1023
|
<xsl:param name="pattern" as="xs:string"/>
|
1024
|
|
1025
|
<xsl:sequence select=" if (matches($arg,$pattern)) then string-length(tokenize($arg, $pattern)[1]) + 1 else () "/>
|
1026
|
|
1027
|
</xsl:function>
|
1028
|
|
1029
|
|
1030
|
<!--
|
1031
|
The position of a node in a sequence, based on node identity
|
1032
|
|
1033
|
@author W3C XML Query Working Group
|
1034
|
@version 1.0
|
1035
|
@see http://www.xsltfunctions.com/xsl/functx_index-of-node.html
|
1036
|
@param $nodes the node sequence
|
1037
|
@param $nodeToFind the node to find in the sequence
|
1038
|
-->
|
1039
|
<xsl:function name="functx:index-of-node" as="xs:integer*" xmlns:functx="http://www.functx.com">
|
1040
|
<xsl:param name="nodes" as="node()*"/>
|
1041
|
<xsl:param name="nodeToFind" as="node()"/>
|
1042
|
|
1043
|
<xsl:sequence select=" for $seq in (1 to count($nodes)) return $seq[$nodes[$seq] is $nodeToFind] "/>
|
1044
|
|
1045
|
</xsl:function>
|
1046
|
|
1047
|
|
1048
|
<!--
|
1049
|
The first position of a substring
|
1050
|
|
1051
|
@author Priscilla Walmsley, Datypic
|
1052
|
@version 1.0
|
1053
|
@see http://www.xsltfunctions.com/xsl/functx_index-of-string-first.html
|
1054
|
@param $arg the string
|
1055
|
@param $substring the substring to find
|
1056
|
-->
|
1057
|
<xsl:function name="functx:index-of-string-first" as="xs:integer?" xmlns:functx="http://www.functx.com">
|
1058
|
<xsl:param name="arg" as="xs:string?"/>
|
1059
|
<xsl:param name="substring" as="xs:string"/>
|
1060
|
|
1061
|
<xsl:sequence select=" if (contains($arg, $substring)) then string-length(substring-before($arg, $substring))+1 else () "/>
|
1062
|
|
1063
|
</xsl:function>
|
1064
|
|
1065
|
|
1066
|
<!--
|
1067
|
The last position of a substring
|
1068
|
|
1069
|
@author Priscilla Walmsley, Datypic
|
1070
|
@version 1.0
|
1071
|
@see http://www.xsltfunctions.com/xsl/functx_index-of-string-last.html
|
1072
|
@param $arg the string
|
1073
|
@param $substring the substring to find
|
1074
|
-->
|
1075
|
<xsl:function name="functx:index-of-string-last" as="xs:integer?" xmlns:functx="http://www.functx.com">
|
1076
|
<xsl:param name="arg" as="xs:string?"/>
|
1077
|
<xsl:param name="substring" as="xs:string"/>
|
1078
|
|
1079
|
<xsl:sequence select=" functx:index-of-string($arg, $substring)[last()] "/>
|
1080
|
|
1081
|
</xsl:function>
|
1082
|
|
1083
|
|
1084
|
<!--
|
1085
|
The position(s) of a substring
|
1086
|
|
1087
|
@author Priscilla Walmsley, Datypic
|
1088
|
@version 1.0
|
1089
|
@see http://www.xsltfunctions.com/xsl/functx_index-of-string.html
|
1090
|
@param $arg the string
|
1091
|
@param $substring the substring to find
|
1092
|
-->
|
1093
|
<xsl:function name="functx:index-of-string" as="xs:integer*" xmlns:functx="http://www.functx.com">
|
1094
|
<xsl:param name="arg" as="xs:string?"/>
|
1095
|
<xsl:param name="substring" as="xs:string"/>
|
1096
|
|
1097
|
<xsl:sequence select=" if (contains($arg, $substring)) then (string-length(substring-before($arg, $substring))+1, for $other in functx:index-of-string(substring-after($arg, $substring), $substring) return $other + string-length(substring-before($arg, $substring)) + string-length($substring)) else () "/>
|
1098
|
|
1099
|
</xsl:function>
|
1100
|
|
1101
|
|
1102
|
<!--
|
1103
|
Inserts a string at a specified position
|
1104
|
|
1105
|
@author Priscilla Walmsley, Datypic
|
1106
|
@version 1.0
|
1107
|
@see http://www.xsltfunctions.com/xsl/functx_insert-string.html
|
1108
|
@param $originalString the original string to insert into
|
1109
|
@param $stringToInsert the string to insert
|
1110
|
@param $pos the position
|
1111
|
-->
|
1112
|
<xsl:function name="functx:insert-string" as="xs:string" xmlns:functx="http://www.functx.com">
|
1113
|
<xsl:param name="originalString" as="xs:string?"/>
|
1114
|
<xsl:param name="stringToInsert" as="xs:string?"/>
|
1115
|
<xsl:param name="pos" as="xs:integer"/>
|
1116
|
|
1117
|
<xsl:sequence select=" concat(substring($originalString,1,$pos - 1), $stringToInsert, substring($originalString,$pos)) "/>
|
1118
|
|
1119
|
</xsl:function>
|
1120
|
|
1121
|
|
1122
|
<!--
|
1123
|
Whether a value is numeric
|
1124
|
|
1125
|
@author Priscilla Walmsley, Datypic
|
1126
|
@version 1.0
|
1127
|
@see http://www.xsltfunctions.com/xsl/functx_is-a-number.html
|
1128
|
@param $value the value to test
|
1129
|
-->
|
1130
|
<xsl:function name="functx:is-a-number" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1131
|
<xsl:param name="value" as="xs:anyAtomicType?"/>
|
1132
|
|
1133
|
<xsl:sequence select=" string(number($value)) != 'NaN' "/>
|
1134
|
|
1135
|
</xsl:function>
|
1136
|
|
1137
|
|
1138
|
<!--
|
1139
|
Whether a URI is absolute
|
1140
|
|
1141
|
@author Priscilla Walmsley, Datypic
|
1142
|
@version 1.0
|
1143
|
@see http://www.xsltfunctions.com/xsl/functx_is-absolute-uri.html
|
1144
|
@param $uri the URI to test
|
1145
|
-->
|
1146
|
<xsl:function name="functx:is-absolute-uri" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1147
|
<xsl:param name="uri" as="xs:string?"/>
|
1148
|
|
1149
|
<xsl:sequence select=" matches($uri,'^[a-z]+:') "/>
|
1150
|
|
1151
|
</xsl:function>
|
1152
|
|
1153
|
|
1154
|
<!--
|
1155
|
Whether an XML node is an ancestor of another node
|
1156
|
|
1157
|
@author Priscilla Walmsley, Datypic
|
1158
|
@version 1.0
|
1159
|
@see http://www.xsltfunctions.com/xsl/functx_is-ancestor.html
|
1160
|
@param $node1 the first node
|
1161
|
@param $node2 the second node
|
1162
|
-->
|
1163
|
<xsl:function name="functx:is-ancestor" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1164
|
<xsl:param name="node1" as="node()"/>
|
1165
|
<xsl:param name="node2" as="node()"/>
|
1166
|
|
1167
|
<xsl:sequence select=" exists($node1 intersect $node2/ancestor::node()) "/>
|
1168
|
|
1169
|
</xsl:function>
|
1170
|
|
1171
|
|
1172
|
<!--
|
1173
|
Whether an XML node is a descendant of another node
|
1174
|
|
1175
|
@author Priscilla Walmsley, Datypic
|
1176
|
@version 1.0
|
1177
|
@see http://www.xsltfunctions.com/xsl/functx_is-descendant.html
|
1178
|
@param $node1 the first node
|
1179
|
@param $node2 the second node
|
1180
|
-->
|
1181
|
<xsl:function name="functx:is-descendant" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1182
|
<xsl:param name="node1" as="node()"/>
|
1183
|
<xsl:param name="node2" as="node()"/>
|
1184
|
|
1185
|
<xsl:sequence select=" boolean($node2 intersect $node1/ancestor::node()) "/>
|
1186
|
|
1187
|
</xsl:function>
|
1188
|
|
1189
|
|
1190
|
<!--
|
1191
|
Whether a date falls in a leap year
|
1192
|
|
1193
|
@author Priscilla Walmsley, Datypic
|
1194
|
@version 1.0
|
1195
|
@see http://www.xsltfunctions.com/xsl/functx_is-leap-year.html
|
1196
|
@param $date the date or year
|
1197
|
-->
|
1198
|
<xsl:function name="functx:is-leap-year" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1199
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
1200
|
|
1201
|
<xsl:sequence select=" for $year in xs:integer(substring(string($date),1,4)) return ($year mod 4 = 0 and $year mod 100 != 0) or $year mod 400 = 0 "/>
|
1202
|
|
1203
|
</xsl:function>
|
1204
|
|
1205
|
|
1206
|
<!--
|
1207
|
Whether an XML node is among the descendants of a sequence, based on contents and attributes
|
1208
|
|
1209
|
@author Priscilla Walmsley, Datypic
|
1210
|
@version 1.0
|
1211
|
@see http://www.xsltfunctions.com/xsl/functx_is-node-among-descendants-deep-equal.html
|
1212
|
@param $node the node to test
|
1213
|
@param $seq the sequence of nodes to search
|
1214
|
-->
|
1215
|
<xsl:function name="functx:is-node-among-descendants-deep-equal" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1216
|
<xsl:param name="node" as="node()?"/>
|
1217
|
<xsl:param name="seq" as="node()*"/>
|
1218
|
|
1219
|
<xsl:sequence select=" some $nodeInSeq in $seq/descendant-or-self::*/(.|@*) satisfies deep-equal($nodeInSeq,$node) "/>
|
1220
|
|
1221
|
</xsl:function>
|
1222
|
|
1223
|
|
1224
|
<!--
|
1225
|
Whether an XML node is among the descendants of a sequence, based on node identity
|
1226
|
|
1227
|
@author Priscilla Walmsley, Datypic
|
1228
|
@version 1.0
|
1229
|
@see http://www.xsltfunctions.com/xsl/functx_is-node-among-descendants.html
|
1230
|
@param $node the node to test
|
1231
|
@param $seq the sequence of nodes to search
|
1232
|
-->
|
1233
|
<xsl:function name="functx:is-node-among-descendants" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1234
|
<xsl:param name="node" as="node()?"/>
|
1235
|
<xsl:param name="seq" as="node()*"/>
|
1236
|
|
1237
|
<xsl:sequence select=" some $nodeInSeq in $seq/descendant-or-self::*/(.|@*) satisfies $nodeInSeq is $node "/>
|
1238
|
|
1239
|
</xsl:function>
|
1240
|
|
1241
|
|
1242
|
<!--
|
1243
|
Whether an XML node is in a sequence, based on contents and attributes
|
1244
|
|
1245
|
@author Priscilla Walmsley, Datypic
|
1246
|
@version 1.0
|
1247
|
@see http://www.xsltfunctions.com/xsl/functx_is-node-in-sequence-deep-equal.html
|
1248
|
@param $node the node to test
|
1249
|
@param $seq the sequence of nodes to search
|
1250
|
-->
|
1251
|
<xsl:function name="functx:is-node-in-sequence-deep-equal" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1252
|
<xsl:param name="node" as="node()?"/>
|
1253
|
<xsl:param name="seq" as="node()*"/>
|
1254
|
|
1255
|
<xsl:sequence select=" some $nodeInSeq in $seq satisfies deep-equal($nodeInSeq,$node) "/>
|
1256
|
|
1257
|
</xsl:function>
|
1258
|
|
1259
|
|
1260
|
<!--
|
1261
|
Whether an XML node is in a sequence, based on node identity
|
1262
|
|
1263
|
@author Priscilla Walmsley, Datypic
|
1264
|
@version 1.0
|
1265
|
@see http://www.xsltfunctions.com/xsl/functx_is-node-in-sequence.html
|
1266
|
@param $node the node to test
|
1267
|
@param $seq the sequence of nodes to search
|
1268
|
-->
|
1269
|
<xsl:function name="functx:is-node-in-sequence" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1270
|
<xsl:param name="node" as="node()?"/>
|
1271
|
<xsl:param name="seq" as="node()*"/>
|
1272
|
|
1273
|
<xsl:sequence select=" some $nodeInSeq in $seq satisfies $nodeInSeq is $node "/>
|
1274
|
|
1275
|
</xsl:function>
|
1276
|
|
1277
|
|
1278
|
<!--
|
1279
|
Whether an atomic value appears in a sequence
|
1280
|
|
1281
|
@author Priscilla Walmsley, Datypic
|
1282
|
@version 1.0
|
1283
|
@see http://www.xsltfunctions.com/xsl/functx_is-value-in-sequence.html
|
1284
|
@param $value the atomic value to test
|
1285
|
@param $seq the sequence of values to search
|
1286
|
-->
|
1287
|
<xsl:function name="functx:is-value-in-sequence" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1288
|
<xsl:param name="value" as="xs:anyAtomicType?"/>
|
1289
|
<xsl:param name="seq" as="xs:anyAtomicType*"/>
|
1290
|
|
1291
|
<xsl:sequence select=" $value = $seq "/>
|
1292
|
|
1293
|
</xsl:function>
|
1294
|
|
1295
|
|
1296
|
<!--
|
1297
|
The last day of the month of a date
|
1298
|
|
1299
|
@author Priscilla Walmsley, Datypic
|
1300
|
@version 1.0
|
1301
|
@see http://www.xsltfunctions.com/xsl/functx_last-day-of-month.html
|
1302
|
@param $date the date
|
1303
|
-->
|
1304
|
<xsl:function name="functx:last-day-of-month" as="xs:date?" xmlns:functx="http://www.functx.com">
|
1305
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
1306
|
|
1307
|
<xsl:sequence select=" functx:date(year-from-date(xs:date($date)), month-from-date(xs:date($date)), functx:days-in-month($date)) "/>
|
1308
|
|
1309
|
</xsl:function>
|
1310
|
|
1311
|
|
1312
|
<!--
|
1313
|
The last day of the month of a date
|
1314
|
|
1315
|
@author Priscilla Walmsley, Datypic
|
1316
|
@version 1.0
|
1317
|
@see http://www.xsltfunctions.com/xsl/functx_last-day-of-year.html
|
1318
|
@param $date the date
|
1319
|
-->
|
1320
|
<xsl:function name="functx:last-day-of-year" as="xs:date?" xmlns:functx="http://www.functx.com">
|
1321
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
1322
|
|
1323
|
<xsl:sequence select=" functx:date(year-from-date(xs:date($date)), 12, 31) "/>
|
1324
|
|
1325
|
</xsl:function>
|
1326
|
|
1327
|
|
1328
|
<!--
|
1329
|
The XML node in a sequence that is last in document order
|
1330
|
|
1331
|
@author Priscilla Walmsley, Datypic
|
1332
|
@version 1.0
|
1333
|
@see http://www.xsltfunctions.com/xsl/functx_last-node.html
|
1334
|
@param $nodes the sequence of nodes
|
1335
|
-->
|
1336
|
<xsl:function name="functx:last-node" as="node()?" xmlns:functx="http://www.functx.com">
|
1337
|
<xsl:param name="nodes" as="node()*"/>
|
1338
|
|
1339
|
<xsl:sequence select=" ($nodes/.)[last()] "/>
|
1340
|
|
1341
|
</xsl:function>
|
1342
|
|
1343
|
|
1344
|
<!--
|
1345
|
All XML elements that don't have any child elements
|
1346
|
|
1347
|
@author Priscilla Walmsley, Datypic
|
1348
|
@version 1.0
|
1349
|
@see http://www.xsltfunctions.com/xsl/functx_leaf-elements.html
|
1350
|
@param $root the root
|
1351
|
-->
|
1352
|
<xsl:function name="functx:leaf-elements" as="element()*" xmlns:functx="http://www.functx.com">
|
1353
|
<xsl:param name="root" as="node()?"/>
|
1354
|
|
1355
|
<xsl:sequence select=" $root/descendant-or-self::*[not(*)] "/>
|
1356
|
|
1357
|
</xsl:function>
|
1358
|
|
1359
|
|
1360
|
<!--
|
1361
|
Trims leading whitespace
|
1362
|
|
1363
|
@author Priscilla Walmsley, Datypic
|
1364
|
@version 1.0
|
1365
|
@see http://www.xsltfunctions.com/xsl/functx_left-trim.html
|
1366
|
@param $arg the string to trim
|
1367
|
-->
|
1368
|
<xsl:function name="functx:left-trim" as="xs:string" xmlns:functx="http://www.functx.com">
|
1369
|
<xsl:param name="arg" as="xs:string?"/>
|
1370
|
|
1371
|
<xsl:sequence select=" replace($arg,'^\s+','') "/>
|
1372
|
|
1373
|
</xsl:function>
|
1374
|
|
1375
|
|
1376
|
<!--
|
1377
|
The number of lines
|
1378
|
|
1379
|
@author Priscilla Walmsley, Datypic
|
1380
|
@version 1.0
|
1381
|
@see http://www.xsltfunctions.com/xsl/functx_line-count.html
|
1382
|
@param $arg the string to test
|
1383
|
-->
|
1384
|
<xsl:function name="functx:line-count" as="xs:integer" xmlns:functx="http://www.functx.com">
|
1385
|
<xsl:param name="arg" as="xs:string?"/>
|
1386
|
|
1387
|
<xsl:sequence select=" count(functx:lines($arg)) "/>
|
1388
|
|
1389
|
</xsl:function>
|
1390
|
|
1391
|
|
1392
|
<!--
|
1393
|
Split a string into separate lines
|
1394
|
|
1395
|
@author Priscilla Walmsley, Datypic
|
1396
|
@version 1.0
|
1397
|
@see http://www.xsltfunctions.com/xsl/functx_lines.html
|
1398
|
@param $arg the string to split
|
1399
|
-->
|
1400
|
<xsl:function name="functx:lines" as="xs:string*" xmlns:functx="http://www.functx.com">
|
1401
|
<xsl:param name="arg" as="xs:string?"/>
|
1402
|
|
1403
|
<xsl:sequence select=" tokenize($arg, '(\r\n?|\n\r?)') "/>
|
1404
|
|
1405
|
</xsl:function>
|
1406
|
|
1407
|
|
1408
|
<!--
|
1409
|
The maximum depth of elements in an XML tree
|
1410
|
|
1411
|
@author Priscilla Walmsley, Datypic
|
1412
|
@version 1.0
|
1413
|
@see http://www.xsltfunctions.com/xsl/functx_max-depth.html
|
1414
|
@param $root the root to start from
|
1415
|
-->
|
1416
|
<xsl:function name="functx:max-depth" as="xs:integer?" xmlns:functx="http://www.functx.com">
|
1417
|
<xsl:param name="root" as="node()?"/>
|
1418
|
|
1419
|
<xsl:sequence select=" if ($root/*) then max($root/*/functx:max-depth(.)) + 1 else 1 "/>
|
1420
|
|
1421
|
</xsl:function>
|
1422
|
|
1423
|
|
1424
|
<!--
|
1425
|
The maximum value in a sequence, figuring out its type (numeric or string)
|
1426
|
|
1427
|
@author Priscilla Walmsley, Datypic
|
1428
|
@version 1.0
|
1429
|
@see http://www.xsltfunctions.com/xsl/functx_max-determine-type.html
|
1430
|
@param $seq the sequence of values to test
|
1431
|
-->
|
1432
|
<xsl:function name="functx:max-determine-type" as="xs:anyAtomicType?" xmlns:functx="http://www.functx.com">
|
1433
|
<xsl:param name="seq" as="xs:anyAtomicType*"/>
|
1434
|
|
1435
|
<xsl:sequence select=" if (every $value in $seq satisfies ($value castable as xs:double)) then max(for $value in $seq return xs:double($value)) else max(for $value in $seq return xs:string($value)) "/>
|
1436
|
|
1437
|
</xsl:function>
|
1438
|
|
1439
|
|
1440
|
<!--
|
1441
|
The maximum line length
|
1442
|
|
1443
|
@author Priscilla Walmsley, Datypic
|
1444
|
@version 1.0
|
1445
|
@see http://www.xsltfunctions.com/xsl/functx_max-line-length.html
|
1446
|
@param $arg the string to test
|
1447
|
-->
|
1448
|
<xsl:function name="functx:max-line-length" as="xs:integer" xmlns:functx="http://www.functx.com">
|
1449
|
<xsl:param name="arg" as="xs:string?"/>
|
1450
|
|
1451
|
<xsl:sequence select=" max( for $line in functx:lines($arg) return string-length($line)) "/>
|
1452
|
|
1453
|
</xsl:function>
|
1454
|
|
1455
|
|
1456
|
<!--
|
1457
|
The XML node whose typed value is the maximum
|
1458
|
|
1459
|
@author Priscilla Walmsley, Datypic
|
1460
|
@version 1.0
|
1461
|
@see http://www.xsltfunctions.com/xsl/functx_max-node.html
|
1462
|
@param $nodes the sequence of nodes to test
|
1463
|
-->
|
1464
|
<xsl:function name="functx:max-node" as="node()*" xmlns:functx="http://www.functx.com">
|
1465
|
<xsl:param name="nodes" as="node()*"/>
|
1466
|
|
1467
|
<xsl:sequence select=" $nodes[. = max($nodes)] "/>
|
1468
|
|
1469
|
</xsl:function>
|
1470
|
|
1471
|
|
1472
|
<!--
|
1473
|
The maximum of a sequence of values, treating them like strings
|
1474
|
|
1475
|
@author Priscilla Walmsley, Datypic
|
1476
|
@version 1.0
|
1477
|
@see http://www.xsltfunctions.com/xsl/functx_max-string.html
|
1478
|
@param $strings the sequence of values
|
1479
|
-->
|
1480
|
<xsl:function name="functx:max-string" as="xs:string?" xmlns:functx="http://www.functx.com">
|
1481
|
<xsl:param name="strings" as="xs:anyAtomicType*"/>
|
1482
|
|
1483
|
<xsl:sequence select=" max(for $string in $strings return string($string)) "/>
|
1484
|
|
1485
|
</xsl:function>
|
1486
|
|
1487
|
|
1488
|
<!--
|
1489
|
The minimum value in a sequence, figuring out its type (numeric or string)
|
1490
|
|
1491
|
@author Priscilla Walmsley, Datypic
|
1492
|
@version 1.0
|
1493
|
@see http://www.xsltfunctions.com/xsl/functx_min-determine-type.html
|
1494
|
@param $seq the sequence of values to test
|
1495
|
-->
|
1496
|
<xsl:function name="functx:min-determine-type" as="xs:anyAtomicType?" xmlns:functx="http://www.functx.com">
|
1497
|
<xsl:param name="seq" as="xs:anyAtomicType*"/>
|
1498
|
|
1499
|
<xsl:sequence select=" if (every $value in $seq satisfies ($value castable as xs:double)) then min(for $value in $seq return xs:double($value)) else min(for $value in $seq return xs:string($value)) "/>
|
1500
|
|
1501
|
</xsl:function>
|
1502
|
|
1503
|
|
1504
|
<!--
|
1505
|
The XML node whose typed value is the minimum
|
1506
|
|
1507
|
@author Priscilla Walmsley, Datypic
|
1508
|
@version 1.0
|
1509
|
@see http://www.xsltfunctions.com/xsl/functx_min-node.html
|
1510
|
@param $nodes the sequence of nodes to test
|
1511
|
-->
|
1512
|
<xsl:function name="functx:min-node" as="node()*" xmlns:functx="http://www.functx.com">
|
1513
|
<xsl:param name="nodes" as="node()*"/>
|
1514
|
|
1515
|
<xsl:sequence select=" $nodes[. = min($nodes)] "/>
|
1516
|
|
1517
|
</xsl:function>
|
1518
|
|
1519
|
|
1520
|
<!--
|
1521
|
The minimum of a sequence of strings, ignoring "empty" values
|
1522
|
|
1523
|
@author Priscilla Walmsley, Datypic
|
1524
|
@version 1.0
|
1525
|
@see http://www.xsltfunctions.com/xsl/functx_min-non-empty-string.html
|
1526
|
@param $strings the sequence of strings to search
|
1527
|
-->
|
1528
|
<xsl:function name="functx:min-non-empty-string" as="xs:string?" xmlns:functx="http://www.functx.com">
|
1529
|
<xsl:param name="strings" as="xs:string*"/>
|
1530
|
|
1531
|
<xsl:sequence select=" min($strings[. != '']) "/>
|
1532
|
|
1533
|
</xsl:function>
|
1534
|
|
1535
|
|
1536
|
<!--
|
1537
|
The minimum of a sequence of values, treating them like strings
|
1538
|
|
1539
|
@author Priscilla Walmsley, Datypic
|
1540
|
@version 1.0
|
1541
|
@see http://www.xsltfunctions.com/xsl/functx_min-string.html
|
1542
|
@param $strings the sequence of strings
|
1543
|
-->
|
1544
|
<xsl:function name="functx:min-string" as="xs:string?" xmlns:functx="http://www.functx.com">
|
1545
|
<xsl:param name="strings" as="xs:anyAtomicType*"/>
|
1546
|
|
1547
|
<xsl:sequence select=" min(for $string in $strings return string($string)) "/>
|
1548
|
|
1549
|
</xsl:function>
|
1550
|
|
1551
|
|
1552
|
<!--
|
1553
|
Converts a string with format MMDDYYYY (with any delimiters) to a date
|
1554
|
|
1555
|
@author Priscilla Walmsley, Datypic
|
1556
|
@version 1.0
|
1557
|
@see http://www.xsltfunctions.com/xsl/functx_mmddyyyy-to-date.html
|
1558
|
@param $dateString the MMDDYYYY string
|
1559
|
-->
|
1560
|
<xsl:function name="functx:mmddyyyy-to-date" as="xs:date?" xmlns:functx="http://www.functx.com">
|
1561
|
<xsl:param name="dateString" as="xs:string?"/>
|
1562
|
|
1563
|
<xsl:sequence select=" if (empty($dateString)) then () else if (not(matches($dateString, '^\D*(\d{2})\D*(\d{2})\D*(\d{4})\D*$'))) then error(xs:QName('functx:Invalid_Date_Format')) else xs:date(replace($dateString, '^\D*(\d{2})\D*(\d{2})\D*(\d{4})\D*$', '$3-$1-$2')) "/>
|
1564
|
|
1565
|
</xsl:function>
|
1566
|
|
1567
|
|
1568
|
<!--
|
1569
|
The month of a date as an abbreviated word (Jan, Feb, etc.)
|
1570
|
|
1571
|
@author Priscilla Walmsley, Datypic
|
1572
|
@version 1.0
|
1573
|
@see http://www.xsltfunctions.com/xsl/functx_month-abbrev-en.html
|
1574
|
@param $date the date
|
1575
|
-->
|
1576
|
<xsl:function name="functx:month-abbrev-en" as="xs:string?" xmlns:functx="http://www.functx.com">
|
1577
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
1578
|
|
1579
|
<xsl:sequence select=" ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') [month-from-date(xs:date($date))] "/>
|
1580
|
|
1581
|
</xsl:function>
|
1582
|
|
1583
|
|
1584
|
<!--
|
1585
|
The month of a date as a word (January, February, etc.)
|
1586
|
|
1587
|
@author Priscilla Walmsley, Datypic
|
1588
|
@version 1.0
|
1589
|
@see http://www.xsltfunctions.com/xsl/functx_month-name-en.html
|
1590
|
@param $date the date
|
1591
|
-->
|
1592
|
<xsl:function name="functx:month-name-en" as="xs:string?" xmlns:functx="http://www.functx.com">
|
1593
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
1594
|
|
1595
|
<xsl:sequence select=" ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December') [month-from-date(xs:date($date))] "/>
|
1596
|
|
1597
|
</xsl:function>
|
1598
|
|
1599
|
|
1600
|
<!--
|
1601
|
Whether a name matches a list of names or name wildcards
|
1602
|
|
1603
|
@author Priscilla Walmsley, Datypic
|
1604
|
@version 1.0
|
1605
|
@see http://www.xsltfunctions.com/xsl/functx_name-test.html
|
1606
|
@param $testname the name to test
|
1607
|
@param $names the list of names or name wildcards
|
1608
|
-->
|
1609
|
<xsl:function name="functx:name-test" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1610
|
<xsl:param name="testname" as="xs:string?"/>
|
1611
|
<xsl:param name="names" as="xs:string*"/>
|
1612
|
|
1613
|
<xsl:sequence select=" $testname = $names or $names = '*' or functx:substring-after-if-contains($testname,':') = (for $name in $names return substring-after($name,'*:')) or substring-before($testname,':') = (for $name in $names[contains(.,':*')] return substring-before($name,':*')) "/>
|
1614
|
|
1615
|
</xsl:function>
|
1616
|
|
1617
|
|
1618
|
<!--
|
1619
|
A list of namespaces used in element/attribute names in an XML fragment
|
1620
|
|
1621
|
@author Priscilla Walmsley, Datypic
|
1622
|
@version 1.0
|
1623
|
@see http://www.xsltfunctions.com/xsl/functx_namespaces-in-use.html
|
1624
|
@param $root the root node to start from
|
1625
|
-->
|
1626
|
<xsl:function name="functx:namespaces-in-use" as="xs:anyURI*" xmlns:functx="http://www.functx.com">
|
1627
|
<xsl:param name="root" as="node()?"/>
|
1628
|
|
1629
|
<xsl:sequence select=" distinct-values( $root/descendant-or-self::*/(.|@*)/namespace-uri(.)) "/>
|
1630
|
|
1631
|
</xsl:function>
|
1632
|
|
1633
|
|
1634
|
<!--
|
1635
|
The next day
|
1636
|
|
1637
|
@author Priscilla Walmsley, Datypic
|
1638
|
@version 1.0
|
1639
|
@see http://www.xsltfunctions.com/xsl/functx_next-day.html
|
1640
|
@param $date the date
|
1641
|
-->
|
1642
|
<xsl:function name="functx:next-day" as="xs:date?" xmlns:functx="http://www.functx.com">
|
1643
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
1644
|
|
1645
|
<xsl:sequence select=" xs:date($date) + xs:dayTimeDuration('P1D') "/>
|
1646
|
|
1647
|
</xsl:function>
|
1648
|
|
1649
|
|
1650
|
<!--
|
1651
|
The XML node kind (element, attribute, text, etc.)
|
1652
|
|
1653
|
@author Priscilla Walmsley, Datypic
|
1654
|
@version 1.0
|
1655
|
@see http://www.xsltfunctions.com/xsl/functx_node-kind.html
|
1656
|
@param $nodes the node(s) whose kind you want to determine
|
1657
|
-->
|
1658
|
<xsl:function name="functx:node-kind" as="xs:string*" xmlns:functx="http://www.functx.com">
|
1659
|
<xsl:param name="nodes" as="node()*"/>
|
1660
|
|
1661
|
<xsl:sequence select=" for $node in $nodes return if ($node instance of element()) then 'element' else if ($node instance of attribute()) then 'attribute' else if ($node instance of text()) then 'text' else if ($node instance of document-node()) then 'document-node' else if ($node instance of comment()) then 'comment' else if ($node instance of processing-instruction()) then 'processing-instruction' else 'unknown' "/>
|
1662
|
|
1663
|
</xsl:function>
|
1664
|
|
1665
|
|
1666
|
<!--
|
1667
|
Returns any values that appear more than once in a sequence
|
1668
|
|
1669
|
@author Priscilla Walmsley, Datypic
|
1670
|
@version 1.0
|
1671
|
@see http://www.xsltfunctions.com/xsl/functx_non-distinct-values.html
|
1672
|
@param $seq the sequence of values
|
1673
|
-->
|
1674
|
<xsl:function name="functx:non-distinct-values" as="xs:anyAtomicType*" xmlns:functx="http://www.functx.com">
|
1675
|
<xsl:param name="seq" as="xs:anyAtomicType*"/>
|
1676
|
|
1677
|
<xsl:sequence select=" for $val in distinct-values($seq) return $val[count($seq[. = $val]) > 1] "/>
|
1678
|
|
1679
|
</xsl:function>
|
1680
|
|
1681
|
|
1682
|
<!--
|
1683
|
The number of regions that match a pattern
|
1684
|
|
1685
|
@author Priscilla Walmsley, Datypic
|
1686
|
@version 1.0
|
1687
|
@see http://www.xsltfunctions.com/xsl/functx_number-of-matches.html
|
1688
|
@param $arg the string to test
|
1689
|
@param $pattern the regular expression
|
1690
|
-->
|
1691
|
<xsl:function name="functx:number-of-matches" as="xs:integer" xmlns:functx="http://www.functx.com">
|
1692
|
<xsl:param name="arg" as="xs:string?"/>
|
1693
|
<xsl:param name="pattern" as="xs:string"/>
|
1694
|
|
1695
|
<xsl:sequence select=" count(tokenize($arg,$pattern)) - 1 "/>
|
1696
|
|
1697
|
</xsl:function>
|
1698
|
|
1699
|
|
1700
|
<!--
|
1701
|
Resolves a relative URI and references it, returning an XML document
|
1702
|
|
1703
|
@author Priscilla Walmsley, Datypic
|
1704
|
@version 1.0
|
1705
|
@see http://www.xsltfunctions.com/xsl/functx_open-ref-document.html
|
1706
|
@param $refNode a node whose value is a relative URI reference
|
1707
|
-->
|
1708
|
<xsl:function name="functx:open-ref-document" as="document-node()" xmlns:functx="http://www.functx.com">
|
1709
|
<xsl:param name="refNode" as="node()"/>
|
1710
|
|
1711
|
<xsl:sequence select=" if (base-uri($refNode)) then doc(resolve-uri($refNode, base-uri($refNode))) else doc(resolve-uri($refNode)) "/>
|
1712
|
|
1713
|
</xsl:function>
|
1714
|
|
1715
|
|
1716
|
<!--
|
1717
|
Reformats a number as an ordinal number, e.g. 1st, 2nd, 3rd.
|
1718
|
|
1719
|
@author Priscilla Walmsley, Datypic
|
1720
|
@version 1.0
|
1721
|
@see http://www.xsltfunctions.com/xsl/functx_ordinal-number-en.html
|
1722
|
@param $num the number
|
1723
|
-->
|
1724
|
<xsl:function name="functx:ordinal-number-en" as="xs:string" xmlns:functx="http://www.functx.com">
|
1725
|
<xsl:param name="num" as="xs:integer?"/>
|
1726
|
|
1727
|
<xsl:sequence select=" concat(xs:string($num), if (matches(xs:string($num),'[04-9]$|1[1-3]$')) then 'th' else if (ends-with(xs:string($num),'1')) then 'st' else if (ends-with(xs:string($num),'2')) then 'nd' else if (ends-with(xs:string($num),'3')) then 'rd' else '') "/>
|
1728
|
|
1729
|
</xsl:function>
|
1730
|
|
1731
|
|
1732
|
<!--
|
1733
|
Pads an integer to a desired length by adding leading zeros
|
1734
|
|
1735
|
@author Priscilla Walmsley, Datypic
|
1736
|
@version 1.0
|
1737
|
@see http://www.xsltfunctions.com/xsl/functx_pad-integer-to-length.html
|
1738
|
@param $integerToPad the integer to pad
|
1739
|
@param $length the desired length
|
1740
|
-->
|
1741
|
<xsl:function name="functx:pad-integer-to-length" as="xs:string" xmlns:functx="http://www.functx.com">
|
1742
|
<xsl:param name="integerToPad" as="xs:anyAtomicType?"/>
|
1743
|
<xsl:param name="length" as="xs:integer"/>
|
1744
|
|
1745
|
<xsl:sequence select=" if ($length < string-length(string($integerToPad))) then error(xs:QName('functx:Integer_Longer_Than_Length')) else concat (functx:repeat-string( '0',$length - string-length(string($integerToPad))), string($integerToPad)) "/>
|
1746
|
|
1747
|
</xsl:function>
|
1748
|
|
1749
|
|
1750
|
<!--
|
1751
|
Pads a string to a desired length
|
1752
|
|
1753
|
@author Priscilla Walmsley, Datypic
|
1754
|
@version 1.0
|
1755
|
@see http://www.xsltfunctions.com/xsl/functx_pad-string-to-length.html
|
1756
|
@param $stringToPad the string to pad
|
1757
|
@param $padChar the character(s) to use as padding
|
1758
|
@param $length the desired length
|
1759
|
-->
|
1760
|
<xsl:function name="functx:pad-string-to-length" as="xs:string" xmlns:functx="http://www.functx.com">
|
1761
|
<xsl:param name="stringToPad" as="xs:string?"/>
|
1762
|
<xsl:param name="padChar" as="xs:string"/>
|
1763
|
<xsl:param name="length" as="xs:integer"/>
|
1764
|
|
1765
|
<xsl:sequence select=" substring( string-join ( ($stringToPad, for $i in (1 to $length) return $padChar) ,'') ,1,$length) "/>
|
1766
|
|
1767
|
</xsl:function>
|
1768
|
|
1769
|
|
1770
|
<!--
|
1771
|
A unique path to an XML node (or sequence of nodes)
|
1772
|
|
1773
|
@author Priscilla Walmsley, Datypic
|
1774
|
@version 1.0
|
1775
|
@see http://www.xsltfunctions.com/xsl/functx_path-to-node-with-pos.html
|
1776
|
@param $node the node sequence
|
1777
|
-->
|
1778
|
<xsl:function name="functx:path-to-node-with-pos" as="xs:string" xmlns:functx="http://www.functx.com">
|
1779
|
<xsl:param name="node" as="node()?"/>
|
1780
|
|
1781
|
<xsl:variable name="names" as="xs:string*">
|
1782
|
<xsl:for-each select="$node/ancestor-or-self::*">
|
1783
|
<xsl:variable name="ancestor" select="."/>
|
1784
|
<xsl:variable name="sibsOfSameName" select="$ancestor/../*[name() = name($ancestor)]"/>
|
1785
|
<xsl:sequence select="concat(name($ancestor), if (count($sibsOfSameName) <= 1) then '' else concat( '[',functx:index-of-node($sibsOfSameName,$ancestor),']'))"/>
|
1786
|
</xsl:for-each>
|
1787
|
</xsl:variable>
|
1788
|
<xsl:sequence select="string-join($names,'/')"/>
|
1789
|
|
1790
|
</xsl:function>
|
1791
|
|
1792
|
|
1793
|
<!--
|
1794
|
A path to an XML node (or sequence of nodes)
|
1795
|
|
1796
|
@author Priscilla Walmsley, Datypic
|
1797
|
@version 1.0
|
1798
|
@see http://www.xsltfunctions.com/xsl/functx_path-to-node.html
|
1799
|
@param $nodes the node sequence
|
1800
|
-->
|
1801
|
<xsl:function name="functx:path-to-node" as="xs:string*" xmlns:functx="http://www.functx.com">
|
1802
|
<xsl:param name="nodes" as="node()*"/>
|
1803
|
|
1804
|
<xsl:sequence select=" $nodes/string-join(ancestor-or-self::*/name(.), '/') "/>
|
1805
|
|
1806
|
</xsl:function>
|
1807
|
|
1808
|
|
1809
|
<!--
|
1810
|
Whether an XML node precedes another without being its ancestor
|
1811
|
|
1812
|
@author W3C XML Query Working Group
|
1813
|
@version 1.0
|
1814
|
@see http://www.xsltfunctions.com/xsl/functx_precedes-not-ancestor.html
|
1815
|
@param $a the first node
|
1816
|
@param $b the second node
|
1817
|
-->
|
1818
|
<xsl:function name="functx:precedes-not-ancestor" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
1819
|
<xsl:param name="a" as="node()?"/>
|
1820
|
<xsl:param name="b" as="node()?"/>
|
1821
|
|
1822
|
<xsl:sequence select=" $a << $b and empty($a intersect $b/ancestor::node()) "/>
|
1823
|
|
1824
|
</xsl:function>
|
1825
|
|
1826
|
|
1827
|
<!--
|
1828
|
The previous day
|
1829
|
|
1830
|
@author Priscilla Walmsley, Datypic
|
1831
|
@version 1.0
|
1832
|
@see http://www.xsltfunctions.com/xsl/functx_previous-day.html
|
1833
|
@param $date the date
|
1834
|
-->
|
1835
|
<xsl:function name="functx:previous-day" as="xs:date?" xmlns:functx="http://www.functx.com">
|
1836
|
<xsl:param name="date" as="xs:anyAtomicType?"/>
|
1837
|
|
1838
|
<xsl:sequence select=" xs:date($date) - xs:dayTimeDuration('P1D') "/>
|
1839
|
|
1840
|
</xsl:function>
|
1841
|
|
1842
|
|
1843
|
<!--
|
1844
|
Removes attributes from an XML fragment, based on name
|
1845
|
|
1846
|
@author Priscilla Walmsley, Datypic
|
1847
|
@version 1.0
|
1848
|
@see http://www.xsltfunctions.com/xsl/functx_remove-attributes-deep.html
|
1849
|
@param $nodes the root(s) to start from
|
1850
|
@param $names the names of the attributes to remove, or * for all attributes
|
1851
|
-->
|
1852
|
<xsl:function name="functx:remove-attributes-deep" as="node()*" xmlns:functx="http://www.functx.com">
|
1853
|
<xsl:param name="nodes" as="node()*"/>
|
1854
|
<xsl:param name="names" as="xs:string*"/>
|
1855
|
|
1856
|
<xsl:for-each select="$nodes">
|
1857
|
<xsl:choose>
|
1858
|
<xsl:when test=". instance of element()">
|
1859
|
<xsl:element name="{node-name(.)}">
|
1860
|
<xsl:sequence select=" (@*[not(functx:name-test(name(),$names))], functx:remove-attributes-deep(node(), $names))"/>
|
1861
|
</xsl:element>
|
1862
|
</xsl:when>
|
1863
|
<xsl:when test=". instance of document-node()">
|
1864
|
<xsl:document>
|
1865
|
<xsl:sequence select=" functx:remove-attributes-deep(node(), $names)"/>
|
1866
|
</xsl:document>
|
1867
|
</xsl:when>
|
1868
|
<xsl:otherwise>
|
1869
|
<xsl:sequence select="."/>
|
1870
|
</xsl:otherwise>
|
1871
|
</xsl:choose>
|
1872
|
</xsl:for-each>
|
1873
|
|
1874
|
</xsl:function>
|
1875
|
|
1876
|
|
1877
|
<!--
|
1878
|
Removes attributes from an XML element, based on name
|
1879
|
|
1880
|
@author Priscilla Walmsley, Datypic
|
1881
|
@version 1.0
|
1882
|
@see http://www.xsltfunctions.com/xsl/functx_remove-attributes.html
|
1883
|
@param $elements the element(s) from which to remove the attributes
|
1884
|
@param $names the names of the attributes to remove, or * for all attributes
|
1885
|
-->
|
1886
|
<xsl:function name="functx:remove-attributes" as="element()" xmlns:functx="http://www.functx.com">
|
1887
|
<xsl:param name="elements" as="element()*"/>
|
1888
|
<xsl:param name="names" as="xs:string*"/>
|
1889
|
|
1890
|
<xsl:for-each select="$elements">
|
1891
|
<xsl:element name="{node-name(.)}">
|
1892
|
<xsl:sequence select="(@*[not(functx:name-test(name(),$names))], node())"/>
|
1893
|
</xsl:element>
|
1894
|
</xsl:for-each>
|
1895
|
|
1896
|
</xsl:function>
|
1897
|
|
1898
|
|
1899
|
<!--
|
1900
|
Removes descendant elements from an XML node, based on name
|
1901
|
|
1902
|
@author Priscilla Walmsley, Datypic
|
1903
|
@version 1.0
|
1904
|
@see http://www.xsltfunctions.com/xsl/functx_remove-elements-deep.html
|
1905
|
@param $nodes root(s) to start from
|
1906
|
@param $names the names of the elements to remove
|
1907
|
-->
|
1908
|
<xsl:function name="functx:remove-elements-deep" as="node()*" xmlns:functx="http://www.functx.com">
|
1909
|
<xsl:param name="nodes" as="node()*"/>
|
1910
|
<xsl:param name="names" as="xs:string*"/>
|
1911
|
|
1912
|
<xsl:for-each select="$nodes">
|
1913
|
<xsl:choose>
|
1914
|
<xsl:when test=". instance of element()">
|
1915
|
<xsl:if test="not(functx:name-test(name(),$names))">
|
1916
|
<xsl:element name="{node-name(.)}">
|
1917
|
<xsl:sequence select="@*, functx:remove-elements-deep(node(), $names)"/>
|
1918
|
</xsl:element>
|
1919
|
</xsl:if>
|
1920
|
</xsl:when>
|
1921
|
<xsl:when test=". instance of document-node()">
|
1922
|
<xsl:document>
|
1923
|
<xsl:sequence select=" functx:remove-elements-deep(node(), $names)"/>
|
1924
|
</xsl:document>
|
1925
|
</xsl:when>
|
1926
|
<xsl:otherwise>
|
1927
|
<xsl:sequence select="."/>
|
1928
|
</xsl:otherwise>
|
1929
|
</xsl:choose>
|
1930
|
</xsl:for-each>
|
1931
|
|
1932
|
</xsl:function>
|
1933
|
|
1934
|
|
1935
|
<!--
|
1936
|
Removes descendant XML elements but keeps their content
|
1937
|
|
1938
|
@author Priscilla Walmsley, Datypic
|
1939
|
@version 1.0
|
1940
|
@see http://www.xsltfunctions.com/xsl/functx_remove-elements-not-contents.html
|
1941
|
@param $nodes the root(s) to start from
|
1942
|
@param $names the names of the elements to remove
|
1943
|
-->
|
1944
|
<xsl:function name="functx:remove-elements-not-contents" as="node()*" xmlns:functx="http://www.functx.com">
|
1945
|
<xsl:param name="nodes" as="node()*"/>
|
1946
|
<xsl:param name="names" as="xs:string*"/>
|
1947
|
|
1948
|
<xsl:for-each select="$nodes">
|
1949
|
<xsl:choose>
|
1950
|
<xsl:when test=". instance of element()">
|
1951
|
<xsl:choose>
|
1952
|
<xsl:when test="functx:name-test(name(),$names)">
|
1953
|
<xsl:sequence select=" functx:remove-elements-not-contents(node(), $names)"/>
|
1954
|
</xsl:when>
|
1955
|
<xsl:otherwise>
|
1956
|
<xsl:element name="{node-name(.)}">
|
1957
|
<xsl:sequence select="@*, functx:remove-elements-not-contents(node(),$names)"/>
|
1958
|
</xsl:element>
|
1959
|
</xsl:otherwise>
|
1960
|
</xsl:choose>
|
1961
|
</xsl:when>
|
1962
|
<xsl:when test=". instance of document-node()">
|
1963
|
<xsl:document>
|
1964
|
<xsl:sequence select=" functx:remove-elements-not-contents(node(), $names)"/>
|
1965
|
</xsl:document>
|
1966
|
</xsl:when>
|
1967
|
<xsl:otherwise>
|
1968
|
<xsl:sequence select="."/>
|
1969
|
</xsl:otherwise>
|
1970
|
</xsl:choose>
|
1971
|
</xsl:for-each>
|
1972
|
|
1973
|
</xsl:function>
|
1974
|
|
1975
|
|
1976
|
<!--
|
1977
|
Removes child elements from an XML node, based on name
|
1978
|
|
1979
|
@author Priscilla Walmsley, Datypic
|
1980
|
@version 1.0
|
1981
|
@see http://www.xsltfunctions.com/xsl/functx_remove-elements.html
|
1982
|
@param $elements the element(s) from which you wish to remove the children
|
1983
|
@param $names the names of the child elements to remove
|
1984
|
-->
|
1985
|
<xsl:function name="functx:remove-elements" as="element()*" xmlns:functx="http://www.functx.com">
|
1986
|
<xsl:param name="elements" as="element()*"/>
|
1987
|
<xsl:param name="names" as="xs:string*"/>
|
1988
|
|
1989
|
<xsl:for-each select="$elements">
|
1990
|
<xsl:element name="{node-name(.)}">
|
1991
|
<xsl:sequence select="(@*, node()[not(functx:name-test(name(),$names))])"/>
|
1992
|
</xsl:element>
|
1993
|
</xsl:for-each>
|
1994
|
|
1995
|
</xsl:function>
|
1996
|
|
1997
|
|
1998
|
<!--
|
1999
|
Repeats a string a given number of times
|
2000
|
|
2001
|
@author Priscilla Walmsley, Datypic
|
2002
|
@version 1.0
|
2003
|
@see http://www.xsltfunctions.com/xsl/functx_repeat-string.html
|
2004
|
@param $stringToRepeat the string to repeat
|
2005
|
@param $count the desired number of copies
|
2006
|
-->
|
2007
|
<xsl:function name="functx:repeat-string" as="xs:string" xmlns:functx="http://www.functx.com">
|
2008
|
<xsl:param name="stringToRepeat" as="xs:string?"/>
|
2009
|
<xsl:param name="count" as="xs:integer"/>
|
2010
|
|
2011
|
<xsl:sequence select=" string-join((for $i in 1 to $count return $stringToRepeat), '') "/>
|
2012
|
|
2013
|
</xsl:function>
|
2014
|
|
2015
|
|
2016
|
<!--
|
2017
|
Replaces the beginning of a string, up to a matched pattern
|
2018
|
|
2019
|
@author Priscilla Walmsley, Datypic
|
2020
|
@version 1.0
|
2021
|
@see http://www.xsltfunctions.com/xsl/functx_replace-beginning.html
|
2022
|
@param $arg the entire string to change
|
2023
|
@param $pattern the pattern of characters to replace up to
|
2024
|
@param $replacement the replacement string
|
2025
|
-->
|
2026
|
<xsl:function name="functx:replace-beginning" as="xs:string" xmlns:functx="http://www.functx.com">
|
2027
|
<xsl:param name="arg" as="xs:string?"/>
|
2028
|
<xsl:param name="pattern" as="xs:string"/>
|
2029
|
<xsl:param name="replacement" as="xs:string"/>
|
2030
|
|
2031
|
<xsl:sequence select=" replace($arg, concat('^.*?', $pattern), $replacement) "/>
|
2032
|
|
2033
|
</xsl:function>
|
2034
|
|
2035
|
|
2036
|
<!--
|
2037
|
Updates the content of one or more elements
|
2038
|
|
2039
|
@author Priscilla Walmsley, Datypic
|
2040
|
@version 1.0
|
2041
|
@see http://www.xsltfunctions.com/xsl/functx_replace-element-values.html
|
2042
|
@param $elements the elements whose content you wish to replace
|
2043
|
@param $values the replacement values
|
2044
|
-->
|
2045
|
<xsl:function name="functx:replace-element-values" as="element()*" xmlns:functx="http://www.functx.com">
|
2046
|
<xsl:param name="elements" as="element()*"/>
|
2047
|
<xsl:param name="values" as="xs:anyAtomicType*"/>
|
2048
|
|
2049
|
<xsl:for-each select="$elements">
|
2050
|
<xsl:variable name="seq" select="position()"/>
|
2051
|
<xsl:element name="{node-name(.)}">
|
2052
|
<xsl:sequence select="@*, $values[$seq]"/>
|
2053
|
</xsl:element>
|
2054
|
</xsl:for-each>
|
2055
|
|
2056
|
</xsl:function>
|
2057
|
|
2058
|
|
2059
|
<!--
|
2060
|
Replaces the first match of a pattern
|
2061
|
|
2062
|
@author Priscilla Walmsley, Datypic
|
2063
|
@version 1.0
|
2064
|
@see http://www.xsltfunctions.com/xsl/functx_replace-first.html
|
2065
|
@param $arg the entire string to change
|
2066
|
@param $pattern the pattern of characters to replace
|
2067
|
@param $replacement the replacement string
|
2068
|
-->
|
2069
|
<xsl:function name="functx:replace-first" as="xs:string" xmlns:functx="http://www.functx.com">
|
2070
|
<xsl:param name="arg" as="xs:string?"/>
|
2071
|
<xsl:param name="pattern" as="xs:string"/>
|
2072
|
<xsl:param name="replacement" as="xs:string"/>
|
2073
|
|
2074
|
<xsl:sequence select=" replace($arg, concat('(^.*?)', $pattern), concat('$1',$replacement)) "/>
|
2075
|
|
2076
|
</xsl:function>
|
2077
|
|
2078
|
|
2079
|
<!--
|
2080
|
Performs multiple replacements, using pairs of replace parameters
|
2081
|
|
2082
|
@author Priscilla Walmsley, Datypic
|
2083
|
@version 1.0
|
2084
|
@see http://www.xsltfunctions.com/xsl/functx_replace-multi.html
|
2085
|
@param $arg the string to manipulate
|
2086
|
@param $changeFrom the sequence of strings or patterns to change from
|
2087
|
@param $changeTo the sequence of strings to change to
|
2088
|
-->
|
2089
|
<xsl:function name="functx:replace-multi" as="xs:string?" xmlns:functx="http://www.functx.com">
|
2090
|
<xsl:param name="arg" as="xs:string?"/>
|
2091
|
<xsl:param name="changeFrom" as="xs:string*"/>
|
2092
|
<xsl:param name="changeTo" as="xs:string*"/>
|
2093
|
|
2094
|
<xsl:sequence select=" if (count($changeFrom) > 0) then functx:replace-multi( replace($arg, $changeFrom[1], functx:if-absent($changeTo[1],'')), $changeFrom[position() > 1], $changeTo[position() > 1]) else $arg "/>
|
2095
|
|
2096
|
</xsl:function>
|
2097
|
|
2098
|
|
2099
|
<!--
|
2100
|
Reverses the order of characters
|
2101
|
|
2102
|
@author Priscilla Walmsley, Datypic
|
2103
|
@version 1.0
|
2104
|
@see http://www.xsltfunctions.com/xsl/functx_reverse-string.html
|
2105
|
@param $arg the string to reverse
|
2106
|
-->
|
2107
|
<xsl:function name="functx:reverse-string" as="xs:string" xmlns:functx="http://www.functx.com">
|
2108
|
<xsl:param name="arg" as="xs:string?"/>
|
2109
|
|
2110
|
<xsl:sequence select=" codepoints-to-string(reverse(string-to-codepoints($arg))) "/>
|
2111
|
|
2112
|
</xsl:function>
|
2113
|
|
2114
|
|
2115
|
<!--
|
2116
|
Trims trailing whitespace
|
2117
|
|
2118
|
@author Priscilla Walmsley, Datypic
|
2119
|
@version 1.0
|
2120
|
@see http://www.xsltfunctions.com/xsl/functx_right-trim.html
|
2121
|
@param $arg the string to trim
|
2122
|
-->
|
2123
|
<xsl:function name="functx:right-trim" as="xs:string" xmlns:functx="http://www.functx.com">
|
2124
|
<xsl:param name="arg" as="xs:string?"/>
|
2125
|
|
2126
|
<xsl:sequence select=" replace($arg,'\s+$','') "/>
|
2127
|
|
2128
|
</xsl:function>
|
2129
|
|
2130
|
|
2131
|
<!--
|
2132
|
Returns the scheme from a URI
|
2133
|
|
2134
|
@author Priscilla Walmsley, Datypic
|
2135
|
@version 1.0
|
2136
|
@see http://www.xsltfunctions.com/xsl/functx_scheme-from-uri.html
|
2137
|
@param $uri the URI
|
2138
|
-->
|
2139
|
<xsl:function name="functx:scheme-from-uri" as="xs:string?" xmlns:functx="http://www.functx.com">
|
2140
|
<xsl:param name="uri" as="xs:string?"/>
|
2141
|
|
2142
|
<xsl:sequence select=" substring-before($uri,':') "/>
|
2143
|
|
2144
|
</xsl:function>
|
2145
|
|
2146
|
|
2147
|
<!--
|
2148
|
Whether two sequences have the same XML node content and/or values
|
2149
|
|
2150
|
@author Priscilla Walmsley, Datypic
|
2151
|
@version 1.0
|
2152
|
@see http://www.xsltfunctions.com/xsl/functx_sequence-deep-equal.html
|
2153
|
@param $seq1 the first sequence
|
2154
|
@param $seq2 the second sequence
|
2155
|
-->
|
2156
|
<xsl:function name="functx:sequence-deep-equal" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
2157
|
<xsl:param name="seq1" as="item()*"/>
|
2158
|
<xsl:param name="seq2" as="item()*"/>
|
2159
|
|
2160
|
<xsl:sequence select=" every $i in 1 to max((count($seq1),count($seq2))) satisfies deep-equal($seq1[$i],$seq2[$i]) "/>
|
2161
|
|
2162
|
</xsl:function>
|
2163
|
|
2164
|
|
2165
|
<!--
|
2166
|
Whether two sequences contain the same XML nodes, regardless of order
|
2167
|
|
2168
|
@author Priscilla Walmsley, Datypic
|
2169
|
@version 1.0
|
2170
|
@see http://www.xsltfunctions.com/xsl/functx_sequence-node-equal-any-order.html
|
2171
|
@param $seq1 the first sequence of nodes
|
2172
|
@param $seq2 the second sequence of nodes
|
2173
|
-->
|
2174
|
<xsl:function name="functx:sequence-node-equal-any-order" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
2175
|
<xsl:param name="seq1" as="node()*"/>
|
2176
|
<xsl:param name="seq2" as="node()*"/>
|
2177
|
|
2178
|
<xsl:sequence select=" not( ($seq1 except $seq2, $seq2 except $seq1)) "/>
|
2179
|
|
2180
|
</xsl:function>
|
2181
|
|
2182
|
|
2183
|
<!--
|
2184
|
Whether two sequences contain the same XML nodes, in the same order
|
2185
|
|
2186
|
@author Priscilla Walmsley, Datypic
|
2187
|
@version 1.0
|
2188
|
@see http://www.xsltfunctions.com/xsl/functx_sequence-node-equal.html
|
2189
|
@param $seq1 the first sequence of nodes
|
2190
|
@param $seq2 the second sequence of nodes
|
2191
|
-->
|
2192
|
<xsl:function name="functx:sequence-node-equal" as="xs:boolean" xmlns:functx="http://www.functx.com">
|
2193
|
<xsl:param name="seq1" as="node()*"/>
|
2194
|
<xsl:param name="seq2" as="node()*"/>
|
2195
|
|
2196
|
<xsl:sequence select=" every $i in 1 to max((count($seq1),count($seq2))) satisfies $seq1[$i] is $seq2[$i] "/>
|
2197
|
|
2198
|
</xsl:function>
|
2199
|
|
2200
|
|
2201
|
<!--
|
2202
|
The sequence type that represents a sequence of nodes or values
|
2203
|
|
2204
|
@author Priscilla Walmsley, Datypic
|
2205
|
@version 1.0
|
2206
|
@see http://www.xsltfunctions.com/xsl/functx_sequence-type.html
|
2207
|
@param $items the items whose sequence type you want to determine
|
2208
|
-->
|
2209
|
<xsl:function name="functx:sequence-type" as="xs:string" xmlns:functx="http://www.functx.com">
|
2210
|
<xsl:param name="items" as="item()*"/>
|
2211
|
|
2212
|
<xsl:sequence select=" concat( if (empty($items)) then 'empty-sequence()' else if (every $val in $items satisfies $val instance of xs:anyAtomicType) then if (count(distinct-values(functx:atomic-type($items))) > 1) then 'xs:anyAtomicType' else functx:atomic-type($items[1]) else if (some $val in $items satisfies $val instance of xs:anyAtomicType) then 'item()' else if (count(distinct-values(functx:node-kind($items))) > 1) then 'node()' else concat(functx:node-kind($items[1]),'()') , if (count($items) > 1) then '+' else '') "/>
|
2213
|
|
2214
|
</xsl:function>
|
2215
|
|
2216
|
|
2217
|
<!--
|
2218
|
The siblings of an XML element that have the same name
|
2219
|
|
2220
|
@author Priscilla Walmsley, Datypic
|
2221
|
@version 1.0
|
2222
|
@see http://www.xsltfunctions.com/xsl/functx_siblings-same-name.html
|
2223
|
@param $element the node
|
2224
|
-->
|
2225
|
<xsl:function name="functx:siblings-same-name" as="element()*" xmlns:functx="http://www.functx.com">
|
2226
|
<xsl:param name="element" as="element()?"/>
|
2227
|
|
2228
|
<xsl:sequence select=" $element/../*[node-name(.) = node-name($element)] except $element "/>
|
2229
|
|
2230
|
</xsl:function>
|
2231
|
|
2232
|
|
2233
|
<!--
|
2234
|
The siblings of an XML node
|
2235
|
|
2236
|
@author Priscilla Walmsley, Datypic
|
2237
|
@version 1.0
|
2238
|
@see http://www.xsltfunctions.com/xsl/functx_siblings.html
|
2239
|
@param $node the node
|
2240
|
-->
|
2241
|
<xsl:function name="functx:siblings" as="node()*" xmlns:functx="http://www.functx.com">
|
2242
|
<xsl:param name="node" as="node()?"/>
|
2243
|
|
2244
|
<xsl:sequence select=" $node/../node() except $node "/>
|
2245
|
|
2246
|
</xsl:function>
|
2247
|
|
2248
|
|
2249
|
<!--
|
2250
|
Sorts a sequence of numeric values or nodes
|
2251
|
|
2252
|
@author Priscilla Walmsley, Datypic
|
2253
|
@version 1.0
|
2254
|
@see http://www.xsltfunctions.com/xsl/functx_sort-as-numeric.html
|
2255
|
@param $seq the sequence to sort
|
2256
|
-->
|
2257
|
<xsl:function name="functx:sort-as-numeric" as="item()*" xmlns:functx="http://www.functx.com">
|
2258
|
<xsl:param name="seq" as="item()*"/>
|
2259
|
|
2260
|
<xsl:for-each select="$seq">
|
2261
|
<xsl:sort select="number(.)"/>
|
2262
|
<xsl:copy-of select="."/>
|
2263
|
</xsl:for-each>
|
2264
|
|
2265
|
</xsl:function>
|
2266
|
|
2267
|
|
2268
|
<!--
|
2269
|
Sorts a sequence of values or nodes regardless of capitalization
|
2270
|
|
2271
|
@author Priscilla Walmsley, Datypic
|
2272
|
@version 1.0
|
2273
|
@see http://www.xsltfunctions.com/xsl/functx_sort-case-insensitive.html
|
2274
|
@param $seq the sequence to sort
|
2275
|
-->
|
2276
|
<xsl:function name="functx:sort-case-insensitive" as="item()*" xmlns:functx="http://www.functx.com">
|
2277
|
<xsl:param name="seq" as="item()*"/>
|
2278
|
|
2279
|
<xsl:for-each select="$seq">
|
2280
|
<xsl:sort select="upper-case(string(.))"/>
|
2281
|
<xsl:copy-of select="."/>
|
2282
|
</xsl:for-each>
|
2283
|
|
2284
|
</xsl:function>
|
2285
|
|
2286
|
|
2287
|
<!--
|
2288
|
Sorts a sequence of nodes in document order
|
2289
|
|
2290
|
@author Priscilla Walmsley, Datypic
|
2291
|
@version 1.0
|
2292
|
@see http://www.xsltfunctions.com/xsl/functx_sort-document-order.html
|
2293
|
@param $seq the sequence to sort
|
2294
|
-->
|
2295
|
<xsl:function name="functx:sort-document-order" as="node()*" xmlns:functx="http://www.functx.com">
|
2296
|
<xsl:param name="seq" as="node()*"/>
|
2297
|
|
2298
|
<xsl:sequence select=" $seq/. "/>
|
2299
|
|
2300
|
</xsl:function>
|
2301
|
|
2302
|
|
2303
|
<!--
|
2304
|
Sorts a sequence of values or nodes
|
2305
|
|
2306
|
@author Priscilla Walmsley, Datypic
|
2307
|
@version 1.0
|
2308
|
@see http://www.xsltfunctions.com/xsl/functx_sort.html
|
2309
|
@param $seq the sequence to sort
|
2310
|
-->
|
2311
|
<xsl:function name="functx:sort" as="item()*" xmlns:functx="http://www.functx.com">
|
2312
|
<xsl:param name="seq" as="item()*"/>
|
2313
|
|
2314
|
<xsl:for-each select="$seq">
|
2315
|
<xsl:sort select="."/>
|
2316
|
<xsl:copy-of select="."/>
|
2317
|
</xsl:for-each>
|
2318
|
|
2319
|
</xsl:function>
|
2320
|
|
2321
|
|
2322
|
<!--
|
2323
|
Performs substring-after, returning the entire string if it does not contain the delimiter
|
2324
|
|
2325
|
@author Priscilla Walmsley, Datypic
|
2326
|
@version 1.0
|
2327
|
@see http://www.xsltfunctions.com/xsl/functx_substring-after-if-contains.html
|
2328
|
@param $arg the string to substring
|
2329
|
@param $delim the delimiter
|
2330
|
-->
|
2331
|
<xsl:function name="functx:substring-after-if-contains" as="xs:string?" xmlns:functx="http://www.functx.com">
|
2332
|
<xsl:param name="arg" as="xs:string?"/>
|
2333
|
<xsl:param name="delim" as="xs:string"/>
|
2334
|
|
2335
|
<xsl:sequence select=" if (contains($arg,$delim)) then substring-after($arg,$delim) else $arg "/>
|
2336
|
|
2337
|
</xsl:function>
|
2338
|
|
2339
|
|
2340
|
<!--
|
2341
|
The substring after the last text that matches a regex
|
2342
|
|
2343
|
@author Priscilla Walmsley, Datypic
|
2344
|
@version 1.0
|
2345
|
@see http://www.xsltfunctions.com/xsl/functx_substring-after-last-match.html
|
2346
|
@param $arg the string to substring
|
2347
|
@param $regex the regular expression
|
2348
|
-->
|
2349
|
<xsl:function name="functx:substring-after-last-match" as="xs:string" xmlns:functx="http://www.functx.com">
|
2350
|
<xsl:param name="arg" as="xs:string?"/>
|
2351
|
<xsl:param name="regex" as="xs:string"/>
|
2352
|
|
2353
|
<xsl:sequence select=" replace($arg,concat('^.*',$regex),'') "/>
|
2354
|
|
2355
|
</xsl:function>
|
2356
|
|
2357
|
|
2358
|
<!--
|
2359
|
The substring after the last occurrence of a delimiter
|
2360
|
|
2361
|
@author Priscilla Walmsley, Datypic
|
2362
|
@version 1.0
|
2363
|
@see http://www.xsltfunctions.com/xsl/functx_substring-after-last.html
|
2364
|
@param $arg the string to substring
|
2365
|
@param $delim the delimiter
|
2366
|
-->
|
2367
|
<xsl:function name="functx:substring-after-last" as="xs:string" xmlns:functx="http://www.functx.com">
|
2368
|
<xsl:param name="arg" as="xs:string?"/>
|
2369
|
<xsl:param name="delim" as="xs:string"/>
|
2370
|
|
2371
|
<xsl:sequence select=" replace ($arg,concat('^.*',functx:escape-for-regex($delim)),'') "/>
|
2372
|
|
2373
|
</xsl:function>
|
2374
|
|
2375
|
|
2376
|
<!--
|
2377
|
The substring after the first text that matches a regex
|
2378
|
|
2379
|
@author Priscilla Walmsley, Datypic
|
2380
|
@version 1.0
|
2381
|
@see http://www.xsltfunctions.com/xsl/functx_substring-after-match.html
|
2382
|
@param $arg the string to substring
|
2383
|
@param $regex the regular expression
|
2384
|
-->
|
2385
|
<xsl:function name="functx:substring-after-match" as="xs:string?" xmlns:functx="http://www.functx.com">
|
2386
|
<xsl:param name="arg" as="xs:string?"/>
|
2387
|
<xsl:param name="regex" as="xs:string"/>
|
2388
|
|
2389
|
<xsl:sequence select=" replace($arg,concat('^.*?',$regex),'') "/>
|
2390
|
|
2391
|
</xsl:function>
|
2392
|
|
2393
|
|
2394
|
<!--
|
2395
|
Performs substring-before, returning the entire string if it does not contain the delimiter
|
2396
|
|
2397
|
@author Priscilla Walmsley, Datypic
|
2398
|
@version 1.0
|
2399
|
@see http://www.xsltfunctions.com/xsl/functx_substring-before-if-contains.html
|
2400
|
@param $arg the string to substring
|
2401
|
@param $delim the delimiter
|
2402
|
-->
|
2403
|
<xsl:function name="functx:substring-before-if-contains" as="xs:string?" xmlns:functx="http://www.functx.com">
|
2404
|
<xsl:param name="arg" as="xs:string?"/>
|
2405
|
<xsl:param name="delim" as="xs:string"/>
|
2406
|
|
2407
|
<xsl:sequence select=" if (contains($arg,$delim)) then substring-before($arg,$delim) else $arg "/>
|
2408
|
|
2409
|
</xsl:function>
|
2410
|
|
2411
|
|
2412
|
<!--
|
2413
|
The substring after the first text that matches a regex
|
2414
|
|
2415
|
@author Priscilla Walmsley, Datypic
|
2416
|
@version 1.0
|
2417
|
@see http://www.xsltfunctions.com/xsl/functx_substring-before-last-match.html
|
2418
|
@param $arg the string to substring
|
2419
|
@param $regex the regular expression
|
2420
|
-->
|
2421
|
<xsl:function name="functx:substring-before-last-match" as="xs:string?" xmlns:functx="http://www.functx.com">
|
2422
|
<xsl:param name="arg" as="xs:string?"/>
|
2423
|
<xsl:param name="regex" as="xs:string"/>
|
2424
|
|
2425
|
<xsl:sequence select=" replace($arg,concat('^(.*)',$regex,'.*'),'$1') "/>
|
2426
|
|
2427
|
</xsl:function>
|
2428
|
|
2429
|
|
2430
|
<!--
|
2431
|
The substring before the last occurrence of a delimiter
|
2432
|
|
2433
|
@author Priscilla Walmsley, Datypic
|
2434
|
@version 1.0
|
2435
|
@see http://www.xsltfunctions.com/xsl/functx_substring-before-last.html
|
2436
|
@param $arg the string to substring
|
2437
|
@param $delim the delimiter
|
2438
|
-->
|
2439
|
<xsl:function name="functx:substring-before-last" as="xs:string" xmlns:functx="http://www.functx.com">
|
2440
|
<xsl:param name="arg" as="xs:string?"/>
|
2441
|
<xsl:param name="delim" as="xs:string"/>
|
2442
|
|
2443
|
<xsl:sequence select=" if (matches($arg, functx:escape-for-regex($delim))) then replace($arg, concat('^(.*)', functx:escape-for-regex($delim),'.*'), '$1') else '' "/>
|
2444
|
|
2445
|
</xsl:function>
|
2446
|
|
2447
|
|
2448
|
<!--
|
2449
|
The substring before the last text that matches a regex
|
2450
|
|
2451
|
@author Priscilla Walmsley, Datypic
|
2452
|
@version 1.0
|
2453
|
@see http://www.xsltfunctions.com/xsl/functx_substring-before-match.html
|
2454
|
@param $arg the string to substring
|
2455
|
@param $regex the regular expression
|
2456
|
-->
|
2457
|
<xsl:function name="functx:substring-before-match" as="xs:string" xmlns:functx="http://www.functx.com">
|
2458
|
<xsl:param name="arg" as="xs:string?"/>
|
2459
|
<xsl:param name="regex" as="xs:string"/>
|
2460
|
|
2461
|
<xsl:sequence select=" tokenize($arg,$regex)[1] "/>
|
2462
|
|
2463
|
</xsl:function>
|
2464
|
|
2465
|
|
2466
|
<!--
|
2467
|
Construct a time from an hour, minute and second
|
2468
|
|
2469
|
@author Priscilla Walmsley, Datypic
|
2470
|
@version 1.0
|
2471
|
@see http://www.xsltfunctions.com/xsl/functx_time.html
|
2472
|
@param $hour the hour
|
2473
|
@param $minute the minute
|
2474
|
@param $second the second
|
2475
|
-->
|
2476
|
<xsl:function name="functx:time" as="xs:time" xmlns:functx="http://www.functx.com">
|
2477
|
<xsl:param name="hour" as="xs:anyAtomicType"/>
|
2478
|
<xsl:param name="minute" as="xs:anyAtomicType"/>
|
2479
|
<xsl:param name="second" as="xs:anyAtomicType"/>
|
2480
|
|
2481
|
<xsl:sequence select=" xs:time( concat( functx:pad-integer-to-length(xs:integer($hour),2),':', functx:pad-integer-to-length(xs:integer($minute),2),':', functx:pad-integer-to-length(xs:integer($second),2))) "/>
|
2482
|
|
2483
|
</xsl:function>
|
2484
|
|
2485
|
|
2486
|
<!--
|
2487
|
Converts an xs:dayTimeDuration into a timezone like "-05:00" or "Z"
|
2488
|
|
2489
|
@author Priscilla Walmsley, Datypic
|
2490
|
@version 1.0
|
2491
|
@see http://www.xsltfunctions.com/xsl/functx_timezone-from-duration.html
|
2492
|
@param $duration the duration
|
2493
|
-->
|
2494
|
<xsl:function name="functx:timezone-from-duration" as="xs:string" xmlns:functx="http://www.functx.com">
|
2495
|
<xsl:param name="duration" as="xs:dayTimeDuration"/>
|
2496
|
|
2497
|
<xsl:sequence select=" if (string($duration) = ('PT0S','-PT0S')) then 'Z' else if (matches(string($duration),'-PT[1-9]H')) then replace(string($duration),'PT([1-9])H','0$1:00') else if (matches(string($duration),'PT[1-9]H')) then replace(string($duration),'PT([1-9])H','+0$1:00') else if (matches(string($duration),'-PT1[0-4]H')) then replace(string($duration),'PT(1[0-4])H','$1:00') else if (matches(string($duration),'PT1[0-4]H')) then replace(string($duration),'PT(1[0-4])H','+$1:00') else error(xs:QName('functx:Invalid_Duration_Value')) "/>
|
2498
|
|
2499
|
</xsl:function>
|
2500
|
|
2501
|
|
2502
|
<!--
|
2503
|
The total number of days in a dayTimeDuration
|
2504
|
|
2505
|
@author Priscilla Walmsley, Datypic
|
2506
|
@version 1.0
|
2507
|
@see http://www.xsltfunctions.com/xsl/functx_total-days-from-duration.html
|
2508
|
@param $duration the duration
|
2509
|
-->
|
2510
|
<xsl:function name="functx:total-days-from-duration" as="xs:decimal?" xmlns:functx="http://www.functx.com">
|
2511
|
<xsl:param name="duration" as="xs:dayTimeDuration?"/>
|
2512
|
|
2513
|
<xsl:sequence select=" $duration div xs:dayTimeDuration('P1D') "/>
|
2514
|
|
2515
|
</xsl:function>
|
2516
|
|
2517
|
|
2518
|
<!--
|
2519
|
The total number of hours in a dayTimeDuration
|
2520
|
|
2521
|
@author Priscilla Walmsley, Datypic
|
2522
|
@version 1.0
|
2523
|
@see http://www.xsltfunctions.com/xsl/functx_total-hours-from-duration.html
|
2524
|
@param $duration the duration
|
2525
|
-->
|
2526
|
<xsl:function name="functx:total-hours-from-duration" as="xs:decimal?" xmlns:functx="http://www.functx.com">
|
2527
|
<xsl:param name="duration" as="xs:dayTimeDuration?"/>
|
2528
|
|
2529
|
<xsl:sequence select=" $duration div xs:dayTimeDuration('PT1H') "/>
|
2530
|
|
2531
|
</xsl:function>
|
2532
|
|
2533
|
|
2534
|
<!--
|
2535
|
The total number of minutes in a dayTimeDuration
|
2536
|
|
2537
|
@author Priscilla Walmsley, Datypic
|
2538
|
@version 1.0
|
2539
|
@see http://www.xsltfunctions.com/xsl/functx_total-minutes-from-duration.html
|
2540
|
@param $duration the duration
|
2541
|
-->
|
2542
|
<xsl:function name="functx:total-minutes-from-duration" as="xs:decimal?" xmlns:functx="http://www.functx.com">
|
2543
|
<xsl:param name="duration" as="xs:dayTimeDuration?"/>
|
2544
|
|
2545
|
<xsl:sequence select=" $duration div xs:dayTimeDuration('PT1M') "/>
|
2546
|
|
2547
|
</xsl:function>
|
2548
|
|
2549
|
|
2550
|
<!--
|
2551
|
The total number of months in a yearMonthDuration
|
2552
|
|
2553
|
@author Priscilla Walmsley, Datypic
|
2554
|
@version 1.0
|
2555
|
@see http://www.xsltfunctions.com/xsl/functx_total-months-from-duration.html
|
2556
|
@param $duration the duration
|
2557
|
-->
|
2558
|
<xsl:function name="functx:total-months-from-duration" as="xs:decimal?" xmlns:functx="http://www.functx.com">
|
2559
|
<xsl:param name="duration" as="xs:yearMonthDuration?"/>
|
2560
|
|
2561
|
<xsl:sequence select=" $duration div xs:yearMonthDuration('P1M') "/>
|
2562
|
|
2563
|
</xsl:function>
|
2564
|
|
2565
|
|
2566
|
<!--
|
2567
|
The total number of seconds in a dayTimeDuration
|
2568
|
|
2569
|
@author Priscilla Walmsley, Datypic
|
2570
|
@version 1.0
|
2571
|
@see http://www.xsltfunctions.com/xsl/functx_total-seconds-from-duration.html
|
2572
|
@param $duration the duration
|
2573
|
-->
|
2574
|
<xsl:function name="functx:total-seconds-from-duration" as="xs:decimal?" xmlns:functx="http://www.functx.com">
|
2575
|
<xsl:param name="duration" as="xs:dayTimeDuration?"/>
|
2576
|
|
2577
|
<xsl:sequence select=" $duration div xs:dayTimeDuration('PT1S') "/>
|
2578
|
|
2579
|
</xsl:function>
|
2580
|
|
2581
|
|
2582
|
<!--
|
2583
|
The total number of years in a yearMonthDuration
|
2584
|
|
2585
|
@author Priscilla Walmsley, Datypic
|
2586
|
@version 1.0
|
2587
|
@see http://www.xsltfunctions.com/xsl/functx_total-years-from-duration.html
|
2588
|
@param $duration the duration
|
2589
|
-->
|
2590
|
<xsl:function name="functx:total-years-from-duration" as="xs:decimal?" xmlns:functx="http://www.functx.com">
|
2591
|
<xsl:param name="duration" as="xs:yearMonthDuration?"/>
|
2592
|
|
2593
|
<xsl:sequence select=" $duration div xs:yearMonthDuration('P1Y') "/>
|
2594
|
|
2595
|
</xsl:function>
|
2596
|
|
2597
|
|
2598
|
<!--
|
2599
|
Trims leading and trailing whitespace
|
2600
|
|
2601
|
@author Priscilla Walmsley, Datypic
|
2602
|
@version 1.0
|
2603
|
@see http://www.xsltfunctions.com/xsl/functx_trim.html
|
2604
|
@param $arg the string to trim
|
2605
|
-->
|
2606
|
<xsl:function name="functx:trim" as="xs:string" xmlns:functx="http://www.functx.com">
|
2607
|
<xsl:param name="arg" as="xs:string?"/>
|
2608
|
|
2609
|
<xsl:sequence select=" replace(replace($arg,'\s+$',''),'^\s+','') "/>
|
2610
|
|
2611
|
</xsl:function>
|
2612
|
|
2613
|
|
2614
|
<!--
|
2615
|
Updates the attribute value of an XML element
|
2616
|
|
2617
|
@author Priscilla Walmsley, Datypic
|
2618
|
@version 1.0
|
2619
|
@see http://www.xsltfunctions.com/xsl/functx_update-attributes.html
|
2620
|
@param $elements the element(s) for which you wish to update the attribute
|
2621
|
@param $attrNames the name(s) of the attribute(s) to add
|
2622
|
@param $attrValues the value(s) of the attribute(s) to add
|
2623
|
-->
|
2624
|
<xsl:function name="functx:update-attributes" as="element()?" xmlns:functx="http://www.functx.com">
|
2625
|
<xsl:param name="elements" as="element()*"/>
|
2626
|
<xsl:param name="attrNames" as="xs:QName*"/>
|
2627
|
<xsl:param name="attrValues" as="xs:anyAtomicType*"/>
|
2628
|
|
2629
|
<xsl:for-each select="$elements">
|
2630
|
<xsl:variable name="element" select="."/>
|
2631
|
<xsl:copy>
|
2632
|
<xsl:for-each select="$attrNames">
|
2633
|
<xsl:variable name="seq" select="position()"/>
|
2634
|
<xsl:if test="$element/@*[node-name(.) = current()]">
|
2635
|
<xsl:attribute name="{.}" namespace="{namespace-uri-from-QName(.)}" select="$attrValues[$seq]"/>
|
2636
|
</xsl:if>
|
2637
|
</xsl:for-each>
|
2638
|
<xsl:copy-of select="@*[not(node-name(.) = $attrNames)]|node()"/>
|
2639
|
</xsl:copy>
|
2640
|
</xsl:for-each>
|
2641
|
|
2642
|
</xsl:function>
|
2643
|
|
2644
|
|
2645
|
<!--
|
2646
|
The values in one sequence that aren't in another sequence
|
2647
|
|
2648
|
@author W3C XML Query Working Group
|
2649
|
@version 1.0
|
2650
|
@see http://www.xsltfunctions.com/xsl/functx_value-except.html
|
2651
|
@param $arg1 the first sequence
|
2652
|
@param $arg2 the second sequence
|
2653
|
-->
|
2654
|
<xsl:function name="functx:value-except" as="xs:anyAtomicType*" xmlns:functx="http://www.functx.com">
|
2655
|
<xsl:param name="arg1" as="xs:anyAtomicType*"/>
|
2656
|
<xsl:param name="arg2" as="xs:anyAtomicType*"/>
|
2657
|
|
2658
|
<xsl:sequence select=" distinct-values($arg1[not(.=$arg2)]) "/>
|
2659
|
|
2660
|
</xsl:function>
|
2661
|
|
2662
|
|
2663
|
<!--
|
2664
|
The intersection of two sequences of values
|
2665
|
|
2666
|
@author W3C XML Query Working Group
|
2667
|
@version 1.0
|
2668
|
@see http://www.xsltfunctions.com/xsl/functx_value-intersect.html
|
2669
|
@param $arg1 the first sequence
|
2670
|
@param $arg2 the second sequence
|
2671
|
-->
|
2672
|
<xsl:function name="functx:value-intersect" as="xs:anyAtomicType*" xmlns:functx="http://www.functx.com">
|
2673
|
<xsl:param name="arg1" as="xs:anyAtomicType*"/>
|
2674
|
<xsl:param name="arg2" as="xs:anyAtomicType*"/>
|
2675
|
|
2676
|
<xsl:sequence select=" distinct-values($arg1[.=$arg2]) "/>
|
2677
|
|
2678
|
</xsl:function>
|
2679
|
|
2680
|
|
2681
|
<!--
|
2682
|
The union of two sequences of values
|
2683
|
|
2684
|
@author W3C XML Query Working Group
|
2685
|
@version 1.0
|
2686
|
@see http://www.xsltfunctions.com/xsl/functx_value-union.html
|
2687
|
@param $arg1 the first sequence
|
2688
|
@param $arg2 the second sequence
|
2689
|
-->
|
2690
|
<xsl:function name="functx:value-union" as="xs:anyAtomicType*" xmlns:functx="http://www.functx.com">
|
2691
|
<xsl:param name="arg1" as="xs:anyAtomicType*"/>
|
2692
|
<xsl:param name="arg2" as="xs:anyAtomicType*"/>
|
2693
|
|
2694
|
<xsl:sequence select=" distinct-values(($arg1, $arg2)) "/>
|
2695
|
|
2696
|
</xsl:function>
|
2697
|
|
2698
|
|
2699
|
<!--
|
2700
|
The number of words
|
2701
|
|
2702
|
@author Priscilla Walmsley, Datypic
|
2703
|
@version 1.0
|
2704
|
@see http://www.xsltfunctions.com/xsl/functx_word-count.html
|
2705
|
@param $arg the string to measure
|
2706
|
-->
|
2707
|
<xsl:function name="functx:word-count" as="xs:integer" xmlns:functx="http://www.functx.com">
|
2708
|
<xsl:param name="arg" as="xs:string?"/>
|
2709
|
|
2710
|
<xsl:sequence select=" count(tokenize($arg, '\W+')[. != '']) "/>
|
2711
|
|
2712
|
</xsl:function>
|
2713
|
|
2714
|
|
2715
|
<!--
|
2716
|
Turns a string of words into camelCase
|
2717
|
|
2718
|
@author Priscilla Walmsley, Datypic
|
2719
|
@version 1.0
|
2720
|
@see http://www.xsltfunctions.com/xsl/functx_words-to-camel-case.html
|
2721
|
@param $arg the string to modify
|
2722
|
-->
|
2723
|
<xsl:function name="functx:words-to-camel-case" as="xs:string" xmlns:functx="http://www.functx.com">
|
2724
|
<xsl:param name="arg" as="xs:string?"/>
|
2725
|
|
2726
|
<xsl:sequence select=" string-join((tokenize($arg,'\s+')[1], for $word in tokenize($arg,'\s+')[position() > 1] return functx:capitalize-first($word)) ,'') "/>
|
2727
|
|
2728
|
</xsl:function>
|
2729
|
|
2730
|
|
2731
|
<!--
|
2732
|
Wraps a sequence of atomic values in XML elements
|
2733
|
|
2734
|
@author Priscilla Walmsley, Datypic
|
2735
|
@version 1.0
|
2736
|
@see http://www.xsltfunctions.com/xsl/functx_wrap-values-in-elements.html
|
2737
|
@param $values the values to wrap in elements
|
2738
|
@param $elementName the name of the elements to construct
|
2739
|
-->
|
2740
|
<xsl:function name="functx:wrap-values-in-elements" as="element()*" xmlns:functx="http://www.functx.com">
|
2741
|
<xsl:param name="values" as="xs:anyAtomicType*"/>
|
2742
|
<xsl:param name="elementName" as="xs:QName"/>
|
2743
|
|
2744
|
<xsl:for-each select="$values">
|
2745
|
<xsl:element name="{$elementName}" namespace="{namespace-uri-from-QName($elementName)}">
|
2746
|
<xsl:sequence select="."/>
|
2747
|
</xsl:element>
|
2748
|
</xsl:for-each>
|
2749
|
|
2750
|
</xsl:function>
|
2751
|
|
2752
|
|
2753
|
<!--
|
2754
|
Construct a yearMonthDuration from a number of years and months
|
2755
|
|
2756
|
@author Priscilla Walmsley, Datypic
|
2757
|
@version 1.0
|
2758
|
@see http://www.xsltfunctions.com/xsl/functx_yearmonthduration.html
|
2759
|
@param $years the number of years
|
2760
|
@param $months the number of months
|
2761
|
-->
|
2762
|
<xsl:function name="functx:yearMonthDuration" as="xs:yearMonthDuration" xmlns:functx="http://www.functx.com">
|
2763
|
<xsl:param name="years" as="xs:decimal?"/>
|
2764
|
<xsl:param name="months" as="xs:integer?"/>
|
2765
|
|
2766
|
<xsl:sequence select=" (xs:yearMonthDuration('P1M') * functx:if-empty($months,0)) + (xs:yearMonthDuration('P1Y') * functx:if-empty($years,0)) "/>
|
2767
|
|
2768
|
</xsl:function>
|
2769
|
|
2770
|
|
2771
|
</xsl:stylesheet>
|