- From: Norman Walsh <ndw@nwalsh.com>
- Date: Wed, 23 May 2007 07:37:21 -0400
- To: public-xml-processing-model-wg@w3.org
- Message-ID: <878xbfhitq.fsf@nwalsh.com>
/ Jeni Tennison <jeni@jenitennison.com> was heard to say:
| Norman Walsh wrote:
|> Position is always 1 in for-each and viewport because they're odd cases.
|> Consider this example instead:
|>
|> <p:matching-documents>
|> <p:input port="source">
|> <p:inline>
|> <odd/>
|> </p:inline>
|> <p:inline>
|> <even/>
|> </p:inline>
|> <p:inline>
|> <odd/>
|> </p:inline>
|> <p:inline>
|> <even/>
|> </p:inline>
|> <p:inline>
|> <odd/>
|> </p:inline>
|> </p:input>
|> <p:option name="test" value="$p:position mod 2 = 1"/>
|> </p:matching-documents>
|>
|> It returns all the "<odd/>" documents.
|>
|> I think this example also illustrates why it would be a mistake to
|> overload XPath's built-in position() function. A complex expression
|> might use position() in a more natural context and it would be confusing
|> (though I grant not explicitly illegal) to have position() used in two
|> different ways in the same expression.
|
| I really don't understand this example. You seem to be suggesting that there's
| some implicit iteration happening, that the component is passed:
All of the steps that accept a sequence do iterate implicitly. We simply
don't pass sequences to very many steps.
| * a single document on the 'source' port (with the document element <odd>)
| * the option 'test' with the value '$p:position mod 2 = 1'
| * a set of variable bindings that includes the binding of $p:position to 1
|
| then,
|
| * a single document on the 'source' port (with the document element <even>)
| * the option 'test' with the value '$p:position mod 2 = 1'
| * a set of variable bindings that includes the binding of $p:position to 2
|
| and so on.
Yes, whether we call it $p:position or p:position(), I expect
p:matching-documents and other steps that evaluate an expression in the
context of a sequence to keep track of the number of documents that have
passed by and return the position correctly.
| In this explanation, the pipeline processor is in charge of the iteration,
| supplies a different value of $p:position each time, and therefore you only get
| the <odd> elements.
The pipeline processor doesn't do any iteration, it just passes the
sequence to the step.
| I thought that we'd decided not to allow implicit iteration, (a) because we run
| into huge problems if we have steps that have more than one port that accepts
| sequences and (b) because it means you can't have steps that do useful things
| like count the number of documents passed on a port.
Right. The pipeline processor is not doing the iteration, the step is,
and yes, I had thought that meant the step had to keep track of some
evolution in its XPath context.
| So assuming that there *isn't* implicit iteration, this is what I think happens:
| the p:matching-documents component gets passed:
|
| * a sequence of documents on the 'source' port (with the document elements
| <odd> and <even>)
| * the option 'test' with the value '$p:position mod 2 = 1'
| * a set of variable bindings, which presumably includes the binding of
| $p:position to some number, let's say 1.
|
| The component iterates through the documents on the 'source' port, and for each
| one evaluates the XPath "$p:position mod 2 = 1". Since the value of $p:position
| is bound to 1, this is always true. Therefore the component returns all the
| documents on the 'source' port.
I can see the appeal of that interpretation, but in that case I don't
think p:position() is useful enough to bother implementing.
| I think that p:matching-documents should say:
|
| The XPath expression supplied as the value of the 'test' option is
| evaluated for each document supplied on the 'source' port, with the
| following context:
|
| * the context node is the document itself
| * the context position is the position of the document in the sequence
| supplied to the 'source' port
| * the context size is the number of documents in the sequence supplied
| to the 'source' port
| * the variable bindings are those supplied to the step
| * the function library is the core XPath function library
| * the namespace declarations are those supplied to the step
|
| and that using
|
| <p:option name="test" value="position() mod 2 = 1" />
|
| will work just fine.
Two things:
First, it seems to me that the step has to update the context position
as it iterates through the sequence and I don't see how that's any
different than updating the p:position().
Second, while all of the off-the-shelf XPath processors that I've looked
at offer some mechanism for calling extension functions (or setting
variables, though we've opted not to go that way, I think), I'm much
less confident that they provide a mechanism for changing the internal
context position.
While I concede that the number of documents can be seen as the context
position in one sense, I remain of the opinion that that's not very
XPath-1-like and would prefer to use an extension function.
| The only issue that I can see is:
|> I still think it would be wrong. Not only for the reason I gave just
|> above but also because it might encourage people to believe that they
|> could use last() and the streaming folks explicitly don't want to have
|> to support that.
|
| To get around this, the p:matching-documents step *could* say:
|
| * the context size is the number of documents in the same as the
| context position
|
| This would mean that users could still use last() but not in any meaningful way.
|
| But the streaming folks are going to have to do some analysis of XPath
| expressions anyway, since not all of them are going to be streamable, and one of
| the tests could be whether the expression contains the last() function or not.
| If it doesn't, as in the above example, streaming is still a possibility; if it
| does, then it can't stream.
I think there was strong resistance to supporting last() or p:last()
when we discussed this before.
Be seeing you,
norm
--
Norman Walsh <ndw@nwalsh.com> | He that will not apply new remedies
http://nwalsh.com/ | must expect new evils; for time is the
| great innovator.--Sir Francis Bacon
Received on Wednesday, 23 May 2007 11:37:29 UTC