  | |  | Weird behavior of XPath.evaluate() | Weird behavior of XPath.evaluate() 2007-05-10 - By Jason Morris
Hi all,
Apologies if this has been asked before but it is driving me mad. I am happily able to evaluate non-namespaced XPath expressions using either an InputSource or a document context element. I can evaluate namespaced expressions using the InputSource, but it doesn't work if I evaluate a namespaced expression passing an Element as a context node.
Take the example file from http://xml.apache.org/xalan-j/xpath_apis.html#namespacecontext
<?xml version='1.0'?>
<foo:document xmlns:foo="http://apache.org/foo" xmlns:bar=" http://apache.org/bar"> <bar:element>MyBar</bar:element> </foo:document>
I want to evaluate "/foo:document/bar:element", which should return "MyBar". I use the following code:
package test;
import java.util.Iterator;
import javax.xml.XMLConstants; import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory ;
import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource;
public class NamespaceTest { public static void main(String[] argv) throws Exception { String doc = " namespace.xml"; String xPath = "/foo:document/bar:element";
// Parse the doc independently to get the root Element DocumentBuilderFactory fct = DocumentBuilderFactory.newInstance (); DocumentBuilder builder = fct.newDocumentBuilder(); Document document = builder.parse("file:" + doc); Element rootElement = document.getDocumentElement();
// Setup the namespace context XPathFactory factory = XPathFactory.newInstance(); XPath xp = factory.newXPath(); NamespaceContext ctx = new MyNamespaceContext(); xp.setNamespaceContext(ctx);
// Create an InputSource of the file InputSource is = new InputSource(doc);
// This works String resultString1 = xp.evaluate(xPath,is); // This doesn't String resultString2 = xp.evaluate (xPath,rootElement);
System.out.println("RES1=" + resultString1); System.out.println("RES2=" + resultString2); } }
class MyNamespaceContext implements NamespaceContext { public String getNamespaceURI(String prefix) { if (prefix.equals("foo")) return "http://apache.org/foo"; else if ( prefix.equals("bar")) return "http://apache.org/bar"; else return XMLConstants.NULL_NS_URI; }
public String getPrefix(String namespace) { if (namespace.equals("http://apache.org/foo")) return "foo"; else if (namespace.equals(" http://apache.org/bar")) return "bar"; else return null; }
public Iterator getPrefixes(String namespace) { return null; } }
When I execute this (against Xalan 2.7.0), resultString1 returns "MyBar" correctly, resultString2 is set as empty string. Surely they should both return the correct result? Interestingly, if I use the exact same code to evaluate a namespace-free expression, both versions work fine.
Is this a bug, or am I doing something stupid with the rootElement I am passing in?
Any and all assistance greatly appreciated,
Jason
Hi all,<br><br>Apologies if this has been asked before but it is driving me mad . I am happily able to evaluate non-namespaced XPath expressions using either an InputSource or a document context element. I can evaluate namespaced expressions using the InputSource, but it doesn't work if I evaluate a namespaced expression passing an Element as a context node. <br><br>Take the example file from <a href="http://xml.apache.org/xalan-j/xpath _apis.html#namespacecontext" target="_blank" onclick="return top.js.OpenExtLink (window,event,this)">http://xml.apache.org/xalan-j/xpath_apis.html #namespacecontext </a><br><br><?xml version='1.0'?><br> <br> <foo:document xmlns:foo="<a href="http://apache.org/foo" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">http:/ /apache.org/foo</a>" xmlns:bar="<a href="http://apache.org/bar" target ="_blank" onclick="return top.js.OpenExtLink(window,event,this)"> http://apache.org/bar</a>"><br> <bar:element> ;MyBar</bar:element> <br> </foo:document><br> <br>I want to evaluate "/foo :document/bar:element", which should return "MyBar". I use the following code:<br><br>package test;<br><br>import java.util.Iterator;<br><br>
import javax.xml.XMLConstants;<br>import javax.xml.namespace.NamespaceContext; <br>import javax.xml.parsers.DocumentBuilder;<br>import javax.xml.parsers .DocumentBuilderFactory;<br>import javax.xml.xpath.XPath;<br>import javax.xml .xpath.XPathFactory
;<br><br>import org.w3c.dom.Document;<br>import org.w3c.dom.Element;<br>import org.xml.sax.InputSource;<br><br>public class NamespaceTest<br>{<br> public static void main(String[] argv) throws Exception<br> {<br> String doc = " namespace.xml";<br> String xPath = "/foo:document/bar:element";<br><br> // Parse the doc independently to get the root Element<br> DocumentBuilderFactory fct = DocumentBuilderFactory .newInstance
();<br> DocumentBuilder builder = fct .newDocumentBuilder();<br> Document document = builder.parse("file:" + doc);<br> Element rootElement = document.getDocumentElement();<br><br> // Setup the namespace context <br> XPathFactory factory = XPathFactory .newInstance();<br> XPath xp = factory .newXPath();<br> NamespaceContext ctx = new MyNamespaceContext();<br> xp .setNamespaceContext(ctx);<br> <br> // Create an InputSource of the file <br> InputSource is = new InputSource(doc) ;<br> <br> // This works<br> String resultString1 = xp.evaluate(xPath,is);<br> // This doesn't<br> String resultString2 = xp.evaluate
(xPath,rootElement);<br><br> System.out .println("RES1=" + resultString1);<br> System.out.println("RES2=" + resultString2);<br> }<br>}<br><br><br><br>class MyNamespaceContext implements NamespaceContext <br>{<br> public String getNamespaceURI(String prefix)<br> {<br> if (prefix .equals("foo"))<br> return "<a href="http://apache.org/foo" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)"> http://apache.org/foo</a>";<br> else if ( prefix.equals("bar"))<br> return "<a href="http://apache.org/bar" target=" _blank" onclick="return top.js.OpenExtLink(window,event,this)">http://apache.org /bar</a>";<br> else<br> return XMLConstants.NULL_NS_URI;<br> }<br> <br> public String getPrefix(String namespace) <br> {<br> if (namespace.equals("<a href="http://apache.org/foo" target="_blank" onclick= "return top.js.OpenExtLink(window,event,this)">http://apache.org/foo</a>")) <br> return "foo"; <br> else if (namespace.equals(" <a href="http://apache.org/bar" target="_blank" onclick="return top.js .OpenExtLink(window,event,this)"> http://apache.org/bar</a>"))<br> return "bar";<br> else<br>   ; return null;<br> }<br><br> public Iterator getPrefixes(String namespace)<br> {<br> return null;<br> } <br>} <br><br><br>When I execute this (against Xalan 2.7.0), resultString1 returns "MyBar" correctly, resultString2 is set as empty string. Surely they should both return the correct result? Interestingly, if I use the exact same code to evaluate a namespace-free expression, both versions work fine. <br><br>Is this a bug, or am I doing something stupid with the rootElement I am passing in?<br><br>Any and all assistance greatly appreciated,<br><br>Jason<br> <br>
|
|
 |