Skip to content

Commit

Permalink
Merge pull request #909 from ChristianGruen/893
Browse files Browse the repository at this point in the history
893 fn:compare: Support for arbitrary atomic types
  • Loading branch information
ndw authored Jan 9, 2024
2 parents c778bf5 + f33735e commit 2217b60
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 29 deletions.
178 changes: 164 additions & 14 deletions specifications/xpath-functions-40/src/function-catalog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3675,8 +3675,8 @@ return if (starts-with($preprocessed-value, "-")) then -$abs else +$abs]]></eg>
<fos:function name="compare" prefix="fn">
<fos:signatures>
<fos:proto name="compare" return-type="xs:integer?">
<fos:arg name="value1" type="xs:string?"/>
<fos:arg name="value2" type="xs:string?"/>
<fos:arg name="value1" type="xs:anyAtomicType?"/>
<fos:arg name="value2" type="xs:anyAtomicType?"/>
<fos:arg name="collation" type="xs:string?" default="fn:default-collation()"/>
</fos:proto>
</fos:signatures>
Expand All @@ -3691,22 +3691,133 @@ return if (starts-with($preprocessed-value, "-")) then -$abs else +$abs]]></eg>
<fos:property>focus-independent</fos:property>
</fos:properties>
<fos:summary>
<p>Returns <code>-1</code>, <code>0</code>, or <code>1</code>,
depending on whether <code>$value1</code> collates before,
equal to, or after <code>$value2</code> according to the rules of a selected
collation.</p>
<p>Returns <code>-1</code>, <code>0</code>, or <code>1</code>, depending on whether
the first value is less than, equal to, or greater than the second value.</p>
</fos:summary>
<fos:rules>
<p>Returns <code>-1</code>, <code>0</code>, or <code>1</code>,
depending on whether <code>$value1</code> is
respectively less than, equal to, or greater than <code>$value2</code>,
according to the rules of the collation that is used. </p>
<p>The collation used by this function is determined according to the rules in <specref
ref="choosing-a-collation"/>. </p>
<p>Compares two atomic values <code>$value1</code> and <code>$value2</code> for order, and
returns the integer value <code>-1</code>, <code>0</code>, or <code>1</code>,
depending on whether <code>$value1</code> is less than, equal to, or greater than
<code>$value2</code>, respectively.</p>
<p>If either <code>$value1</code> or <code>$value2</code> is the empty sequence,
the function returns the empty sequence.</p>
<p>This function, <phrase diff="chg" at="2023-01-17">when used with the default collation,</phrase> defines the semantics of the <code>eq</code>, <code>ne</code>,
<code>gt</code>, <code>lt</code>, <code>le</code> and <code>ge</code> operators on <code>xs:string</code> values.</p>
<p>Otherwise, the result is determined as follows:</p>
<olist>
<item>
<p>If <code>$value1</code> is an instance of <code>xs:string</code>,
<code>xs:anyURI</code> or <code>xs:untypedAtomic</code>, and if
<code>$value2</code> is an instance of <code>xs:string</code>, <code>xs:anyURI</code>
or <code>xs:untypedAtomic</code>, the values are compared as strings, and the
result reflects the order according to the rules of the collation that is used.</p>
<p>The collation is determined according to the rules in
<specref ref="choosing-a-collation"/>.</p>
<p><phrase diff="chg" at="2023-01-17">When used with the default collation,</phrase>
the function defines the semantics of the <code>eq</code>, <code>ne</code>,
<code>gt</code>, <code>lt</code>, <code>le</code> and <code>ge</code>
operators on <code>xs:string</code> values.</p>
</item>
<item>
<p>If both <code>$value1</code> and <code>$value2</code> are instances of
<code>xs:numeric</code>, the result of
<code>fn:numeric-compare($value1, $value2)</code> is returned.</p>
</item>
<item>
<p>If both <code>$value1</code> and <code>$value2</code> are instances of
<code>xs:boolean</code>, then:</p>
<olist>
<item><p><code>-1</code> is returned if
<code>op:boolean-less-than($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>0</code> is returned if
<code>op:boolean-equal($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>1</code> is returned otherwise.</p></item>
</olist>
</item>
<item>
<p>If <code>$value1</code> is an instance of <code>xs:hexBinary</code> or
<code>xs:base64Binary</code>, and if <code>$value2</code> is an instance of
<code>xs:hexBinary</code> or <code>xs:base64Binary</code>, then:</p>
<olist>
<item><p><code>-1</code> is returned if
<code>op:binary-less-than($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>0</code> is returned if
<code>op:binary-equal($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>1</code> is returned otherwise.</p></item>
</olist>
</item>
<item>
<p>If both <code>$value1</code> and <code>$value2</code> are instances of
<code>xs:date</code>, then:</p>
<olist>
<item><p><code>-1</code> is returned if
<code>op:date-less-than($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>0</code> is returned if
<code>op:date-equal($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>1</code> is returned otherwise.</p></item>
</olist>
</item>
<item>
<p>If both <code>$value1</code> and <code>$value2</code> are instances of
<code>xs:time</code>, then:</p>
<olist>
<item><p><code>-1</code> is returned if
<code>op:time-less-than($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>0</code> is returned if
<code>op:time-equal($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>1</code> is returned otherwise.</p></item>
</olist>
</item>
<item>
<p>If both <code>$value1</code> and <code>$value2</code> are instances of
<code>xs:dateTime</code>, then:</p>
<olist>
<item><p><code>-1</code> is returned if
<code>op:dateTime-less-than($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>0</code> is returned if
<code>op:dateTime-equal($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>1</code> is returned otherwise.</p></item>
</olist>
</item>
<item>
<p>If both <code>$value1</code> and <code>$value2</code> are instances of
<code>xs:dayTimeDuration</code>, then:</p>
<olist>
<item><p><code>-1</code> is returned if
<code>op:dayTimeDuration-less-than($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>0</code> is returned if
<code>op:duration-equal($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>1</code> is returned otherwise.</p></item>
</olist>
</item>
<item>
<p>If both <code>$value1</code> and <code>$value2</code> are instances of
<code>xs:yearMonthDuration</code>, then:</p>
<olist>
<item><p><code>-1</code> is returned if
<code>op:yearMonthDuration-less-than($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>0</code> is returned if
<code>op:duration-equal($value1, $value2)</code> returns <code>true</code>.</p>
</item>
<item><p><code>1</code> is returned otherwise.</p></item>
</olist>
</item>
<item>
<p>For any other combination of types, a type error
<xerrorref spec="XP" class="TY" code="0004"/> is raised.</p>
</item>
</olist>
</fos:rules>
<fos:examples>
<fos:example>
Expand Down Expand Up @@ -3749,7 +3860,46 @@ return if (starts-with($preprocessed-value, "-")) then -$abs else +$abs]]></eg>
base characters, such as the final <quote>n</quote>. </fos:postamble>
</fos:test>
</fos:example>
<fos:example>
<fos:test>
<fos:expression>compare(9, 10)</fos:expression>
<fos:result>-1</fos:result>
</fos:test>
</fos:example>
<fos:example>
<fos:test>
<fos:expression>compare(123, 123.0)</fos:expression>
<fos:result>0</fos:result>
</fos:test>
</fos:example>
<fos:example>
<fos:test>
<fos:expression>compare(false(), true())</fos:expression>
<fos:result>-1</fos:result>
</fos:test>
</fos:example>
<fos:example>
<fos:test>
<fos:expression><![CDATA[compare('text', parse-xml('<xml>text</xml>'))]]></fos:expression>
<fos:result>0</fos:result>
</fos:test>
</fos:example>
<fos:example>
<fos:test>
<fos:expression>compare(xs:time('23:59:59'), xs:time('00:00:00'))</fos:expression>
<fos:result>1</fos:result>
</fos:test>
</fos:example>
<fos:example>
<fos:test>
<fos:expression>compare(xs:date('2001-01-01'), xs:date('2001-01-01'))</fos:expression>
<fos:result>0</fos:result>
</fos:test>
</fos:example>
</fos:examples>
<fos:history>
<fos:version version="4.0">Changed in 4.0: Enhanced to accept types other than strings.</fos:version>
</fos:history>
</fos:function>
<fos:function name="codepoint-equal" prefix="fn">
<fos:signatures>
Expand Down
32 changes: 17 additions & 15 deletions specifications/xpath-functions-40/src/xpath-functions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2705,9 +2705,6 @@ string conversion of the number as obtained above, and the appropriate <var>suff
may also cause an error if they cannot be resolved against the <phrase diff="chg" at="2023-05-19">relevant</phrase> base URI.</p></note>

</div3>
<div3 id="func-compare">
<head><?function fn:compare?></head>
</div3>
<div3 id="func-codepoint-equal">
<head><?function fn:codepoint-equal?></head>
</div3>
Expand Down Expand Up @@ -5450,15 +5447,12 @@ correctly in all browsers, depending on the system configuration.</emph></p>-->
<div3 id="func-atomic-equal">
<head><?function fn:atomic-equal?></head>
</div3>
<div3 id="func-starts-with-subsequence" diff="add" at="B">
<head><?function fn:starts-with-subsequence?></head>
</div3>
<div3 id="func-ends-with-subsequence" diff="add" at="B">
<head><?function fn:ends-with-subsequence?></head>
</div3>
<div3 id="func-contains-subsequence" diff="add" at="B">
<head><?function fn:contains-subsequence?></head>
</div3>
<div3 id="func-deep-equal">
<head><?function fn:deep-equal?></head>
</div3>
<div3 id="func-compare">
<head><?function fn:compare?></head>
</div3>
<div3 id="func-distinct-values">
<head><?function fn:distinct-values?></head>
</div3>
Expand All @@ -5468,9 +5462,15 @@ correctly in all browsers, depending on the system configuration.</emph></p>-->
<div3 id="func-index-of">
<head><?function fn:index-of?></head>
</div3>
<div3 id="func-deep-equal">
<head><?function fn:deep-equal?></head>
</div3>
<div3 id="func-starts-with-subsequence" diff="add" at="B">
<head><?function fn:starts-with-subsequence?></head>
</div3>
<div3 id="func-ends-with-subsequence" diff="add" at="B">
<head><?function fn:ends-with-subsequence?></head>
</div3>
<div3 id="func-contains-subsequence" diff="add" at="B">
<head><?function fn:contains-subsequence?></head>
</div3>
</div2>
<div2 id="cardinality-functions">
<head>Functions that test the cardinality of sequences</head>
Expand Down Expand Up @@ -11985,6 +11985,8 @@ declare function eg:distinct-nodes-stable ($arg as node()*) as node()* {
argument syntax in function calls.</p></item>
<item><p>The <code>fn:deep-equal</code> function has an <code>options</code> argument
giving detailed control over how two values are compared.</p></item>
<item><p>The <code>fn:compare</code> function has been enhanced to accept types
other than strings.</p></item>
<item><p>The <code>fn:format-integer</code> function can produce output in non-decimal
radices, for example binary and hexadecimal.</p></item>
<item><p>The <code>fn:json-doc</code> function accepts additional options.</p></item>
Expand Down

0 comments on commit 2217b60

Please sign in to comment.