this file is imported in the multipage it provides some string parsing
[cdmlib.git] / cdmlib-print / src / main / resources / stylesheets / mediawiki / functx-1.0-doc-2007-01.xsl
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 &gt; $minValue and $value &lt; $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 &gt;= $minValue and $value &lt;= $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() &lt; $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() &lt; $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 &gt;&gt; $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]) &gt; 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 &lt; 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) &lt;= 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 &lt;&lt; $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) &gt; 0) then functx:replace-multi( replace($arg, $changeFrom[1], functx:if-absent($changeTo[1],'')), $changeFrom[position() &gt; 1], $changeTo[position() &gt; 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))) &gt; 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))) &gt; 1) then 'node()' else concat(functx:node-kind($items[1]),'()') , if (count($items) &gt; 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() &gt; 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>