FLWOR expression order is lost

Friday, 20 October 2017 · 4 messages
IB
Iwan Briquemont20 Oct 2017 18:20 #
Hello, I noticed that the order of my FLWOR expression is not kept when I do an xpath on the node list:
Quoted text · 1 line
> basex 'declare function local:nodes() {let $data := (<test a="2"/>, <test a="1"/>) let $nodes := trace(for $n in $data order by xs:integer($n/@a/data()) return $n) return $nodes }; local:nodes()/@a/data()'
<test a="1"/> <test a="2"/> 2 1 I would expect it to return it in order. Is it a bug or or some optimization allowed by XQuery? I tried it on the latest snapshot (BaseX90-20171020.102055.zip). Best regards, Iwan
CG
Christian Grün20 Oct 2017 19:02 #
Hi Iwan, The nodes of a path expression will always be returned in document order. See the following query as example:
  let $xml := <xml><a>2</a><a>1</a></xml>
  return (
    '[A]', sort($xml/a),
    '[B]', sort($xml/a) / self::node()
  )
The result in BaseX is:
  [A]
  <a>1</a>
  <a>2</a>
  [B]
  <a>2</a>
  <a>1</a>
While the results of the first sort function will be in the order you would expect, the nodes of the second result were reordered. The order of nodes that occur in distinct XML tree (such as in your example) is implementation-defined, so it could happen that another query processor returns "1" before "2". However, the reason would not be that your sorting was preserved. Instead, it would reflect another internal ordering of the elements that you assigned to $data. More information on the document order can be found in the spec [1]. You can use the map operator to get rid of the implicit reordering step. In addition, it will be more efficient:
  local:nodes() ! @a ! data()
Quoted text · Iwan Briquemont · 24 lines
> I noticed that the order of my FLWOR expression is not kept when I do an > xpath on the node list: > >> basex 'declare function local:nodes() {let $data := (<test a="2"/>, <test >> a="1"/>) let $nodes := trace(for $n in $data order by >> xs:integer($n/@a/data()) return $n) return $nodes }; >> local:nodes()/@a/data()' > > <test a="1"/> > > <test a="2"/> > > 2 > > 1 > > > I would expect it to return it in order. > Is it a bug or or some optimization allowed by XQuery? > > I tried it on the latest snapshot (BaseX90-20171020.102055.zip). > > Best regards, > Iwan
IB
Iwan Briquemont20 Oct 2017 19:45 #
Thank you ! So I should not rely on the order of a sequence (of XML trees) if I do a path expression on it? A bit confusing but I'll take that into account now. Regards, Iwan
Quoted text · Christian Grün · 69 lines
Le vendredi 20 octobre 2017 à 19:02 +0200, Christian Grün a écrit : > Hi Iwan, > > The nodes of a path expression will always be returned in document > order. See the following query as example: > > let $xml := <xml><a>2</a><a>1</a></xml> > return ( > '[A]', sort($xml/a), > '[B]', sort($xml/a) / self::node() > ) > > The result in BaseX is: > > [A] > <a>1</a> > <a>2</a> > [B] > <a>2</a> > <a>1</a> > > While the results of the first sort function will be in the order you > would expect, the nodes of the second result were reordered. > > The order of nodes that occur in distinct XML tree (such as in your > example) is implementation-defined, so it could happen that another > query processor returns "1" before "2". However, the reason would not > be that your sorting was preserved. Instead, it would reflect another > internal ordering of the elements that you assigned to $data. More > information on the document order can be found in the spec [1]. > > You can use the map operator to get rid of the implicit reordering > step. In addition, it will be more efficient: > > local:nodes() ! @a ! data() > > Hope this helps, > Christian > > [1] https://www.w3.org/TR/xquery-31/#id-document-order > > > > > I noticed that the order of my FLWOR expression is not kept when I > > do an > > xpath on the node list: > > > > > basex 'declare function local:nodes() {let $data := (<test > > > a="2"/>, <test > > > a="1"/>) let $nodes := trace(for $n in $data order by > > > xs:integer($n/@a/data()) return $n) return $nodes }; > > > local:nodes()/@a/data()' > > > > <test a="1"/> > > > > <test a="2"/> > > > > 2 > > > > 1 > > > > > > I would expect it to return it in order. > > Is it a bug or or some optimization allowed by XQuery? > > > > I tried it on the latest snapshot (BaseX90-20171020.102055.zip). > > > > Best regards, > > Iwan
CG
Christian Grünin reply to Christian Grün, 20 Oct 2017, 19:0220 Oct 2017 19:59 #
Quoted text · Christian Grün · 2 lines
> So I should not rely on the order of a sequence (of XML trees) if I do > a path expression on it?
The simple map operator (!) is always the best choice if you want to preserve the node order. It would have been more consistent to first define a basic map operator in the language, and extend it with distinct document order semantics later on. I assume that hardly anyone sensed 18 years ago (when XPath 1.0 was finalized) that XPath and XQuery would be used for much more complex things than navigating through single XML documents...
Quoted text · Christian Grün · 69 lines
> Le vendredi 20 octobre 2017 à 19:02 +0200, Christian Grün a écrit : >> Hi Iwan, >> >> The nodes of a path expression will always be returned in document >> order. See the following query as example: >> >> let $xml := <xml><a>2</a><a>1</a></xml> >> return ( >> '[A]', sort($xml/a), >> '[B]', sort($xml/a) / self::node() >> ) >> >> The result in BaseX is: >> >> [A] >> <a>1</a> >> <a>2</a> >> [B] >> <a>2</a> >> <a>1</a> >> >> While the results of the first sort function will be in the order you >> would expect, the nodes of the second result were reordered. >> >> The order of nodes that occur in distinct XML tree (such as in your >> example) is implementation-defined, so it could happen that another >> query processor returns "1" before "2". However, the reason would not >> be that your sorting was preserved. Instead, it would reflect another >> internal ordering of the elements that you assigned to $data. More >> information on the document order can be found in the spec [1]. >> >> You can use the map operator to get rid of the implicit reordering >> step. In addition, it will be more efficient: >> >> local:nodes() ! @a ! data() >> >> Hope this helps, >> Christian >> >> [1] https://www.w3.org/TR/xquery-31/#id-document-order >> >> >> >> > I noticed that the order of my FLWOR expression is not kept when I >> > do an >> > xpath on the node list: >> > >> > > basex 'declare function local:nodes() {let $data := (<test >> > > a="2"/>, <test >> > > a="1"/>) let $nodes := trace(for $n in $data order by >> > > xs:integer($n/@a/data()) return $n) return $nodes }; >> > > local:nodes()/@a/data()' >> > >> > <test a="1"/> >> > >> > <test a="2"/> >> > >> > 2 >> > >> > 1 >> > >> > >> > I would expect it to return it in order. >> > Is it a bug or or some optimization allowed by XQuery? >> > >> > I tried it on the latest snapshot (BaseX90-20171020.102055.zip). >> > >> > Best regards, >> > Iwan

⚡Generated with XQuery