Re: [xslt] xpath queries from shell revisted



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]