A compare of two values seems very simple on the surface, but with standard XPath there are some potential challenges e.g. if null is compared with an empty string. Some recommendations are found here:
2.Test if a node is not blank.
An alternative is to use the ng:compare function.
The XPath extension ng:compare can compare two inputs as either text strings or numbers.
The format is ng:compare(left, right, operator, method)
The parameters of the ng:compare function are:
Left and right
These are the two arguments, that are to be compared. The allowed data types are string, number, empty sequence and sequence of either strings or numbers. When a sequence with more than one element is used as argument, then the first element in the sequence is used for the comparison.
Operator
This can be either =, !=, >, <, <= or >=. An incorrect value for this parameter will result in an exception.
Method
This paramete is optional and can be “text” or “numeric”, indicating the comparison method. The default value is “text”. An incorrect value for this parameter will result in an exception.
Comparison with the <, >, <= and >= operators is done lexicographically. The comparison is based on the Unicode value of each character in the strings, so comparisons between non-ASCII strings do not follow any locale-specific rules.
An empty sequence (such as an XPath expression referencing a non-existent node) is treated as empty string.
Examples of text compares are found below.
When compare method is "number"
Comparison with non-integer values (i.e. decimal numbers and infinity) follow the IEEE-754 standard for floating point arithmetic. One exception from this rule is the value “Not a Number” (NaN). In numeric comparisons NaN is treated as the value 0 (zero).
Note that if one argument is integer and the other is decimal, then the integer is converted to a double precision floating point number before the comparison. Integers greater than 2^53 are not all represented accurately when converted to double-precision floating point.
Also, the following rules apply:
If number compare and the input argument is a string value:
If it contains a dot ".", it will be parsed as a double precision floating point number.
If it does not contain a dot, it will be parsed as a 64-bit signed integer (limit is -/+ 9223372036854775808).
If number compare and parsing the string as a number fails, then the argument gets the value 0 (zero).
If the input argument is an empty or blank string (whitespace only), it will be treated as the numeric value zero.
If the input argument is an empty sequence (An XPath sequence that does not exist in the XML), it will be treated as the numeric value zero.
Left | Right | Operator | Result | Comment |
---|---|---|---|---|
“abc” | “abc” | = | true | |
“abc” | “bcd” | = | false | Differs from numeric comparison. |
“abc” | “bcd” | != | true | |
“abc” | “bcd” | < | true | |
“abc” | “bcd” | <= | true | |
“abc” | “bcd” | > | false | |
“abc” | “bcd” | >= | false | |
“123” | “124” | = | false | |
“123” | “124” | != | true | |
“123” | “124” | < | true | |
“123” | “124” | > | false | |
“69” | “124” | > | true | Differs from numeric comparison. |
xs:double("INF") | xs:double("INF") | = | true | |
xs:double("NaN") | xs:double("NaN") | = | true | |
xs:double("NaN") | xs:double("NaN") | != | false | |
Empty sequence | Empty sequence | = | true | |
Empty sequence | Empty sequence | != | false | |
Empty sequence | ““ | = | true | |
Empty sequence | ““ | != | false | |
““ | "0" | = | false | Differs from numeric comparison. |
Left | Right | Operator | Result | Comment |
---|---|---|---|---|
“abc” | “abc” | = | true | Because “abc” is parsed to 0 |
“abc” | “bcd” | = | false | Differs from text comparison. Because both “abc” and “bcd” are parsed to 0 |
“abc” | “bcd” | != | true | |
“abc” | “bcd” | < | true | |
“abc” | “bcd” | <= | true | |
“abc” | “bcd” | > | false | |
“abc” | “bcd” | >= | false | |
“123” | “124” | = | false | |
“123” | “124” | != | true | |
“123” | “124” | < | true | |
“123” | “124” | > | false | |
“69” | “124” | < | true | Differs from text comparison. |
xs:double("INF") | xs:double("INF") | = | true | |
xs:double("NaN") | xs:double("NaN") | = | true | Because NaN is parsed as 0 |
xs:double("NaN") | xs:double("NaN") | != | false | |
Empty sequence | Empty sequence | = | true | |
Empty sequence | Empty sequence | != | false | |
Empty sequence | ““ | = | true | |
Empty sequence | ““ | != | false | |
““ | "0" | = | true | Differs from text comparison. |