stackbacker
stackbacker

Reputation: 329

Xpath: Comparing Node Attributes of Decimal Type

I am trying to create an xpath expression for the following xml file (abbreviated obviously).

<estimate>
   <heights id="4.1">
     <year>1985</year>
   </heights>
   <heights id="4.2">
     <year>1986</year>
   </heights>
   <heights id="4.3">
     <year>1987</year>
   </heights>
   .
   .
   .
   <heights id="x.x">
     <year>XXXX</year>
   </heights>
</estimate>

The xpath expression I'm using is this:

/estimate/heights[@id>4.2]

So I'm basically looking for nodes with ids greater than 4.2 in this case. While this seems to work when I play with it, I'm concerned that I'm not actually comparing float to float or double-double. If I read the wikipedia entry for XPATH 2.0 correctly, it seems like it will cast the attribute to the appropriate type:

If no schema is in use, the node will be untyped, and the type of the resulting atomic value will be untypedAtomic. Typed atomic values are checked to ensure that they have an appropriate type for the context where they are used: for example, it is not possible to multiply a date by a number. Untyped atomic values, by contrast, follow a weak typing discipline: they are automatically converted to a type appropriate to the operation where they are used: for example with an arithmetic operation an untyped atomic value is converted to the type double.

I've done a lot of searching and haven't found anything definitive though (I'm not clear if the above quoted statements apply to my case.)

Upvotes: 1

Views: 1024

Answers (1)

Michael Kay
Michael Kay

Reputation: 163322

First, you really need to be clear whether this is XPath 1.0 or XPath 2.0 (or XPath 2.0 running in backwards compatibility mode). For this particular example the rules probably have much the same effect, but they are expressed very differently.

In XPath 1.0 you are comparing a node-set against a number (=double), and the result is true if any node in the node-set, after converting to a number (=double) is greater than 4.2. The result is false if the node-set is empty (i.e. if @id doesn't exist), or if the conversion produces NaN (i.e. if @id is not numeric).

In XPath 2.0, assuming the data is untyped (that is, it's not a schema-aware processor), you are comparing a sequence of nodes against an xs:decimal. The nodes are atomized, producing a sequence of xs:untypedAtomic values, and these are cast to xs:double for the purpose of the comparison (because the other operand is numeric). Again, if any value is greater than 4.2, the answer is true. The only effective difference from the XPath 1.0 rules is that if @id is not numeric, the cast fails and you get a dynamic error, whereas XPath 1.0 gave "false".

In XPath 2.0 with backwards compatibility enabled, the conversion to a double uses the number() function rather than casting, so non-numeric @id values are converted to NaN, and the result is false as it is in XPath 1.0.

Upvotes: 2

Related Questions