From: Aaron Patterson Date: 2009-08-03T07:39:29+09:00 Subject: Re: : Can't find nodes using XPath, namespaces mess On Sun, Aug 02, 2009 at 12:50:05AM +0900, Matt Neuburg wrote: > Stanislaw Wozniak wrote: > > > Hi, this was a typo, no semicolon in there: > > > > > > > xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > > xsi:schemaLocation="urn:company:platform:foundation:configuration:defn:v1" > > xmlns="urn:company:platform:foundation:configuration:defn:v1"> > > > > > > > > > > > > > > > > > > > > > > Then what's the problem? XPath works: > > s = < > xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > xsi:schemaLocation="urn:company:platform:foundation:configuration:defn:v > 1" > xmlns="urn:company:platform:foundation:configuration:defn:v1"> > > > > > > > > > > > END > require 'rexml/document' > include REXML > doc = Document.new(s) > p XPath.match(doc, "//treenode['Root']/treenode") > #=> [] Wow. These results are just wrong. This is a bug in REXML. In XPath, when you do not specify a namespace for your node, that means that you want a node *with no namespace*. For example: require 'rexml/document' include REXML s = < END doc = Document.new(s) p XPath.match(doc, "//tire") REXML matches *all three* tires. Surely a car tire is not the same as a bike tire? Using XPath, how would I query for a tire that has *no namespace* (the third one) without matching the two that *do* belong in a namespace (it's possible to do this with REXML, just strange)? The XPath used above *should* only match the third entry. This is a broken implementation of XPath. > > Oh, wait, you said you were using libxml: > You have an error in your XML below > s = < > ^ That ">" should not be there. libxml-ruby has corrections turned on by default, so you've effectively removed all namespaces from this document. > xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > xsi:schemaLocation="urn:company:platform:foundation:configuration:defn:v > 1" > xmlns="urn:company:platform:foundation:configuration:defn:v1"> > > > > > > > > > > > END > require 'rubygems' > require 'xml' > doc = XML::Document.string(s) > doc.find("//treenode['Root']/treenode").each do |el| > p el #=> > end > > Sorry, I'm failing to guess what problem you're having. Perhaps if you > showed your actual code? m. Since the namespaces were removed, this example succeeds. -- Aaron Patterson http://tenderlovemaking.com/