This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 29743 - XPath 3.1 maps recursive descent
Summary: XPath 3.1 maps recursive descent
Status: RESOLVED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XPath 3.1 (show other bugs)
Version: Working drafts
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Jonathan Robie
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-07-20 05:07 UTC by Jorge L Williams
Modified: 2016-09-23 08:43 UTC (History)
2 users (show)

See Also:


Attachments

Description Jorge L Williams 2016-07-20 05:07:06 UTC
We use JSONPath (http://goessner.net/articles/JsonPath/) along side of XPath, when working with JSON data.  Now that XPath supports maps and JSON, I've started evaluating  whether it may be worth consolidating around XPath exclusively.  This would certainly make our lives easier especially as JSONPath implementations vary wildly.

One feature that appears to be missing, but which is used quite often by our lazy developers is recursive decent ( .. in JSONPath).

Notice the examples here: http://goessner.net/articles/JsonPath/  it's a bit of a challenge to replicate them with XPath 3.1.

I've created a function in XQuery which I believe captures what JSONPath is doing and it looks like this:

declare function r:d($m as item()) as item()* {
  let $funs := $m?*[. instance of map(*) or . instance of array(*)]
  let $mps := $funs[. instance of map(*)]
  return  ($mps, $funs ! r:d(.))
};

Given that I can replicate all of the examples :

| Description                        | JSONPath                | XPath 3.1                           |
|------------------------------------+-------------------------+-------------------------------------|
| All of the authors of a book       | $.store.book[*].author  | $_?store?book?*?author              |
| All authors                        | $..author               | r:d($_)?author                      |
| All things in the store            | $.store.*               | $_?store?*                          |
| The price of everything in a store | $.store..price          | r:d($_?store)?price                 |
| The third book                     | $..book[ 2 ]            | r:d($_)?book?3                      |
| The last book in order             | $..book[(@.length-1)]   | r:d($_)?book?*[position() = last()] |
|                                    | $..book[-1:]            |                                     |
| The first two books                | $..book[0,1]            | r:d($_)?book?(1, 2)                 |
|                                    | $..book[:2]             | r:d($_)?book?(1 to 2)               |
| Filter all books with isbn number  | $..book[?(@.isbn)]      | r:d($_)?book?*[?isbn]               |
| Filtar all books cheaper than 10   | $..book[?(@.price< 10)] | r:d($_)?book?*[?price < 10]         |
| All members of JSON structure      | $..*                    | r:d($_)                             |

Defining a function to do this doesn't seem right though. I must be missing something...or there is a gap.

Thanks.
Comment 1 Michael Kay 2016-09-06 19:28:13 UTC
Thank you for this usability feedback on the specification.

After some consideration, the working group decided that a good part of the requirement could be met with a new function 

map:find($input as item()*, $key as xs:anyAtomic) as array(*)

which searches $input recursively looking into contained maps at any depth to find an entry with key $key, and returning the associated values as members of the result array.

This clearly doesn't satisfy all these examples but we felt it had the right blend of simplicity and capability, given how close we are to finishing. New syntax at this stage was felt to be far too risky. 

The WG has approved an outline sketch of the specification and will move on to consider the final proposed specification.
Comment 2 Andrew Coleman 2016-09-23 08:43:09 UTC
The function map:find() is available to review in the editor's draft of the F&O spec:
https://www.w3.org/XML/Group/qtspecs/specifications/xpath-functions-31/html/#func-map-find

Marking this bug resolved/fixed.
Many thanks for raising this issue.