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 12951 - [XPath30] Simple mapping operator
Summary: [XPath30] Simple mapping operator
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XPath 3.0 (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: 2011-06-14 01:08 UTC by Evan Lenz
Modified: 2014-09-16 18:46 UTC (History)
4 users (show)

See Also:


Attachments

Description Evan Lenz 2011-06-14 01:08:07 UTC
Forgive my ignorance on whether or not this is already in the works, but I'd like to commend the addition of a "simple mapping operator" to XPath, exactly along the lines described here (whether "!" is chosen or something else): http://lists.w3.org/Archives/Public/public-qt-comments/2003Dec/0061.html

The "/" operator is powerful but limited. Here's a real-world example:

/html/head/script/@src/unparsed-text(
                         resolve-uri(
                           concat('..',.),
                           $invoked-module-uri
                         )
                       )

The nesting of parentheses is a pain to both read and write. JavaScript developers, among others, recognize this and that's largely why jQuery has grown so popular, with its simple chaining mechanism.

I'd much rather be able to type something like this:

/html/head/script/@src ! concat('..',.)
                       ! resolve-uri(.,$invoked-module-uri)
                       ! unparsed-text(.)

In the meantime, I can resort to a jQuery-like library approach (that requires 5 more characters) and trades performance for expressivity:

/html/head/script/@src/_:_(concat('..',.))
                      /_:_(resolve-uri(.,$invoked-module-uri))
                      /unparsed-text(.)

declare function _:_($items as item()*) {
  for $item in $items return <item>{$item}</item>
};

But it would obviously be much better to add a simple mapping operator to the language itself. See the above link for Michael Kay's simple description of the semantics. Basically, it would behave like "/" except not be limited to node sequences, and it would retain order and duplicate node references.
Comment 1 Evan Lenz 2011-06-14 06:03:00 UTC
One other thing that might go without saying but that wasn't explicit in Michael's original post: I'd expect the whole inner focus to change (just as with "/"), i.e. context item, context position, and context size.
Comment 2 Michael Kay 2011-06-14 07:42:06 UTC
Thanks for bringing this back to the WGs attention.

There's been a lot of work in the last few months trying to add a new data structure - maps - to the language, with associated functions, operators, and types. The current status is that this is accepted by the XSL WG (where it is needed for some streaming use cases, as well as being generally useful for other things), but there is some resistance to adding it to XQuery, either on principle or on timing grounds. Associated with this we found that many of the examples using maps would also benefit from the simple mapping operator, and this too is present in the current XSLT draft, though it has not yet been proposed to the joint WGs.

Historically, I think the simple mapping operator would have made it into XPath 2.0 if we had been able to agree on a suitable operator symbol. There seems to be some resistance to "!" perhaps because the languages that have used this symbol in a similar role are unfamiliar to most WG members (and probably to most of our users as well, in fairness). But no-one seems to have any better suggestions ("->" occasionally surfaces, but has the drawback that a space is needed before the hyphen). At a late stage before XPath 2.0 was released the requirement for a simple mapping operator was partly satisfied by overloading the semantics of "/" to allow atomic values on the RHS: an unfortunate compromise in my view, though it's better than nothing.

You mention jQuery's chaining mechanism. We've also looked at this in the XSL WG, for example allowing 

$uri -> substring-before('#') -> substring-after('http://')

Here, rather than the LHS setting the dynamic context for evaluation of the RHS, there's simply an alternative function call notation where a->f(x) replaces f(a,x). It's a different solution than the simple mapping operator but has some of the same benefits, in particular, avoiding the deeply-nested function calls and the right-to-left order of evaluation.
Comment 3 Evan Lenz 2011-06-15 20:02:23 UTC
Thanks, Michael, for the quick, detailed response.

I like the alternative function call syntax you gave, but I would hope it does not substitute for the simple mapping operator (allowing arbitrary expressions and not just function calls). In other words, it would be great to have both, but if I had to choose one, I'd go with the more general mapping operator (regardless of the chosen syntax). I would also hope and expect this operator to be a part of XQuery, not just XSLT, whether or not the map data type gets accepted into XQuery.

If syntax is the obstacle, you could remove the restrictions on "/" so that it behaves as a general mapping operator (if less simple).

I think this can be worked out in a backward-compatible, unsurprising way so that what currently (in XPath 2.0) returns an error (value sequences on LHS and heterogeneous node/value sequences anywhere) will in XPath 3.0 validly return a sequence.

I think this rule works: If the sequences returned by a RHS step contain no atomic values, then they are "unioned" (sorted into document order and duplicates are removed). Conversely, if any of the sequences returned by a RHS step include an atomic value, then the sequences are "concatenated" (sequence order is preserved and duplicates are not removed).

This actually simplifies the current rules listed here: http://www.w3.org/TR/xpath20/#id-path-expressions  #1 remains unchanged, #3 is deleted, and #2 is changed slightly to read something like this:

2. If any evaluation of E2 returns a sequence that includes an atomic value, these sequences are concatenated, in order, and returned.

Then remove err:XPTY0018 and err:XPTY0019.

For example, these expressions would now be legal (and well-defined):

/items/item/substring-before(.,' item')/upper-case(.)
(1 to 3)/concat('#',.)

And in my original post's example, you'd just replace "!" with "/".

The gotchas would then be unique to where the gotchas already are. (No new gotchas.)

E.g., the following expression would still return <foo> elements in implementation-defined order (document order).

$sorted-document-nodes/foo

But that gotcha already exists in XQuery 1.0/XSLT 2.0.

If I could summarize my request, it would be "Please remove what feel like arbitrary restrictions." (You could make an analogy with the abolishment of the result tree fragment in XSLT 1.0.) Unless there is some reason why this doesn't actually work, on balance I would prefer this to adding new syntax to the language.
Comment 4 Michael Kay 2011-06-15 23:01:01 UTC
One of the reasons we don't allow atomic values on the LHS of "/" is that people felt it was not acceptable that let $x := 10 return $x/2 should be legal and return 2. Though you get the same problem with @price/2 which is legal today and returns 2...

The other problem with overloading "/" is that there's also a need for simple mapping (without deduplication and sorting) with nodes on the RHS, for example //@href/doc(.)
Comment 5 Michael Rys 2011-06-16 17:43:53 UTC
Besides the use cases that Mike mentioned:

Having complex overloading semantics that have different fundamental behaviour for the same syntax is normally a very bad language design.

Michael
Comment 6 Evan Lenz 2011-06-16 18:51:17 UTC
Fair enough. So can we expect a simple mapping operator in XPath/XQuery 3.0? I don't really care what the syntax is, as long as it's concise and general (without restrictions).
Comment 7 Michael Kay 2011-07-27 21:59:48 UTC
The proposal to adopt "!" as a simple mapping operator, described in http://lists.w3.org/Archives/Member/w3c-xsl-query/2011Jul/0151.html (member-only) was accepted subject to changes in terminology: we will retain the production names AbsolutePathExpr and RelativePathExpr.
Comment 8 Michael Dyck 2011-07-27 22:15:32 UTC
(In reply to comment #7)
> we will retain the production names AbsolutePathExpr and RelativePathExpr.

(No such thing as "AbsolutePathExpr"; should be just "PathExpr".)
Comment 9 Michael Kay 2014-09-16 18:46:02 UTC
Closure of this bug seems long overdue.