Counterintuitive behavior with cast to double

Tuesday, 23 May 2023 · 3 messages
SL
Shuxin Li23 May 2023 11:35 #

Hi,

I'm Shuxin. Recently I came across this test case in which BaseX returned counterintuitive result. From my feelings it seems like a bug but the behavior of Saxon is similar, and therefore is hard for me to confirm. Give XML document

<P1 id="1"><A1 id="2">1</A1><A1 id="3">1</A1>1</P1>

and XPath query

//*[boolean(.) cast as xs:double]

Both Saxon and BaseX return the result node set [1, 2]. However, the nodes with id 2 and 3 seems identical to me and is hard to understand why node 2 is selected while 3 is not. If node 2 is deleted from the XML document, result set [1,3] is returned. I'm interested in whether this is intended behavior which I might have limited knowledge of? If it is also of interest for you you may have a look. Thank you very much!

Best Regards, Shuxin Li 2023.5.23

MH
Martin Honnen23 May 2023 11:45 #
Quoted text · Shuxin Li · 22 lines
On 5/23/2023 11:35 AM, Shuxin Li wrote: > Hi, > > I'm Shuxin. Recently I came across this test case in which BaseX > returned counterintuitive result. From my feelings it seems like a bug > but the behavior of Saxon is similar, and therefore is hard for me to > confirm. > Give XML document > > <P1 id="1"><A1 id="2">1</A1><A1 id="3">1</A1>1</P1> > > and XPath query > > //*[boolean(.) cast as xs:double] > > Both Saxon and BaseX return the result node set [1, 2]. However, the > nodes with id 2 and 3 seems identical to me and is hard to understand > why node 2 is selected while 3 is not. If node 2 is deleted from the > XML document, result set [1,3] is returned. I'm interested in whether > this is intended behavior which I might have limited knowledge of? If > it is also of interest for you you may have a look. Thank you very much! >

boolean(.) in a predicate of a node will always be true, so what you have is

//*[true() cast as xs:double]

which is

//*[1]

which is

/descendant-or-self::node()/*[1]

and that holds for the outer P element being the first child of the document node and for the A1 id="2" element being the first child of the P element.

If you remove the first A1, then the previously second child is now the first child *[1] of the P and therefore selected as well.

So in my view the result of Saxon and BaseX is fine.

CG
Christian Grünin reply to Shuxin Li, 23 May 2023, 11:3523 May 2023 11:50 #

Dear Shuxin,

Quoted text · Shuxin Li · 1 line
> Both Saxon and BaseX return the result node set [1, 2]. However, the nodes with id 2 and 3 seems identical to me and is hard to understand why node 2 is selected while 3 is not. If node 2 is deleted from the XML document, result set [1,3] is returned. I'm interested in whether this is intended behavior which I might have limited knowledge of? If it is also of interest for you you may have a look. Thank you very much!

The semantics here are tricky:

• boolean(.) gives you true() or false() • true() is returned for all 3 elements • xs:double(true()) returns 1, so your query is equivalent to //*[1] • ...[1] returns the first item of the input • //* returns the 3 elements P1, A1 (id="2") and A1 (id="3") • //* is a shortcut for /descendant-or-self::node()/child::* • /descendant-or-self::node() returns 7 results (1 document, 3 elements, 3 texts) • the document has 1 P1 child node; P1 has 2 A1 child nodes • //*[1] returns a) the P1 child node and b) the first A1 child node

…and Martin was faster with his response, as I just see ;)

If you want to get only the first result of all results, you can use parentheses: (//*[.....])[1]

Hope this helps, Christian


⚡Generated with XQuery