This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: XPath grammar questions
- From: Jeni Tennison <jeni at jenitennison dot com>
- To: Sean Russell <ser at germane-software dot com>
- Cc: xsl-list at lists dot mulberrytech dot com
- Date: Sun, 17 Mar 2002 17:48:16 +0000
- Subject: Re: [xsl] XPath grammar questions
- Organization: Jeni Tennison Consulting Ltd
- References: <200203170903.35751.ser@germane-software.com>
- Reply-to: xsl-list at lists dot mulberrytech dot com
Hi Sean,
> Specifically, it's the 'not(*/node())' that I'm having trouble with.
> The XPath spec states that:
>
> not( boolean ) -> boolean
>
> This would imply that '*/node()' evaluates to a boolean. However, it
> also states that paths such as:
>
> ancestor::node()
>
> evaluates to a set of matching nodes. Further, I had assumed that
> the path:
>
> */node()
>
> by itself would also result in a set of nodes.
>
> I have a group of theories about this, but I'm not quite grokking
> the intent of XPath. I don't see how the same path should evaluate
> to two different results. In any case, there have been a number of
> successful implementations of XPath, so I know I'm missing
> something.
Yep. If an XPath function takes a value of a particular type as an
argument, but gets passed a value of a different type, then the actual
value should be converted to the required type automatically. So in
this case, the node set */node() should be converted to a boolean
(through the rules described in the definition of the boolean()
function), and the not() function performed on the result of that.
I don't think that this is particularly clear in the XPath 1.0 Rec,
but the XPath 2.0 WD makes a better job of spelling out what happens.
See http://www.w3.org/TR/xpath20/#id-type-conversions; for XPath 1.0,
you only have to worry about the "fallback conversions".
> The second (and at this point, more critical) problem I'm having is
> with function names. Take:
>
> [normalize-space(@name)='x']
>
> If you follow the grammar, the evaluation is:
>
> Predicate->Expr->OrExpr->AndExpr->EqualityExpr->RelationalExpr->
> AdditiveExpr
>
> at which point it matches the rule:
>
> AdditiveExpr:: AdditiveExpr '-' MultiplicativeExpr
>
> where you effectively have "normalize" "-" "space(@name)='x'".
In http://www.w3.org/TR/xpath#numbers, there's a note that reads as
follows:
NOTE: Since XML allows - in names, the - operator typically needs to
be preceded by whitespace. For example, foo-bar evaluates to a
node-set containing the child elements named foo-bar; foo - bar
evaluates to the difference of the result of converting the
string-value of the first foo child element to a number and the
result of converting the string-value of the first bar child to a
number.
Your code needs to take account of the fact that hyphens can appear in
names, and only see the - as a minus sign if it is preceded by
whitespace.
I think that when you're parsing the XPath, you need to follow the
rules about the lexical structure of XPath expressions, at
http://www.w3.org/TR/xpath#exprlex, rather than the XPath grammar
(which focuses on describing how the XPath is evaluated). I believe
that if you follow these rules (which includes a rule saying that the
longest token wins), "normalize-space(@name)='x'" is split into the
tokens:
"normalize-space" (FunctionName)
"("
"@"
"name" (NameTest)
")"
"=" (Operator)
"'x'" (Literal)
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list