Groups | Blog | Home
all groups > dotnet xml > february 2006 >

dotnet xml : Why does this xpath fail - starting over



David Thielen
2/25/2006 3:15:27 PM
Hi;

I am sure I am missing something here but I cannot figure it out. Below I
have a program and I cannot figure out why the xpath selects that throw an
exception fail. From what I know they should work.

Also the second nav.OuterXml appears to also be wrong to me.

Can someone explain to me why this does not work? (This is an example from a
program we have where xpath can be entered in two parts so we have to be able
to handle this. We can't just always require the fill
/order/product[.='software'].)

Program below sig.

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com

Program.cs:
using System.Xml;
using System.Xml.XPath;
using System;
using System.IO;

namespace XPathSample
{
class Program
{
static void Main(string[] args)
{

string xml =
"<order>" +
"<product>software</product>" +
"<product>software</product>" +
"</order>";
XPathDocument doc = new XPathDocument(new StringReader(xml));

// this works
XPathNavigator nav = doc.CreateNavigator();
XPathNavigator rtn = nav.SelectSingleNode("/order/product[.='software']");
Console.Out.WriteLine("nav(/) = " + nav.OuterXml);
Console.Out.WriteLine("/order/product[.='software'] = " + rtn.OuterXml);

// this works although the nav.OuterXml appears wrong
nav = nav.SelectSingleNode("/order");
rtn = nav.SelectSingleNode("product[.='software']");
Console.Out.WriteLine("nav(/order) = " + nav.OuterXml);
Console.Out.WriteLine("product[.='software'] = " + rtn.OuterXml);

// this works (same as prev)
rtn = nav.SelectSingleNode("./product[.='software']");
Console.Out.WriteLine("./product[.='software'] = " + rtn.OuterXml);

nav = nav.SelectSingleNode("product");
Console.Out.WriteLine("nav(/order/product) = " + nav.OuterXml);

// these all fail - WHY?
try
{
rtn = nav.SelectSingleNode("[.='software']");
}
catch (XPathException ex)
{
Console.Out.WriteLine("[.='software'] exception = " + ex.Message);
}
try
{
rtn = nav.SelectSingleNode("./[.='software']");
}
catch (XPathException ex)
{
Console.Out.WriteLine("./[.='software'] exception = " + ex.Message);
}

// yes this works - but I need the node as it does have a value.
object obj = nav.Evaluate(".='software'");
Console.Out.WriteLine(".='software' evaluate = " + obj);


Console.Out.WriteLine("all done");
}
}
}

Dimitre Novatchev
2/26/2006 12:00:00 AM
[quoted text, click to view]

because of a common feature -- they all have invalid XPath syntax.

[quoted text, click to view]


Try:

"self::*[.='software']"

or

"string(self::*[.='software'])"

depending on whether you need the node or its string value returned.


Cheers,
Dimitre Novatchev





[quoted text, click to view]

David Thielen
2/26/2006 4:41:28 PM
Hello;

I assumed it is invalid syntax. My question is why? I don't understand why
"[.='software']" or some variation of that is invalid.

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com



[quoted text, click to view]
Dimitre Novatchev
2/27/2006 12:00:00 AM

[quoted text, click to view]

Read the XPath 1.0 Spec.

It says:

http://www.w3.org/TR/xpath#predicates

"A predicate filters a node-set with respect to an axis to produce a new
node-set. For each node in the node-set to be filtered, the PredicateExpr is
evaluated with that node as the context node, with the number of nodes in
the node-set as the context size, and with the proximity position of the
node in the node-set with respect to the axis as the context position; if
PredicateExpr evaluates to true for that node, the node is included in the
new node-set; otherwise, it is not included."



So, a predicate can only apear after some XPath expression and filters it. A
predicate, alone, is not a valid XPath expression.

This is also made clear if we look at the BNF grammar definition of XPath
1.0. Of all rules only rule [4] and rule [20] contain the nonterminal symbol
predicate and it is always not the leading symbol (of the RHS):



http://www.w3.org/TR/xpath#section-Location-Steps


[4] Step ::= AxisSpecifier NodeTest Predicate*
| AbbreviatedStep




http://www.w3.org/TR/xpath#node-sets



