Re: [xslt] xpath queries from shell revisted
- From: Dan Stromberg <dstromberglists gmail com>
- To: veillard redhat com, The Gnome XSLT library mailing-list <xslt gnome org>
- Subject: Re: [xslt] xpath queries from shell revisted
- Date: Thu, 06 Mar 2008 21:50:38 -0800
Daniel Veillard wrote:
On Tue, Mar 04, 2008 at 06:56:01PM +0000, Dan Stromberg wrote:
I'm having a little trouble with some basic XPath queries from shell.
I dug up a small handful of what-seem-like simple examples from http://
www.w3schools.com/xpath/xpath_syntax.asp and fed them into three xpath
programs (one in C, one in python, one in perl), and got pretty different
results from the 3, a number of which I believe must be incorrect.
I've summarized what I found at:
http://stromberg.dnsalias.org/~dstromberg/xml/xpath-issues.html
Is it perhaps the case that some XPath processing programs don't do
complete xpath? Are there different levels of xpath implementation
completeness?
I can't debug other implementations.
I don't expect you to.
If you have a doubt about libxml2
XPath implementation provide a reproductible test case, with the XML
and how to reproduce the problem with xmllint, textXPath (in the
distribution), xsltproc or a standalone code demonstrating the problem.
Here's the python script I was talking about. I know next to nothing
about the API in question; it's derived from Liam's C program:
#!/usr/bin/env python
# Written by Dan Stromberg <dstromberg datallegro com>, 2008-02-28, based on
# a C program obtained from liam holoweb net by dstromberg datallegro com
# on 2008-02-26. Originally named parse.c, DRS renamed it to xpath
import sys
import libxml2
def main():
commandname = sys.argv[0];
if not sys.argv[2:]:
sys.stderr.write("usage: %s filename xpath-expr1 xpath-expr2 ...
xpath-exprn\n" % commandname)
sys.exit(1)
filename = sys.argv[1]
myTree = libxml2.parseFile(filename)
if not myTree:
sys.stderr.write("%s: %s: the parse failed. Alas, I must leave
you.\n" % \
(commandname, filename))
sys.exit(1)
for arg in sys.argv[2:]:
# now extract the given xpath expression
result = matchXPathExpression(filename, myTree, arg)
if not result:
sys.stderr.write("%s: %s: no match for %s\n" % (commandname,
filename, arg))
sys.exit(1)
sys.exit(0)
def matchXPathExpression(filename, doc, expression):
context = doc.xpathNewContext()
if not context:
return None
result = context.xpathEval(expression)
if not result:
return None
for r in result:
print r.getContent()
return result
main()
There are way you ask the tree to be built which can led to different
results. In that case there is no subtleties, no DTD and libxml2 seems
to just work:
paphio:~/XML -> xmllint --shell tst.xml
/ > xpath bookstore
Object is a Node Set :
Set contains 1 nodes:
1 ELEMENT bookstore
/ > xpath /bookstore
Object is a Node Set :
Set contains 1 nodes:
1 ELEMENT bookstore
/ > xpath bookstore/book
Object is a Node Set :
Set contains 2 nodes:
1 ELEMENT book
2 ELEMENT book
/ > xpath //book
Object is a Node Set :
Set contains 2 nodes:
1 ELEMENT book
2 ELEMENT book
/ > xpath //@lang
Object is a Node Set :
Set contains 2 nodes:
1 ATTRIBUTE lang
TEXT
content=eng
2 ATTRIBUTE lang
TEXT
content=eng
/ >
You don't seem to be using any functions in your examples. Is there a
reason for that?
One thing is sure, if libxml2 XPath implementation was not accurate
for any of the very basic tests you pointed out in that page, well
libxslt/xsltproc which use XPath extensively would be completely
unusable in practice.
I don't mean to rule out that I'm misunderstanding how to use libxml2.
Like I said, I'm a noob with it.
Your web page report seems seriously unaccurate just for the fact
that XPath returns programming objects (XPath objects which can be
of various types, all node sets in those queries) and you seems to
just look at *rendering* of those object, plus the embbeding in a
web page, sorry that's not usable for distinguishing what may be
right or wrong. In any case I can't comment or even analyze other
people code.
Here it is again as text:
bookstore - Selects all the child nodes of the bookstore element
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
/data/buildroot/cruise/checkout/3.1.3-dev/xpath: bookstore.xml: no match
for bookstore
\/
/data/swbuild/da_build/xpath/xpath:
\/
/usr/bin/xpath:
Found 1 nodes:
-- NODE --
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
\/
/bookstore - Selects the root element bookstore
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
Harry Potter
29.99
Learning XML
39.95
\/
/data/swbuild/da_build/xpath/xpath:
Harry Potter
29.99
Learning XML
39.95
\/
/usr/bin/xpath:
Found 1 nodes:
-- NODE --
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
\/
bookstore/book - Selects all book elements that are children of bookstore
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
/data/buildroot/cruise/checkout/3.1.3-dev/xpath: bookstore.xml: no match
for bookstore/book
\/
/data/swbuild/da_build/xpath/xpath:
\/
/usr/bin/xpath:
Found 2 nodes:
-- NODE --
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>-- NODE --
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
\/
//book - Selects all book elements no matter where they are in the document
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
Harry Potter
29.99
Learning XML
39.95
\/
/data/swbuild/da_build/xpath/xpath:
Harry Potter
29.99
\/
/usr/bin/xpath:
Found 2 nodes:
-- NODE --
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>-- NODE --
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
\/
bookstore//book - Selects all book elements that are descendant of the
bookstore element, no matter where they are under the bookstore element
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
/data/buildroot/cruise/checkout/3.1.3-dev/xpath: bookstore.xml: no match
for bookstore//book
\/
/data/swbuild/da_build/xpath/xpath:
\/
/usr/bin/xpath:
Found 2 nodes:
-- NODE --
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>-- NODE --
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
\/
//@lang - Selects all attributes that are named lang
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
eng
eng
\/
/data/swbuild/da_build/xpath/xpath:
eng
\/
/usr/bin/xpath:
Found 2 nodes:
-- NODE --
lang="eng"-- NODE --
lang="eng"
\/
/bookstore/book[1] - Selects the first book element that is the child of
the bookstore element.
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
Harry Potter
29.99
\/
/data/swbuild/da_build/xpath/xpath:
Harry Potter
29.99
\/
/usr/bin/xpath:
Found 1 nodes:
-- NODE --
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
\/
/bookstore/book[last()] - Selects the last book element that is the
child of the bookstore element
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
Learning XML
39.95
\/
/data/swbuild/da_build/xpath/xpath:
Learning XML
39.95
\/
/usr/bin/xpath:
Found 1 nodes:
-- NODE --
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
\/
/bookstore/book[last()-1] - Selects the last but one book element that
is the child of the bookstore element
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
Harry Potter
29.99
\/
/data/swbuild/da_build/xpath/xpath:
Harry Potter
29.99
\/
/usr/bin/xpath:
Found 1 nodes:
-- NODE --
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
\/
/bookstore/book[position()<3] - Selects the first two book elements that
are children of the bookstore element
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
Harry Potter
29.99
Learning XML
39.95
\/
/data/swbuild/da_build/xpath/xpath:
Harry Potter
29.99
\/
/usr/bin/xpath:
Found 2 nodes:
-- NODE --
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>-- NODE --
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
\/
//title[ lang] - Selects all the title elements that have an attribute
named lang
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
Harry Potter
Learning XML
\/
/data/swbuild/da_build/xpath/xpath:
Harry Potter
\/
/usr/bin/xpath:
Found 2 nodes:
-- NODE --
<title lang="eng">Harry Potter</title>-- NODE --
<title lang="eng">Learning XML</title>
\/
//title[ lang='eng'] - Selects all the title elements that have an
attribute named lang with a value of 'eng'
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
Harry Potter
Learning XML
\/
/data/swbuild/da_build/xpath/xpath:
Harry Potter
\/
/usr/bin/xpath:
Found 2 nodes:
-- NODE --
<title lang="eng">Harry Potter</title>-- NODE --
<title lang="eng">Learning XML</title>
\/
/bookstore/book[price>35.00] - Selects all the book elements of the
bookstore element that have a price element with a value greater than 35.00
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
Learning XML
39.95
\/
/data/swbuild/da_build/xpath/xpath:
Learning XML
39.95
\/
/usr/bin/xpath:
Found 1 nodes:
-- NODE --
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
\/
/bookstore/book[price>35.00]/title - Selects all the title elements of
the book elements of the bookstore element that have a price element
with a value greater than 35.00
/data/buildroot/cruise/checkout/3.1.3-dev/xpath:
Learning XML
\/
/data/swbuild/da_build/xpath/xpath:
Learning XML
\/
/usr/bin/xpath:
Found 1 nodes:
-- NODE --
<title lang="eng">Learning XML</title>
\/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]