Reputation: 1791
I am very new to XQuery, and frankly find the learning curve incredibly steep.
I have an XML structure that looks something like this:
<root>
<product>
<size>500 units</size>
</product>
<product>
<size>1000 units</size>
</product>
<product>
<size>Unlimited units</size>
</product>
</root>
I need to write an XQuery statement that returns all nodes where the numerical value in size is less than say 1000. So I somehow need to determine this numerical value (ignoring any text) to perform an 'le' operation I assume.
On top of this, there is the possibility that the node will have no digits at all (e.g. 'Unlimited units'), in which case it needs to be treated as having a value of say 1000000.
Is there some way to do this? I've tried various combinations of fn:replace(blah, '\D', '') and casting to xs:int, but I can't seem to get it to work.
Any guidance would be greatly appreciated.
Upvotes: 4
Views: 10872
Reputation: 515
A bit of repetition for the sake of clarity
/root/product[not(substring-before(size," ") castable as xs:integer) or xs:integer(substring-before(size," ")) < 1000]
A bit of repetition for the sake of clarity
Upvotes: 0
Reputation: 243529
Use this XPath 1.0 expression:
/root/product[not(number(substring-before(size, ' ')) >= 1000)]
As we all know well, XPath is a subset of XQuery, so the above is also an XQuery expression.
Upvotes: 4
Reputation:
This XQuery:
for $vProduct in /root/product
let $vUnits := number(substring-before($vProduct/size,'units'))
let $vSize := if ($vUnits)
then $vUnits
else 1000000
where $vSize le 1000
return $vProduct
Output:
<product>
<size>500 units</size>
</product>
<product>
<size>1000 units</size>
</product>
Upvotes: 2
Reputation: 18864
Probably you should use the fn:tokenize(subject, pattern, flags)
(here is an description of the tokenize) function to extract your int values. The tokenize
function will return an array with your int values in the first position of the array. You can then do whatever you want with your int values.
To distinguish between the cases where the units are given and the "Unlimited units" case, you could do a regexp fn:match
with "Unlimited units" or simply compare the string before tokenizing. If the string is "Unlimited units" you'd treat is ar necessary and in the other case you tokenize the string to extract the int value.
Upvotes: 0