3 ********************************
4 The FunctX XSLT Function Library
5 ********************************
7 Copyright (C) 2007 Datypic
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.
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.
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
23 For more information on the FunctX XSLT library, contact contrib@functx.com.
26 @see http://www.xsltfunctions.com
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">
31 Adds attributes to XML elements
33 @author Priscilla Walmsley, Datypic
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
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*"/>
45 <xsl:for-each select="$elements">
46 <xsl:variable name="element" select="."/>
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]"/>
54 <xsl:copy-of select="@*|node()"/>
64 @author Priscilla Walmsley, Datypic
66 @see http://www.xsltfunctions.com/xsl/functx_add-months.html
68 @param $months the number of months to add
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"/>
74 <xsl:sequence select=" xs:date($date) + functx:yearMonthDuration(0,$months) "/>
80 Adds attributes to XML elements
82 @author Priscilla Walmsley, Datypic
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
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*"/>
94 <xsl:for-each select="$elements">
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]"/>
100 <xsl:copy-of select="@*[not(node-name(.) = $attrNames)]|node()"/>
108 Whether a value is all whitespace or a zero-length string
110 @author Priscilla Walmsley, Datypic
112 @see http://www.xsltfunctions.com/xsl/functx_all-whitespace.html
113 @param $arg the string (or node) to test
115 <xsl:function name="functx:all-whitespace" as="xs:boolean" xmlns:functx="http://www.functx.com">
116 <xsl:param name="arg" as="xs:string?"/>
118 <xsl:sequence select=" normalize-space($arg) = '' "/>
124 Whether all the values in a sequence are distinct
126 @author Priscilla Walmsley, Datypic
128 @see http://www.xsltfunctions.com/xsl/functx_are-distinct-values.html
129 @param $seq the sequence of values
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*"/>
134 <xsl:sequence select=" count(distinct-values($seq)) = count($seq) "/>
140 The built-in type of an atomic value
142 @author Priscilla Walmsley, Datypic
144 @see http://www.xsltfunctions.com/xsl/functx_atomic-type.html
145 @param $values the value(s) whose type you want to determine
147 <xsl:function name="functx:atomic-type" as="xs:string*" xmlns:functx="http://www.functx.com">
148 <xsl:param name="values" as="xs:anyAtomicType*"/>
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') "/>
156 The average, counting "empty" values as zero
158 @author Priscilla Walmsley, Datypic
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
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()*"/>
168 <xsl:sequence select=" if (empty($allNodes)) then 0 else sum($values[string(.) != '']) div count($allNodes) "/>
174 Whether a value is between two provided values
176 @author Priscilla Walmsley, Datypic
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
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"/>
188 <xsl:sequence select=" $value > $minValue and $value < $maxValue "/>
194 Whether a value is between two provided values, or equal to one of them
196 @author Priscilla Walmsley, Datypic
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
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"/>
208 <xsl:sequence select=" $value >= $minValue and $value <= $maxValue "/>
214 Turns a camelCase string into space-separated words
216 @author Priscilla Walmsley, Datypic
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)
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"/>
226 <xsl:sequence select=" concat(substring($arg,1,1), replace(substring($arg,2),'(\p{Lu})', concat($delim, '$1'))) "/>
232 Capitalizes the first character of a string
234 @author Priscilla Walmsley, Datypic
236 @see http://www.xsltfunctions.com/xsl/functx_capitalize-first.html
237 @param $arg the word or phrase to capitalize
239 <xsl:function name="functx:capitalize-first" as="xs:string?" xmlns:functx="http://www.functx.com">
240 <xsl:param name="arg" as="xs:string?"/>
242 <xsl:sequence select=" concat(upper-case(substring($arg,1,1)), substring($arg,2)) "/>
248 Changes the names of elements in an XML fragment
250 @author Priscilla Walmsley, Datypic
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
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*"/>
262 <xsl:if test="count($oldNames) != count($newNames)">
263 <xsl:sequence select="error( xs:QName('functx:Different_number_of_names'))"/>
265 <xsl:for-each select="$nodes">
266 <xsl:variable name="node" select="."/>
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))"/>
274 <xsl:when test="$node instance of document-node()">
276 <xsl:sequence select="functx:change-element-names-deep( $node/node(), $oldNames, $newNames)"/>
280 <xsl:sequence select="$node"/>
289 Changes the namespace of XML elements and its descendants
291 @author Priscilla Walmsley, Datypic
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
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"/>
303 <xsl:for-each select="$nodes">
304 <xsl:variable name="node" select="."/>
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))"/>
311 <xsl:when test="$node instance of document-node()">
313 <xsl:sequence select="functx:change-element-ns-deep( $node/node(), $newns, $prefix)"/>
317 <xsl:sequence select="$node"/>
326 Changes the namespace of XML elements
328 @author Priscilla Walmsley, Datypic
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
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"/>
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()"/>
351 Converts a string to a sequence of characters
353 @author Priscilla Walmsley, Datypic
355 @see http://www.xsltfunctions.com/xsl/functx_chars.html
356 @param $arg the string to split
358 <xsl:function name="functx:chars" as="xs:string*" xmlns:functx="http://www.functx.com">
359 <xsl:param name="arg" as="xs:string?"/>
361 <xsl:sequence select=" for $ch in string-to-codepoints($arg) return codepoints-to-string($ch) "/>
367 Whether a string contains any of a sequence of strings
369 @author Priscilla Walmsley, Datypic
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
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*"/>
379 <xsl:sequence select=" some $searchString in $searchStrings satisfies contains($arg,$searchString) "/>
385 Whether one string contains another, without regard to case
387 @author Priscilla Walmsley, Datypic
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
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"/>
397 <xsl:sequence select=" contains(upper-case($arg), upper-case($substring)) "/>
403 Whether one string contains another, as a separate word
405 @author Priscilla Walmsley, Datypic
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
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"/>
415 <xsl:sequence select=" matches(upper-case($arg), concat('^(.*\W)?', upper-case(functx:escape-for-regex($word)), '(\W.*)?$')) "/>
421 Copies attributes from one element to another
423 @author Priscilla Walmsley, Datypic
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
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()"/>
433 <xsl:element name="{node-name($copyTo)}">
434 <xsl:sequence select=" ($copyTo/@*[not(node-name(.) = $copyFrom/@*/node-name(.))], $copyFrom/@*, $copyTo/node())"/>
441 Construct a date from a year, month and day
443 @author Priscilla Walmsley, Datypic
445 @see http://www.xsltfunctions.com/xsl/functx_date.html
446 @param $year the year
447 @param $month the month
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"/>
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))) "/>
461 Construct a date/time from individual components
463 @author Priscilla Walmsley, Datypic
465 @see http://www.xsltfunctions.com/xsl/functx_datetime.html
466 @param $year the year
467 @param $month the month
469 @param $hour the hour
470 @param $minute the minute
471 @param $second the second
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"/>
481 <xsl:sequence select=" xs:dateTime( concat(functx:date($year,$month,$day),'T', functx:time($hour,$minute,$second))) "/>
487 The day of the year (a number between 1 and 366)
489 @author Priscilla Walmsley, Datypic
491 @see http://www.xsltfunctions.com/xsl/functx_day-in-year.html
492 @param $date the date
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?"/>
497 <xsl:sequence select=" days-from-duration( xs:date($date) - functx:first-day-of-year($date)) + 1 "/>
503 The abbreviated day of the week, from a date, in English
505 @author Priscilla Walmsley, Datypic
507 @see http://www.xsltfunctions.com/xsl/functx_day-of-week-abbrev-en.html
508 @param $date the date
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?"/>
513 <xsl:sequence select=" ('Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat') [functx:day-of-week($date) + 1] "/>
519 The name of the day of the week, from a date, in English
521 @author Priscilla Walmsley, Datypic
523 @see http://www.xsltfunctions.com/xsl/functx_day-of-week-name-en.html
524 @param $date the date
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?"/>
529 <xsl:sequence select=" ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday') [functx:day-of-week($date) + 1] "/>
535 The day of the week, from a date
537 @author Priscilla Walmsley, Datypic
539 @see http://www.xsltfunctions.com/xsl/functx_day-of-week.html
540 @param $date the date
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?"/>
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 "/>
551 Construct a dayTimeDuration from a number of days, hours, etc.
553 @author Priscilla Walmsley, Datypic
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
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?"/>
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)) "/>
573 Number of days in the month
575 @author Priscilla Walmsley, Datypic
577 @see http://www.xsltfunctions.com/xsl/functx_days-in-month.html
578 @param $date the date
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?"/>
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))] "/>
589 The depth (level) of a node in an XML tree
591 @author Priscilla Walmsley, Datypic
593 @see http://www.xsltfunctions.com/xsl/functx_depth-of-node.html
594 @param $node the node to check
596 <xsl:function name="functx:depth-of-node" as="xs:integer" xmlns:functx="http://www.functx.com">
597 <xsl:param name="node" as="node()?"/>
599 <xsl:sequence select=" count($node/ancestor-or-self::node()) "/>
605 The distinct names of all attributes in an XML fragment
607 @author Priscilla Walmsley, Datypic
609 @see http://www.xsltfunctions.com/xsl/functx_distinct-attribute-names.html
610 @param $nodes the root to start from
612 <xsl:function name="functx:distinct-attribute-names" as="xs:string*" xmlns:functx="http://www.functx.com">
613 <xsl:param name="nodes" as="node()*"/>
615 <xsl:sequence select=" distinct-values($nodes//@*/name(.)) "/>
621 The XML nodes with distinct values, taking into account attributes and descendants
623 @author Priscilla Walmsley, Datypic
625 @see http://www.xsltfunctions.com/xsl/functx_distinct-deep.html
626 @param $nodes the sequence of nodes to test
628 <xsl:function name="functx:distinct-deep" as="node()*" xmlns:functx="http://www.functx.com">
629 <xsl:param name="nodes" as="node()*"/>
631 <xsl:sequence select=" for $seq in (1 to count($nodes)) return $nodes[$seq][not(functx:is-node-in-sequence-deep-equal( .,$nodes[position() < $seq]))] "/>
637 The distinct names of all elements in an XML fragment
639 @author Priscilla Walmsley, Datypic
641 @see http://www.xsltfunctions.com/xsl/functx_distinct-element-names.html
642 @param $nodes the root(s) to start from
644 <xsl:function name="functx:distinct-element-names" as="xs:string*" xmlns:functx="http://www.functx.com">
645 <xsl:param name="nodes" as="node()*"/>
647 <xsl:sequence select=" distinct-values($nodes/descendant-or-self::*/name(.)) "/>
653 The distinct paths of all descendant elements in an XML fragment
655 @author Priscilla Walmsley, Datypic
657 @see http://www.xsltfunctions.com/xsl/functx_distinct-element-paths.html
658 @param $nodes the root(s) to start from
660 <xsl:function name="functx:distinct-element-paths" as="xs:string*" xmlns:functx="http://www.functx.com">
661 <xsl:param name="nodes" as="node()*"/>
663 <xsl:sequence select=" distinct-values(functx:path-to-node($nodes/descendant-or-self::*)) "/>
669 The distinct XML nodes in a sequence (by node identity)
671 @author Priscilla Walmsley, Datypic
673 @see http://www.xsltfunctions.com/xsl/functx_distinct-nodes.html
674 @param $nodes the node sequence
676 <xsl:function name="functx:distinct-nodes" as="node()*" xmlns:functx="http://www.functx.com">
677 <xsl:param name="nodes" as="node()*"/>
679 <xsl:sequence select=" for $seq in (1 to count($nodes)) return $nodes[$seq][not(functx:is-node-in-sequence( .,$nodes[position() < $seq]))] "/>
685 Converts a timezone like "-05:00" or "Z" into xs:dayTimeDuration
687 @author Priscilla Walmsley, Datypic
689 @see http://www.xsltfunctions.com/xsl/functx_duration-from-timezone.html
690 @param $timezone the time zone, in (+|-)HH:MM format
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"/>
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') ) "/>
701 Dynamically evaluates a simple XPath path
703 @author Priscilla Walmsley, Datypic
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
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"/>
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"/>
724 Escapes regex special characters
726 @author Priscilla Walmsley, Datypic
728 @see http://www.xsltfunctions.com/xsl/functx_escape-for-regex.html
729 @param $arg the string to escape
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?"/>
734 <xsl:sequence select=" replace($arg, '(\.|\[|\]|\\|\||\-|\^|\$|\?|\*|\+|\{|\}|\(|\))','\\$1') "/>
740 Whether one (and only one) of two boolean values is true
742 @author Priscilla Walmsley, Datypic
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
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?"/>
752 <xsl:sequence select=" $arg1 != $arg2 "/>
758 The first day of the month of a date
760 @author Priscilla Walmsley, Datypic
762 @see http://www.xsltfunctions.com/xsl/functx_first-day-of-month.html
763 @param $date the date
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?"/>
768 <xsl:sequence select=" functx:date(year-from-date(xs:date($date)), month-from-date(xs:date($date)), 1) "/>
774 The first day of the year of a date
776 @author Priscilla Walmsley, Datypic
778 @see http://www.xsltfunctions.com/xsl/functx_first-day-of-year.html
779 @param $date the date
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?"/>
784 <xsl:sequence select=" functx:date(year-from-date(xs:date($date)), 1, 1) "/>
790 The XML node in a sequence that appears first in document order
792 @author Priscilla Walmsley, Datypic
794 @see http://www.xsltfunctions.com/xsl/functx_first-node.html
795 @param $nodes the sequence of nodes
797 <xsl:function name="functx:first-node" as="node()?" xmlns:functx="http://www.functx.com">
798 <xsl:param name="nodes" as="node()*"/>
800 <xsl:sequence select=" ($nodes/.)[1] "/>
806 Whether an XML node follows another without being its descendant
808 @author W3C XML Query Working Group
810 @see http://www.xsltfunctions.com/xsl/functx_follows-not-descendant.html
811 @param $a the first node
812 @param $b the second node
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()?"/>
818 <xsl:sequence select=" $a >> $b and empty($b intersect $a/ancestor::node()) "/>
824 Moves title words like "the" and "a" to the end of strings
826 @author Priscilla Walmsley, Datypic
828 @see http://www.xsltfunctions.com/xsl/functx_format-as-title-en.html
829 @param $titles the titles to format
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*"/>
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"/>
845 Returns the fragment from a URI
847 @author Priscilla Walmsley, Datypic
849 @see http://www.xsltfunctions.com/xsl/functx_fragment-from-uri.html
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?"/>
855 <xsl:sequence select=" substring-after($uri,'#') "/>
861 Whether an element has element-only content
863 @author Priscilla Walmsley, Datypic
865 @see http://www.xsltfunctions.com/xsl/functx_has-element-only-content.html
866 @param $element the XML element to test
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()"/>
871 <xsl:sequence select=" not($element/text()[normalize-space(.) != '']) and $element/* "/>
877 Whether an element has empty content
879 @author Priscilla Walmsley, Datypic
881 @see http://www.xsltfunctions.com/xsl/functx_has-empty-content.html
882 @param $element the XML element to test
884 <xsl:function name="functx:has-empty-content" as="xs:boolean" xmlns:functx="http://www.functx.com">
885 <xsl:param name="element" as="element()"/>
887 <xsl:sequence select=" not($element/node()) "/>
893 Whether an element has mixed content
895 @author Priscilla Walmsley, Datypic
897 @see http://www.xsltfunctions.com/xsl/functx_has-mixed-content.html
898 @param $element the XML element to test
900 <xsl:function name="functx:has-mixed-content" as="xs:boolean" xmlns:functx="http://www.functx.com">
901 <xsl:param name="element" as="element()"/>
903 <xsl:sequence select=" $element/text()[normalize-space(.) != ''] and $element/* "/>
909 Whether an element has simple content
911 @author Priscilla Walmsley, Datypic
913 @see http://www.xsltfunctions.com/xsl/functx_has-simple-content.html
914 @param $element the XML element to test
916 <xsl:function name="functx:has-simple-content" as="xs:boolean" xmlns:functx="http://www.functx.com">
917 <xsl:param name="element" as="element()"/>
919 <xsl:sequence select=" $element/text() and not($element/*) "/>
925 Gets the ID of an XML element
927 @author Priscilla Walmsley, Datypic
929 @see http://www.xsltfunctions.com/xsl/functx_id-from-element.html
930 @param $element the element
932 <xsl:function name="functx:id-from-element" as="xs:string?" xmlns:functx="http://www.functx.com">
933 <xsl:param name="element" as="element()?"/>
935 <xsl:sequence select=" data(($element/@*[id(.) is ..])[1]) "/>
941 Gets XML element(s) that have an attribute with a particular value
943 @author Priscilla Walmsley, Datypic
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
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"/>
953 <xsl:sequence select=" $node//*[@* = $id] "/>
959 The first argument if it is not empty, otherwise the second argument
961 @author W3C XML Query WG
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
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()*"/>
971 <xsl:sequence select=" if (exists($arg)) then $arg else $value "/>
977 The first argument if it is not blank, otherwise the second argument
979 @author Priscilla Walmsley, Datypic
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
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()*"/>
989 <xsl:sequence select=" if (string($arg) != '') then data($arg) else $value "/>
995 The position of a node in a sequence, based on contents and attributes
997 @author Priscilla Walmsley, Datypic
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
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()"/>
1007 <xsl:sequence select=" for $seq in (1 to count($nodes)) return $seq[deep-equal($nodes[$seq],$nodeToFind)] "/>
1013 The first position of a matching substring
1015 @author Priscilla Walmsley, Datypic
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
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"/>
1025 <xsl:sequence select=" if (matches($arg,$pattern)) then string-length(tokenize($arg, $pattern)[1]) + 1 else () "/>
1031 The position of a node in a sequence, based on node identity
1033 @author W3C XML Query Working Group
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
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()"/>
1043 <xsl:sequence select=" for $seq in (1 to count($nodes)) return $seq[$nodes[$seq] is $nodeToFind] "/>
1049 The first position of a substring
1051 @author Priscilla Walmsley, Datypic
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
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"/>
1061 <xsl:sequence select=" if (contains($arg, $substring)) then string-length(substring-before($arg, $substring))+1 else () "/>
1067 The last position of a substring
1069 @author Priscilla Walmsley, Datypic
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
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"/>
1079 <xsl:sequence select=" functx:index-of-string($arg, $substring)[last()] "/>
1085 The position(s) of a substring
1087 @author Priscilla Walmsley, Datypic
1089 @see http://www.xsltfunctions.com/xsl/functx_index-of-string.html
1090 @param $arg the string
1091 @param $substring the substring to find
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"/>
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 () "/>
1103 Inserts a string at a specified position
1105 @author Priscilla Walmsley, Datypic
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
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"/>
1117 <xsl:sequence select=" concat(substring($originalString,1,$pos - 1), $stringToInsert, substring($originalString,$pos)) "/>
1123 Whether a value is numeric
1125 @author Priscilla Walmsley, Datypic
1127 @see http://www.xsltfunctions.com/xsl/functx_is-a-number.html
1128 @param $value the value to test
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?"/>
1133 <xsl:sequence select=" string(number($value)) != 'NaN' "/>
1139 Whether a URI is absolute
1141 @author Priscilla Walmsley, Datypic
1143 @see http://www.xsltfunctions.com/xsl/functx_is-absolute-uri.html
1144 @param $uri the URI to test
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?"/>
1149 <xsl:sequence select=" matches($uri,'^[a-z]+:') "/>
1155 Whether an XML node is an ancestor of another node
1157 @author Priscilla Walmsley, Datypic
1159 @see http://www.xsltfunctions.com/xsl/functx_is-ancestor.html
1160 @param $node1 the first node
1161 @param $node2 the second node
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()"/>
1167 <xsl:sequence select=" exists($node1 intersect $node2/ancestor::node()) "/>
1173 Whether an XML node is a descendant of another node
1175 @author Priscilla Walmsley, Datypic
1177 @see http://www.xsltfunctions.com/xsl/functx_is-descendant.html
1178 @param $node1 the first node
1179 @param $node2 the second node
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()"/>
1185 <xsl:sequence select=" boolean($node2 intersect $node1/ancestor::node()) "/>
1191 Whether a date falls in a leap year
1193 @author Priscilla Walmsley, Datypic
1195 @see http://www.xsltfunctions.com/xsl/functx_is-leap-year.html
1196 @param $date the date or year
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?"/>
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 "/>
1207 Whether an XML node is among the descendants of a sequence, based on contents and attributes
1209 @author Priscilla Walmsley, Datypic
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
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()*"/>
1219 <xsl:sequence select=" some $nodeInSeq in $seq/descendant-or-self::*/(.|@*) satisfies deep-equal($nodeInSeq,$node) "/>
1225 Whether an XML node is among the descendants of a sequence, based on node identity
1227 @author Priscilla Walmsley, Datypic
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
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()*"/>
1237 <xsl:sequence select=" some $nodeInSeq in $seq/descendant-or-self::*/(.|@*) satisfies $nodeInSeq is $node "/>
1243 Whether an XML node is in a sequence, based on contents and attributes
1245 @author Priscilla Walmsley, Datypic
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
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()*"/>
1255 <xsl:sequence select=" some $nodeInSeq in $seq satisfies deep-equal($nodeInSeq,$node) "/>
1261 Whether an XML node is in a sequence, based on node identity
1263 @author Priscilla Walmsley, Datypic
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
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()*"/>
1273 <xsl:sequence select=" some $nodeInSeq in $seq satisfies $nodeInSeq is $node "/>
1279 Whether an atomic value appears in a sequence
1281 @author Priscilla Walmsley, Datypic
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
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*"/>
1291 <xsl:sequence select=" $value = $seq "/>
1297 The last day of the month of a date
1299 @author Priscilla Walmsley, Datypic
1301 @see http://www.xsltfunctions.com/xsl/functx_last-day-of-month.html
1302 @param $date the date
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?"/>
1307 <xsl:sequence select=" functx:date(year-from-date(xs:date($date)), month-from-date(xs:date($date)), functx:days-in-month($date)) "/>
1313 The last day of the month of a date
1315 @author Priscilla Walmsley, Datypic
1317 @see http://www.xsltfunctions.com/xsl/functx_last-day-of-year.html
1318 @param $date the date
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?"/>
1323 <xsl:sequence select=" functx:date(year-from-date(xs:date($date)), 12, 31) "/>
1329 The XML node in a sequence that is last in document order
1331 @author Priscilla Walmsley, Datypic
1333 @see http://www.xsltfunctions.com/xsl/functx_last-node.html
1334 @param $nodes the sequence of nodes
1336 <xsl:function name="functx:last-node" as="node()?" xmlns:functx="http://www.functx.com">
1337 <xsl:param name="nodes" as="node()*"/>
1339 <xsl:sequence select=" ($nodes/.)[last()] "/>
1345 All XML elements that don't have any child elements
1347 @author Priscilla Walmsley, Datypic
1349 @see http://www.xsltfunctions.com/xsl/functx_leaf-elements.html
1350 @param $root the root
1352 <xsl:function name="functx:leaf-elements" as="element()*" xmlns:functx="http://www.functx.com">
1353 <xsl:param name="root" as="node()?"/>
1355 <xsl:sequence select=" $root/descendant-or-self::*[not(*)] "/>
1361 Trims leading whitespace
1363 @author Priscilla Walmsley, Datypic
1365 @see http://www.xsltfunctions.com/xsl/functx_left-trim.html
1366 @param $arg the string to trim
1368 <xsl:function name="functx:left-trim" as="xs:string" xmlns:functx="http://www.functx.com">
1369 <xsl:param name="arg" as="xs:string?"/>
1371 <xsl:sequence select=" replace($arg,'^\s+','') "/>
1379 @author Priscilla Walmsley, Datypic
1381 @see http://www.xsltfunctions.com/xsl/functx_line-count.html
1382 @param $arg the string to test
1384 <xsl:function name="functx:line-count" as="xs:integer" xmlns:functx="http://www.functx.com">
1385 <xsl:param name="arg" as="xs:string?"/>
1387 <xsl:sequence select=" count(functx:lines($arg)) "/>
1393 Split a string into separate lines
1395 @author Priscilla Walmsley, Datypic
1397 @see http://www.xsltfunctions.com/xsl/functx_lines.html
1398 @param $arg the string to split
1400 <xsl:function name="functx:lines" as="xs:string*" xmlns:functx="http://www.functx.com">
1401 <xsl:param name="arg" as="xs:string?"/>
1403 <xsl:sequence select=" tokenize($arg, '(\r\n?|\n\r?)') "/>
1409 The maximum depth of elements in an XML tree
1411 @author Priscilla Walmsley, Datypic
1413 @see http://www.xsltfunctions.com/xsl/functx_max-depth.html
1414 @param $root the root to start from
1416 <xsl:function name="functx:max-depth" as="xs:integer?" xmlns:functx="http://www.functx.com">
1417 <xsl:param name="root" as="node()?"/>
1419 <xsl:sequence select=" if ($root/*) then max($root/*/functx:max-depth(.)) + 1 else 1 "/>
1425 The maximum value in a sequence, figuring out its type (numeric or string)
1427 @author Priscilla Walmsley, Datypic
1429 @see http://www.xsltfunctions.com/xsl/functx_max-determine-type.html
1430 @param $seq the sequence of values to test
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*"/>
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)) "/>
1441 The maximum line length
1443 @author Priscilla Walmsley, Datypic
1445 @see http://www.xsltfunctions.com/xsl/functx_max-line-length.html
1446 @param $arg the string to test
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?"/>
1451 <xsl:sequence select=" max( for $line in functx:lines($arg) return string-length($line)) "/>
1457 The XML node whose typed value is the maximum
1459 @author Priscilla Walmsley, Datypic
1461 @see http://www.xsltfunctions.com/xsl/functx_max-node.html
1462 @param $nodes the sequence of nodes to test
1464 <xsl:function name="functx:max-node" as="node()*" xmlns:functx="http://www.functx.com">
1465 <xsl:param name="nodes" as="node()*"/>
1467 <xsl:sequence select=" $nodes[. = max($nodes)] "/>
1473 The maximum of a sequence of values, treating them like strings
1475 @author Priscilla Walmsley, Datypic
1477 @see http://www.xsltfunctions.com/xsl/functx_max-string.html
1478 @param $strings the sequence of values
1480 <xsl:function name="functx:max-string" as="xs:string?" xmlns:functx="http://www.functx.com">
1481 <xsl:param name="strings" as="xs:anyAtomicType*"/>
1483 <xsl:sequence select=" max(for $string in $strings return string($string)) "/>
1489 The minimum value in a sequence, figuring out its type (numeric or string)
1491 @author Priscilla Walmsley, Datypic
1493 @see http://www.xsltfunctions.com/xsl/functx_min-determine-type.html
1494 @param $seq the sequence of values to test
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*"/>
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)) "/>
1505 The XML node whose typed value is the minimum
1507 @author Priscilla Walmsley, Datypic
1509 @see http://www.xsltfunctions.com/xsl/functx_min-node.html
1510 @param $nodes the sequence of nodes to test
1512 <xsl:function name="functx:min-node" as="node()*" xmlns:functx="http://www.functx.com">
1513 <xsl:param name="nodes" as="node()*"/>
1515 <xsl:sequence select=" $nodes[. = min($nodes)] "/>
1521 The minimum of a sequence of strings, ignoring "empty" values
1523 @author Priscilla Walmsley, Datypic
1525 @see http://www.xsltfunctions.com/xsl/functx_min-non-empty-string.html
1526 @param $strings the sequence of strings to search
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*"/>
1531 <xsl:sequence select=" min($strings[. != '']) "/>
1537 The minimum of a sequence of values, treating them like strings
1539 @author Priscilla Walmsley, Datypic
1541 @see http://www.xsltfunctions.com/xsl/functx_min-string.html
1542 @param $strings the sequence of strings
1544 <xsl:function name="functx:min-string" as="xs:string?" xmlns:functx="http://www.functx.com">
1545 <xsl:param name="strings" as="xs:anyAtomicType*"/>
1547 <xsl:sequence select=" min(for $string in $strings return string($string)) "/>
1553 Converts a string with format MMDDYYYY (with any delimiters) to a date
1555 @author Priscilla Walmsley, Datypic
1557 @see http://www.xsltfunctions.com/xsl/functx_mmddyyyy-to-date.html
1558 @param $dateString the MMDDYYYY string
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?"/>
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')) "/>
1569 The month of a date as an abbreviated word (Jan, Feb, etc.)
1571 @author Priscilla Walmsley, Datypic
1573 @see http://www.xsltfunctions.com/xsl/functx_month-abbrev-en.html
1574 @param $date the date
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?"/>
1579 <xsl:sequence select=" ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') [month-from-date(xs:date($date))] "/>
1585 The month of a date as a word (January, February, etc.)
1587 @author Priscilla Walmsley, Datypic
1589 @see http://www.xsltfunctions.com/xsl/functx_month-name-en.html
1590 @param $date the date
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?"/>
1595 <xsl:sequence select=" ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December') [month-from-date(xs:date($date))] "/>
1601 Whether a name matches a list of names or name wildcards
1603 @author Priscilla Walmsley, Datypic
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
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*"/>
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,':*')) "/>
1619 A list of namespaces used in element/attribute names in an XML fragment
1621 @author Priscilla Walmsley, Datypic
1623 @see http://www.xsltfunctions.com/xsl/functx_namespaces-in-use.html
1624 @param $root the root node to start from
1626 <xsl:function name="functx:namespaces-in-use" as="xs:anyURI*" xmlns:functx="http://www.functx.com">
1627 <xsl:param name="root" as="node()?"/>
1629 <xsl:sequence select=" distinct-values( $root/descendant-or-self::*/(.|@*)/namespace-uri(.)) "/>
1637 @author Priscilla Walmsley, Datypic
1639 @see http://www.xsltfunctions.com/xsl/functx_next-day.html
1640 @param $date the date
1642 <xsl:function name="functx:next-day" as="xs:date?" xmlns:functx="http://www.functx.com">
1643 <xsl:param name="date" as="xs:anyAtomicType?"/>
1645 <xsl:sequence select=" xs:date($date) + xs:dayTimeDuration('P1D') "/>
1651 The XML node kind (element, attribute, text, etc.)
1653 @author Priscilla Walmsley, Datypic
1655 @see http://www.xsltfunctions.com/xsl/functx_node-kind.html
1656 @param $nodes the node(s) whose kind you want to determine
1658 <xsl:function name="functx:node-kind" as="xs:string*" xmlns:functx="http://www.functx.com">
1659 <xsl:param name="nodes" as="node()*"/>
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' "/>
1667 Returns any values that appear more than once in a sequence
1669 @author Priscilla Walmsley, Datypic
1671 @see http://www.xsltfunctions.com/xsl/functx_non-distinct-values.html
1672 @param $seq the sequence of values
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*"/>
1677 <xsl:sequence select=" for $val in distinct-values($seq) return $val[count($seq[. = $val]) > 1] "/>
1683 The number of regions that match a pattern
1685 @author Priscilla Walmsley, Datypic
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
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"/>
1695 <xsl:sequence select=" count(tokenize($arg,$pattern)) - 1 "/>
1701 Resolves a relative URI and references it, returning an XML document
1703 @author Priscilla Walmsley, Datypic
1705 @see http://www.xsltfunctions.com/xsl/functx_open-ref-document.html
1706 @param $refNode a node whose value is a relative URI reference
1708 <xsl:function name="functx:open-ref-document" as="document-node()" xmlns:functx="http://www.functx.com">
1709 <xsl:param name="refNode" as="node()"/>
1711 <xsl:sequence select=" if (base-uri($refNode)) then doc(resolve-uri($refNode, base-uri($refNode))) else doc(resolve-uri($refNode)) "/>
1717 Reformats a number as an ordinal number, e.g. 1st, 2nd, 3rd.
1719 @author Priscilla Walmsley, Datypic
1721 @see http://www.xsltfunctions.com/xsl/functx_ordinal-number-en.html
1722 @param $num the number
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?"/>
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 '') "/>
1733 Pads an integer to a desired length by adding leading zeros
1735 @author Priscilla Walmsley, Datypic
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
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"/>
1745 <xsl:sequence select=" if ($length < string-length(string($integerToPad))) then error(xs:QName('functx:Integer_Longer_Than_Length')) else concat (functx:repeat-string( '0',$length - string-length(string($integerToPad))), string($integerToPad)) "/>
1751 Pads a string to a desired length
1753 @author Priscilla Walmsley, Datypic
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
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"/>
1765 <xsl:sequence select=" substring( string-join ( ($stringToPad, for $i in (1 to $length) return $padChar) ,'') ,1,$length) "/>
1771 A unique path to an XML node (or sequence of nodes)
1773 @author Priscilla Walmsley, Datypic
1775 @see http://www.xsltfunctions.com/xsl/functx_path-to-node-with-pos.html
1776 @param $node the node sequence
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()?"/>
1781 <xsl:variable name="names" as="xs:string*">
1782 <xsl:for-each select="$node/ancestor-or-self::*">
1783 <xsl:variable name="ancestor" select="."/>
1784 <xsl:variable name="sibsOfSameName" select="$ancestor/../*[name() = name($ancestor)]"/>
1785 <xsl:sequence select="concat(name($ancestor), if (count($sibsOfSameName) <= 1) then '' else concat( '[',functx:index-of-node($sibsOfSameName,$ancestor),']'))"/>
1788 <xsl:sequence select="string-join($names,'/')"/>
1794 A path to an XML node (or sequence of nodes)
1796 @author Priscilla Walmsley, Datypic
1798 @see http://www.xsltfunctions.com/xsl/functx_path-to-node.html
1799 @param $nodes the node sequence
1801 <xsl:function name="functx:path-to-node" as="xs:string*" xmlns:functx="http://www.functx.com">
1802 <xsl:param name="nodes" as="node()*"/>
1804 <xsl:sequence select=" $nodes/string-join(ancestor-or-self::*/name(.), '/') "/>
1810 Whether an XML node precedes another without being its ancestor
1812 @author W3C XML Query Working Group
1814 @see http://www.xsltfunctions.com/xsl/functx_precedes-not-ancestor.html
1815 @param $a the first node
1816 @param $b the second node
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()?"/>
1822 <xsl:sequence select=" $a << $b and empty($a intersect $b/ancestor::node()) "/>
1830 @author Priscilla Walmsley, Datypic
1832 @see http://www.xsltfunctions.com/xsl/functx_previous-day.html
1833 @param $date the date
1835 <xsl:function name="functx:previous-day" as="xs:date?" xmlns:functx="http://www.functx.com">
1836 <xsl:param name="date" as="xs:anyAtomicType?"/>
1838 <xsl:sequence select=" xs:date($date) - xs:dayTimeDuration('P1D') "/>
1844 Removes attributes from an XML fragment, based on name
1846 @author Priscilla Walmsley, Datypic
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
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*"/>
1856 <xsl:for-each select="$nodes">
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))"/>
1863 <xsl:when test=". instance of document-node()">
1865 <xsl:sequence select=" functx:remove-attributes-deep(node(), $names)"/>
1869 <xsl:sequence select="."/>
1878 Removes attributes from an XML element, based on name
1880 @author Priscilla Walmsley, Datypic
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
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*"/>
1890 <xsl:for-each select="$elements">
1891 <xsl:element name="{node-name(.)}">
1892 <xsl:sequence select="(@*[not(functx:name-test(name(),$names))], node())"/>
1900 Removes descendant elements from an XML node, based on name
1902 @author Priscilla Walmsley, Datypic
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
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*"/>
1912 <xsl:for-each select="$nodes">
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)"/>
1921 <xsl:when test=". instance of document-node()">
1923 <xsl:sequence select=" functx:remove-elements-deep(node(), $names)"/>
1927 <xsl:sequence select="."/>
1936 Removes descendant XML elements but keeps their content
1938 @author Priscilla Walmsley, Datypic
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
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*"/>
1948 <xsl:for-each select="$nodes">
1950 <xsl:when test=". instance of element()">
1952 <xsl:when test="functx:name-test(name(),$names)">
1953 <xsl:sequence select=" functx:remove-elements-not-contents(node(), $names)"/>
1956 <xsl:element name="{node-name(.)}">
1957 <xsl:sequence select="@*, functx:remove-elements-not-contents(node(),$names)"/>
1962 <xsl:when test=". instance of document-node()">
1964 <xsl:sequence select=" functx:remove-elements-not-contents(node(), $names)"/>
1968 <xsl:sequence select="."/>
1977 Removes child elements from an XML node, based on name
1979 @author Priscilla Walmsley, Datypic
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
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*"/>
1989 <xsl:for-each select="$elements">
1990 <xsl:element name="{node-name(.)}">
1991 <xsl:sequence select="(@*, node()[not(functx:name-test(name(),$names))])"/>
1999 Repeats a string a given number of times
2001 @author Priscilla Walmsley, Datypic
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
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"/>
2011 <xsl:sequence select=" string-join((for $i in 1 to $count return $stringToRepeat), '') "/>
2017 Replaces the beginning of a string, up to a matched pattern
2019 @author Priscilla Walmsley, Datypic
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
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"/>
2031 <xsl:sequence select=" replace($arg, concat('^.*?', $pattern), $replacement) "/>
2037 Updates the content of one or more elements
2039 @author Priscilla Walmsley, Datypic
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
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*"/>
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]"/>
2060 Replaces the first match of a pattern
2062 @author Priscilla Walmsley, Datypic
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
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"/>
2074 <xsl:sequence select=" replace($arg, concat('(^.*?)', $pattern), concat('$1',$replacement)) "/>
2080 Performs multiple replacements, using pairs of replace parameters
2082 @author Priscilla Walmsley, Datypic
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
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*"/>
2094 <xsl:sequence select=" if (count($changeFrom) > 0) then functx:replace-multi( replace($arg, $changeFrom[1], functx:if-absent($changeTo[1],'')), $changeFrom[position() > 1], $changeTo[position() > 1]) else $arg "/>
2100 Reverses the order of characters
2102 @author Priscilla Walmsley, Datypic
2104 @see http://www.xsltfunctions.com/xsl/functx_reverse-string.html
2105 @param $arg the string to reverse
2107 <xsl:function name="functx:reverse-string" as="xs:string" xmlns:functx="http://www.functx.com">
2108 <xsl:param name="arg" as="xs:string?"/>
2110 <xsl:sequence select=" codepoints-to-string(reverse(string-to-codepoints($arg))) "/>
2116 Trims trailing whitespace
2118 @author Priscilla Walmsley, Datypic
2120 @see http://www.xsltfunctions.com/xsl/functx_right-trim.html
2121 @param $arg the string to trim
2123 <xsl:function name="functx:right-trim" as="xs:string" xmlns:functx="http://www.functx.com">
2124 <xsl:param name="arg" as="xs:string?"/>
2126 <xsl:sequence select=" replace($arg,'\s+$','') "/>
2132 Returns the scheme from a URI
2134 @author Priscilla Walmsley, Datypic
2136 @see http://www.xsltfunctions.com/xsl/functx_scheme-from-uri.html
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?"/>
2142 <xsl:sequence select=" substring-before($uri,':') "/>
2148 Whether two sequences have the same XML node content and/or values
2150 @author Priscilla Walmsley, Datypic
2152 @see http://www.xsltfunctions.com/xsl/functx_sequence-deep-equal.html
2153 @param $seq1 the first sequence
2154 @param $seq2 the second sequence
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()*"/>
2160 <xsl:sequence select=" every $i in 1 to max((count($seq1),count($seq2))) satisfies deep-equal($seq1[$i],$seq2[$i]) "/>
2166 Whether two sequences contain the same XML nodes, regardless of order
2168 @author Priscilla Walmsley, Datypic
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
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()*"/>
2178 <xsl:sequence select=" not( ($seq1 except $seq2, $seq2 except $seq1)) "/>
2184 Whether two sequences contain the same XML nodes, in the same order
2186 @author Priscilla Walmsley, Datypic
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
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()*"/>
2196 <xsl:sequence select=" every $i in 1 to max((count($seq1),count($seq2))) satisfies $seq1[$i] is $seq2[$i] "/>
2202 The sequence type that represents a sequence of nodes or values
2204 @author Priscilla Walmsley, Datypic
2206 @see http://www.xsltfunctions.com/xsl/functx_sequence-type.html
2207 @param $items the items whose sequence type you want to determine
2209 <xsl:function name="functx:sequence-type" as="xs:string" xmlns:functx="http://www.functx.com">
2210 <xsl:param name="items" as="item()*"/>
2212 <xsl:sequence select=" concat( if (empty($items)) then 'empty-sequence()' else if (every $val in $items satisfies $val instance of xs:anyAtomicType) then if (count(distinct-values(functx:atomic-type($items))) > 1) then 'xs:anyAtomicType' else functx:atomic-type($items[1]) else if (some $val in $items satisfies $val instance of xs:anyAtomicType) then 'item()' else if (count(distinct-values(functx:node-kind($items))) > 1) then 'node()' else concat(functx:node-kind($items[1]),'()') , if (count($items) > 1) then '+' else '') "/>
2218 The siblings of an XML element that have the same name
2220 @author Priscilla Walmsley, Datypic
2222 @see http://www.xsltfunctions.com/xsl/functx_siblings-same-name.html
2223 @param $element the node
2225 <xsl:function name="functx:siblings-same-name" as="element()*" xmlns:functx="http://www.functx.com">
2226 <xsl:param name="element" as="element()?"/>
2228 <xsl:sequence select=" $element/../*[node-name(.) = node-name($element)] except $element "/>
2234 The siblings of an XML node
2236 @author Priscilla Walmsley, Datypic
2238 @see http://www.xsltfunctions.com/xsl/functx_siblings.html
2239 @param $node the node
2241 <xsl:function name="functx:siblings" as="node()*" xmlns:functx="http://www.functx.com">
2242 <xsl:param name="node" as="node()?"/>
2244 <xsl:sequence select=" $node/../node() except $node "/>
2250 Sorts a sequence of numeric values or nodes
2252 @author Priscilla Walmsley, Datypic
2254 @see http://www.xsltfunctions.com/xsl/functx_sort-as-numeric.html
2255 @param $seq the sequence to sort
2257 <xsl:function name="functx:sort-as-numeric" as="item()*" xmlns:functx="http://www.functx.com">
2258 <xsl:param name="seq" as="item()*"/>
2260 <xsl:for-each select="$seq">
2261 <xsl:sort select="number(.)"/>
2262 <xsl:copy-of select="."/>
2269 Sorts a sequence of values or nodes regardless of capitalization
2271 @author Priscilla Walmsley, Datypic
2273 @see http://www.xsltfunctions.com/xsl/functx_sort-case-insensitive.html
2274 @param $seq the sequence to sort
2276 <xsl:function name="functx:sort-case-insensitive" as="item()*" xmlns:functx="http://www.functx.com">
2277 <xsl:param name="seq" as="item()*"/>
2279 <xsl:for-each select="$seq">
2280 <xsl:sort select="upper-case(string(.))"/>
2281 <xsl:copy-of select="."/>
2288 Sorts a sequence of nodes in document order
2290 @author Priscilla Walmsley, Datypic
2292 @see http://www.xsltfunctions.com/xsl/functx_sort-document-order.html
2293 @param $seq the sequence to sort
2295 <xsl:function name="functx:sort-document-order" as="node()*" xmlns:functx="http://www.functx.com">
2296 <xsl:param name="seq" as="node()*"/>
2298 <xsl:sequence select=" $seq/. "/>
2304 Sorts a sequence of values or nodes
2306 @author Priscilla Walmsley, Datypic
2308 @see http://www.xsltfunctions.com/xsl/functx_sort.html
2309 @param $seq the sequence to sort
2311 <xsl:function name="functx:sort" as="item()*" xmlns:functx="http://www.functx.com">
2312 <xsl:param name="seq" as="item()*"/>
2314 <xsl:for-each select="$seq">
2315 <xsl:sort select="."/>
2316 <xsl:copy-of select="."/>
2323 Performs substring-after, returning the entire string if it does not contain the delimiter
2325 @author Priscilla Walmsley, Datypic
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
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"/>
2335 <xsl:sequence select=" if (contains($arg,$delim)) then substring-after($arg,$delim) else $arg "/>
2341 The substring after the last text that matches a regex
2343 @author Priscilla Walmsley, Datypic
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
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"/>
2353 <xsl:sequence select=" replace($arg,concat('^.*',$regex),'') "/>
2359 The substring after the last occurrence of a delimiter
2361 @author Priscilla Walmsley, Datypic
2363 @see http://www.xsltfunctions.com/xsl/functx_substring-after-last.html
2364 @param $arg the string to substring
2365 @param $delim the delimiter
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"/>
2371 <xsl:sequence select=" replace ($arg,concat('^.*',functx:escape-for-regex($delim)),'') "/>
2377 The substring after the first text that matches a regex
2379 @author Priscilla Walmsley, Datypic
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
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"/>
2389 <xsl:sequence select=" replace($arg,concat('^.*?',$regex),'') "/>
2395 Performs substring-before, returning the entire string if it does not contain the delimiter
2397 @author Priscilla Walmsley, Datypic
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
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"/>
2407 <xsl:sequence select=" if (contains($arg,$delim)) then substring-before($arg,$delim) else $arg "/>
2413 The substring after the first text that matches a regex
2415 @author Priscilla Walmsley, Datypic
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
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"/>
2425 <xsl:sequence select=" replace($arg,concat('^(.*)',$regex,'.*'),'$1') "/>
2431 The substring before the last occurrence of a delimiter
2433 @author Priscilla Walmsley, Datypic
2435 @see http://www.xsltfunctions.com/xsl/functx_substring-before-last.html
2436 @param $arg the string to substring
2437 @param $delim the delimiter
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"/>
2443 <xsl:sequence select=" if (matches($arg, functx:escape-for-regex($delim))) then replace($arg, concat('^(.*)', functx:escape-for-regex($delim),'.*'), '$1') else '' "/>
2449 The substring before the last text that matches a regex
2451 @author Priscilla Walmsley, Datypic
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
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"/>
2461 <xsl:sequence select=" tokenize($arg,$regex)[1] "/>
2467 Construct a time from an hour, minute and second
2469 @author Priscilla Walmsley, Datypic
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
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"/>
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))) "/>
2487 Converts an xs:dayTimeDuration into a timezone like "-05:00" or "Z"
2489 @author Priscilla Walmsley, Datypic
2491 @see http://www.xsltfunctions.com/xsl/functx_timezone-from-duration.html
2492 @param $duration the duration
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"/>
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')) "/>
2503 The total number of days in a dayTimeDuration
2505 @author Priscilla Walmsley, Datypic
2507 @see http://www.xsltfunctions.com/xsl/functx_total-days-from-duration.html
2508 @param $duration the duration
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?"/>
2513 <xsl:sequence select=" $duration div xs:dayTimeDuration('P1D') "/>
2519 The total number of hours in a dayTimeDuration
2521 @author Priscilla Walmsley, Datypic
2523 @see http://www.xsltfunctions.com/xsl/functx_total-hours-from-duration.html
2524 @param $duration the duration
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?"/>
2529 <xsl:sequence select=" $duration div xs:dayTimeDuration('PT1H') "/>
2535 The total number of minutes in a dayTimeDuration
2537 @author Priscilla Walmsley, Datypic
2539 @see http://www.xsltfunctions.com/xsl/functx_total-minutes-from-duration.html
2540 @param $duration the duration
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?"/>
2545 <xsl:sequence select=" $duration div xs:dayTimeDuration('PT1M') "/>
2551 The total number of months in a yearMonthDuration
2553 @author Priscilla Walmsley, Datypic
2555 @see http://www.xsltfunctions.com/xsl/functx_total-months-from-duration.html
2556 @param $duration the duration
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?"/>
2561 <xsl:sequence select=" $duration div xs:yearMonthDuration('P1M') "/>
2567 The total number of seconds in a dayTimeDuration
2569 @author Priscilla Walmsley, Datypic
2571 @see http://www.xsltfunctions.com/xsl/functx_total-seconds-from-duration.html
2572 @param $duration the duration
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?"/>
2577 <xsl:sequence select=" $duration div xs:dayTimeDuration('PT1S') "/>
2583 The total number of years in a yearMonthDuration
2585 @author Priscilla Walmsley, Datypic
2587 @see http://www.xsltfunctions.com/xsl/functx_total-years-from-duration.html
2588 @param $duration the duration
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?"/>
2593 <xsl:sequence select=" $duration div xs:yearMonthDuration('P1Y') "/>
2599 Trims leading and trailing whitespace
2601 @author Priscilla Walmsley, Datypic
2603 @see http://www.xsltfunctions.com/xsl/functx_trim.html
2604 @param $arg the string to trim
2606 <xsl:function name="functx:trim" as="xs:string" xmlns:functx="http://www.functx.com">
2607 <xsl:param name="arg" as="xs:string?"/>
2609 <xsl:sequence select=" replace(replace($arg,'\s+$',''),'^\s+','') "/>
2615 Updates the attribute value of an XML element
2617 @author Priscilla Walmsley, Datypic
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
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*"/>
2629 <xsl:for-each select="$elements">
2630 <xsl:variable name="element" select="."/>
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]"/>
2638 <xsl:copy-of select="@*[not(node-name(.) = $attrNames)]|node()"/>
2646 The values in one sequence that aren't in another sequence
2648 @author W3C XML Query Working Group
2650 @see http://www.xsltfunctions.com/xsl/functx_value-except.html
2651 @param $arg1 the first sequence
2652 @param $arg2 the second sequence
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*"/>
2658 <xsl:sequence select=" distinct-values($arg1[not(.=$arg2)]) "/>
2664 The intersection of two sequences of values
2666 @author W3C XML Query Working Group
2668 @see http://www.xsltfunctions.com/xsl/functx_value-intersect.html
2669 @param $arg1 the first sequence
2670 @param $arg2 the second sequence
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*"/>
2676 <xsl:sequence select=" distinct-values($arg1[.=$arg2]) "/>
2682 The union of two sequences of values
2684 @author W3C XML Query Working Group
2686 @see http://www.xsltfunctions.com/xsl/functx_value-union.html
2687 @param $arg1 the first sequence
2688 @param $arg2 the second sequence
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*"/>
2694 <xsl:sequence select=" distinct-values(($arg1, $arg2)) "/>
2702 @author Priscilla Walmsley, Datypic
2704 @see http://www.xsltfunctions.com/xsl/functx_word-count.html
2705 @param $arg the string to measure
2707 <xsl:function name="functx:word-count" as="xs:integer" xmlns:functx="http://www.functx.com">
2708 <xsl:param name="arg" as="xs:string?"/>
2710 <xsl:sequence select=" count(tokenize($arg, '\W+')[. != '']) "/>
2716 Turns a string of words into camelCase
2718 @author Priscilla Walmsley, Datypic
2720 @see http://www.xsltfunctions.com/xsl/functx_words-to-camel-case.html
2721 @param $arg the string to modify
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?"/>
2726 <xsl:sequence select=" string-join((tokenize($arg,'\s+')[1], for $word in tokenize($arg,'\s+')[position() > 1] return functx:capitalize-first($word)) ,'') "/>
2732 Wraps a sequence of atomic values in XML elements
2734 @author Priscilla Walmsley, Datypic
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
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"/>
2744 <xsl:for-each select="$values">
2745 <xsl:element name="{$elementName}" namespace="{namespace-uri-from-QName($elementName)}">
2746 <xsl:sequence select="."/>
2754 Construct a yearMonthDuration from a number of years and months
2756 @author Priscilla Walmsley, Datypic
2758 @see http://www.xsltfunctions.com/xsl/functx_yearmonthduration.html
2759 @param $years the number of years
2760 @param $months the number of months
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?"/>
2766 <xsl:sequence select=" (xs:yearMonthDuration('P1M') * functx:if-empty($months,0)) + (xs:yearMonthDuration('P1Y') * functx:if-empty($years,0)) "/>