I believe that I have prefixed my xpath properly, but I get an
XPathExpressionException when I evaluate it.
The xpath looks like this (note the "xhtml" prefix):
/xhtml:html/xhtml:body//xhtml:div[@class='reviewlist']
The source XML document is a garden-variety XHTML web page whose root
html element declares the document's default namespace as being
http://www.w3.org/1999/xhtml.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"
http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"<html xml:lang="en" xmlns="
http://www.w3.org/1999/xhtml">
As I understand it, writing the html element like this declares that it
belongs to the
http://www.w3.org/1999/xhtml namespace. So, to evaluate
an xpath for this document, my javax.xml.xpath.XPath must have a
namespace context set. Here is my implementation of the the
javax.xml.namespace.NamespaceContext interface (note this
implementation accommodates mutlitple namespaces by use of a
java.util.HashMap - a tip from
http://www.onjava.com/pub/a/onjava/2005/01/12/xpath.html - lest a part
of the web page be in another language and its element has, say,
xml:lang="fr").
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.NamespaceContext;
public class NamespaceContextImpl implements NamespaceContext {
private Map map;
/**
* A contructor that instantiates a new java.util.HashMap in which
* namespace URIs will be mapped to prefixes.
*
* This method is inherited from the implemented NamespaceContext
interface.
*/
public NamespaceContextImpl() {
map = new HashMap();
}
/**
* Adds a prefix and namespace URI pair to this
* NamespaceContextImpl's HashMap.
*
* This method is not inherited from the implemented
* NamespaceContext interface.
*/
public void setNamespaceURI(String prefix, String namespaceURI) {
map.put(prefix, namespaceURI);
}
/**
* Gets the namespace URI mapped to the given
* prefix from this NamespaceContextImpl's HashMap.
*
* This method is inherited from the implemented NamespaceContext
interface.
*/
public String getNamespaceURI(String prefix) {
return (String)map.get(prefix);
}
/**
* Gets the prefix to which the given namespace
* URI is mapped in this NamespaceContextImpl's
* HashMap.
*
* This method is inherited from the implemented
* NamespaceContext interface.
*/
public String getPrefix(String namespaceURI) {
Set keys = map.keySet();
// Loop through the prefixes until one is found
// whose corresponding namespace URI matches
// the namespace URI passed to this method.
// Return that prefix.
for(Iterator i = keys.iterator(); i.hasNext(); ) {
String prefix = (String)i.next();
String uri = (String)map.get(prefix);
if(uri.equals(namespaceURI)) return prefix;
}
// If prefix is found with a namespace URI matching the
// namespace URI passed to this method, return null.
return null;
}
/**
* This method is inherited from the implemented
* NamespaceContext interface.
*/
public Iterator getPrefixes(String namespaceURI) {
return null;
}
}
I then use this NamespaceContext like this:
javax.xml.xpath.XPathFactory factory = XPathFactory.newInstance();
javax.xml.xpath.XPath xpath = factory.newXPath();
NamespaceContextImpl nsctx = new NamespaceContextImpl();
nsctx.setNamespaceURI("xml", "
http://www.w3.org/XML/1998/namespace");
nsctx.setNamespaceURI("xhtml", "
http://www.w3.org/1999/xhtml");
xpath.setNamespaceContext(nsctx);
For the evaluate method, I need a org.xml.sax.InputSource, which i get
like this:
java.net.URL url = new
java.net.URL("
http://www.mywebpage.com/index.html");
java.net.HttpURLConnection huc =
(java.net.HttpURLConnection)url.openConnection();
org.xml.sax.InputSource ins = new
org.xml.sax.InputSource(huc.getInputStream());
Now I can evaluate the xpath and, I hope, get a org.w3c.dom.NodeList:
org.w3c.dom.NodeList nl = (
org.w3c.dom.NodeList)xpath.evaluate(
"/xhtml:html/xhtml:body//xhtml:div[@class='reviewlist']"
ins,
javax.xml.xpath.XPathConstants.NODESET
);
The result I get from calling this method, though, is a
javax.xml.xpath.XPathExpressionException, I think. At least, when I
catch the exception and call its toString() method, that what it says
it is. When I call its getCause() method, though, I get:
java.net.ConnectExcpetion: Connection timed out.
Its stack trace looks like this:
com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(XPathImpl.java:475)
my.package.WebsiteHandler.startElement(Unknown Source)
org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown
Source)
org.apache.xerces.parsers.AbstractXMLDocumentParser.emptyElement(Unknown
Source)
org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown
Source)
org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown
Source)
org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown
Source)
org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
org.cochrane.sitebuilder.servlet.WebsiteBuilder.parseWebSiteLayoutXML(Unknown
Source)
org.cochrane.sitebuilder.servlet.WebsiteBuilder.service(Unknown
Source)
javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:39)
org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:153)
org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:59)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
java.lang.Thread.run(Thread.java:595)
Is it an XPathExpressionException? Is it a java.net.ConnectException?
What's going on?