[20] FilterExpr ::= PrimaryExpr
| FilterExpr Predicate




I hope that this answers completely your question.


Cheers,
Dimitre Novatchev



[quoted text, click to view]


David Thielen
2/27/2006 10:15:13 AM
Hi;

First, thanks for helping on this I really appreciate it.

Ok, I see that the xpath must start with "." to get it to the node and the
"[...]" then modifies that - makes sense.

But then, shouldn't ".[.='software']" or "./.[.='software']" or
"./[.='software']" work.

In the case of ".[.='software']" isn't that saying start with the node "."
(which exists) and then return all where .='software'?

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com



[quoted text, click to view]
David Thielen
2/27/2006 12:54:50 PM
Hello;

Is this correct to say:
"/order/software" or "software" in each case is an axis specifier while "."
is an abbreviated step?

I had thought both were a way of specifing a node and therefore were an
axisSpecifier.

Also, any good book(s) or website(s) that explain this, preferably by example?

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com



[quoted text, click to view]
Dimitre Novatchev
2/28/2006 12:00:00 AM

[quoted text, click to view]

No, Axis specifier can be only a predefined (full) name out of 13 axis names
(see below) or an abbreviated axis specifier (just "@").

[quoted text, click to view]

No.

The rules from the spec:

[5] AxisSpecifier ::= AxisName '::'
| AbbreviatedAxisSpecifier


[6] AxisName ::= 'ancestor'
| 'ancestor-or-self'
| 'attribute'
| 'child'
| 'descendant'
| 'descendant-or-self'
| 'following'
| 'following-sibling'
| 'namespace'
| 'parent'
| 'preceding'
| 'preceding-sibling'
| 'self'


[13] AbbreviatedAxisSpecifier ::= '@'?




[quoted text, click to view]

Michael Kay's books on XSLT 1.0, XSLT 2.0 and XPath 2.0
http://www.amazon.com/gp/product/1861005067/qid=1141109739/sr=2-2/ref=pd_bbs_b_2_2/104-7387044-2692707?s=books&v=glance&n=283155

http://www.amazon.com/gp/product/0764569090/qid=1141109739/sr=2-1/ref=pd_bbs_b_2_1/104-7387044-2692707?s=books&v=glance&n=283155

http://www.amazon.com/gp/product/0764569104/qid=1141109739/sr=2-3/ref=pd_bbs_b_2_3/104-7387044-2692707?s=books&v=glance&n=283155


Jeni Tennison's books on the same topics.
http://www.amazon.com/gp/product/1590592603/qid=1141109854/sr=1-2/ref=sr_1_2/104-7387044-2692707?s=books&v=glance&n=283155

http://www.amazon.com/gp/product/0764547763/qid=1141109854/sr=1-1/ref=sr_1_1/104-7387044-2692707?s=books&v=glance&n=283155

http://www.amazon.com/gp/product/1590593243/qid=1141109854/sr=2-1/ref=pd_bbs_b_2_1/104-7387044-2692707?s=books&v=glance&n=283155


Hope this helped.

Cheers,
Dimitre Novatchev.


[quoted text, click to view]
Dimitre Novatchev
2/28/2006 12:00:00 AM
[quoted text, click to view]

I would recommend the XPath Visualizer as a proven tool for playing with
XPath and learning it "the fun way".

Cheers,
Dimitre Novatchev

[quoted text, click to view]
Dimitre Novatchev
2/28/2006 12:00:00 AM
[quoted text, click to view]

I would recommend the XPath Visualizer as a proven tool for playing with
XPath and learning it "the fun way".

Cheers,
Dimitre Novatchev

[quoted text, click to view]
Dimitre Novatchev
2/28/2006 12:00:00 AM

[quoted text, click to view]

No, the syntax rules do not allow this:

[quoted text, click to view]

as we can see, Predicatecan only occur after a NodeTest , not after an
AbbreviatedStep.

[quoted text, click to view]

Again, Predicate cannot be the leftmost symbol in a step

[quoted text, click to view]

This may seem a clear semantics, but the syntax is invalid according to the
XPath 1.0 grammar rules.

As I said, use:

self::node()[.='software']



Cheers,
Dimitre Novatchev

[quoted text, click to view]
AddThis Social Bookmark Button