Integers as attribute values

Tuesday, 26 April 2022 · 5 messages · last reply 27 Apr 2022
GC
Giuseppe G. A. Celano26 Apr 2022 19:07 #
Hi Everyone, I have an xml document with elements such as <div n=“21”>. If I run the query doc(“file.xml")//div[@subtype="chapter"]//*/parent::div[@n=21], I get the relevant div element, even if 21 is passed as an integer. On the other hand, if I type doc(“file.xmll")//div[@n=21], I get the error "Cannot convert to xs:double”, which can be solved by writing doc(“myfile.xmll")//div[@n=“21”]. Is this due to the fact that BaseX tries to convert the values of @n of all div elements into a number and, if it happens that the @n values returned are all numbers, then an error is not raised (the comparison is then possible), otherwise it is? Is this BaseX specific? Thanks. Best, Giuseppe
CG
Christian Grün26 Apr 2022 19:54 #
Hi Giuseppe,
Quoted text · Giuseppe G. A. Celano · 5 lines
Is this due to the fact that BaseX tries to convert the values of @n of all > div elements into a number and, if it happens that the @n values returned > are all numbers, then an error is not raised (the comparison is then > possible), otherwise it is? Is this BaseX specific? Thanks. >
Exactly; that’s standard XQuery. You can use an additional predicate to restrict the comparisons to valid integers:
<xml>
  <div n='a'/>
  <div n='21'/> <!-- result -->
  <div n='  21   '/> <!-- result -->
</xml>//div[@n[. castable as xs:integer][. = 21]]
Using string comparisons is usually the easier way, and it’s better supported by our index structures. However, if your numeric data is irregular and has additional whitespaces (such as in the third <div> element in my example), string comparisons may be too strict. A side note: I was surprised to see that Saxon EE 10 raises an exception for my example query. It seems that the predicates are swapped, and the comparison is evaluated before the cast check. Maybe the behavior has been adapted in a more recent version. – A workaround is to use the and expression:
<x>a</x>[. castable as xs:integer and . = 21]
In BaseX, a predicate with an and expression will automatically be rewritten to multiple predicates, as simple predicates can be further optimized more easily, and predicates will always be evaluated in the order they are written down. Ciao, Christian
LQ
Liam R. E. Quin26 Apr 2022 22:44 #
Quoted text · Christian Grün · 12 lines
On Tue, 2022-04-26 at 19:54 +0200, Christian Grün wrote: > > A side note: I was surprised to see that Saxon EE 10 raises an > exception for my example query. It seems that the predicates are > swapped, and > the > comparison is evaluated before the cast check. Maybe the behavior has > been > adapted in a more recent version. – A workaround is to use the and > expression: > > <x>a</x>[. castable as xs:integer and . = 21]
This is also not guaranteed. You can, however, write, [if (. castable as xs:integer) then (. = 21) else false() ] This one is guaranteed not to raise dynamic errors in the unused expression. Liam
-- Liam Quin, https://www.delightfulcomputing.com/ Available for XML/Document/Information Architecture/XSLT/ XSL/XQuery/Web/Text Processing/A11Y training, work & consulting. Barefoot Web-slave, antique illustrations: http://www.fromoldbooks.org
GC
Giuseppe G. A. Celanoin reply to Christian Grün, 26 Apr 2022, 19:5427 Apr 2022 00:39 #
Thank you, Christian, as always very useful!
Quoted text · Christian Grün · 37 lines
> On 26. Apr 2022, at 19:54, Christian Grün <christian.gruen at gmail.com> wrote: > > Hi Giuseppe, > > > > > > Is this due to the fact that BaseX tries to convert the values of @n of all div elements into a number and, if it happens that the @n values returned are all numbers, then an error is not raised (the comparison is then possible), otherwise it is? Is this BaseX specific? Thanks. > > > Exactly; that’s standard XQuery. You can use an additional predicate to restrict the comparisons to valid integers: > > > <xml> > <div n='a'/> > <div n='21'/> <!-- result --> > <div n=' 21 '/> <!-- result --> > </xml>//div[@n[. castable as xs:integer][. = 21]] > > > Using string comparisons is usually the easier way, and it’s better supported by our index structures. However, if your numeric data is irregular and has additional whitespaces (such as in the third <div> element in my example), string comparisons may be too strict. > > > > A side note: I was surprised to see that Saxon EE 10 raises an exception for my example query. It seems that the predicates are swapped, and the comparison is evaluated before the cast check. Maybe the behavior has been adapted in a more recent version. – A workaround is to use the and expression: > > > <x>a</x>[. castable as xs:integer and . = 21] > > > > In BaseX, a predicate with an and expression will automatically be rewritten to multiple predicates, as simple predicates can be further optimized more easily, and predicates will always be evaluated in the order they are written down. > > > > Ciao, > Christian
CG
Christian Grünin reply to Liam R. E. Quin, 26 Apr 2022, 22:4427 Apr 2022 13:37 #
Quoted text · Liam R. E. Quin · 5 lines
> > This is also not guaranteed. You can, however, write, > > [if (. castable as xs:integer) then (. = 21) else false() ] >
True; thanks, Liam. In BaseX, specifically, sequential evaluation is guaranteed for all three variants (if; and; multiple predicates).

⚡Generated with XQuery