Using JDK5 XPath functionality

Although JDK5 is available for quite some time I just recently used the builtin ‘XPath’ functionality. I wanted to check if a certain WSDL file contained certain tags and if the message style was set to ‘Document’ and not ‘RPC’. Now this seemed as a great oppertunity to use the XPath object so I started with the following code.
(Please note that this code is just for showing my issue, this is not how I actually would make it 😉 ). The base for this code I found here.

// Translate WSDl file to an InputSOurce
File xmlDocument = new File(new URI(fileName));

InputSource inputSource =
new InputSource(new FileInputStream(xmlDocument));

//Use inputsource as source for the Xpath evaluation of certain expressions
String doc = xPath.evaluate(“//pre:definitions//pre:portType//pre:documentation”, inputSource);

After solving a namespace issue I was able to check for the tag. But doing the same sort of code for the second check

String msgStyle =
xPath.evaluate("//pre:definitions//pre:binding//soap:binding/@style",
inputSource);

I ran into this error:

java.io.IOException: Invalid argument
at java.io.FileInputStream.read(Native Method)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager$RewindableInputStream.read(XMLEntityManager.java:2622)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:997)
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:184)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:798)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:148)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:250)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:292)
at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(XPathImpl.java:468)
at org.soacheck.impl.WsdlCheckerImpl.check2(WsdlCheckerImpl.java:191)
at org.soacheck.Processor.main(Processor.java:31)
————— linked to ——————
javax.xml.xpath.XPathExpressionException
at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(XPathImpl.java:475)
at org.soacheck.impl.WsdlCheckerImpl.check2(WsdlCheckerImpl.java:191)
at org.soacheck.Processor.main(Processor.java:31)
Caused by: java.io.IOException: Invalid argument
at java.io.FileInputStream.read(Native Method)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager$RewindableInputStream.read(XMLEntityManager.java:2622)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:997)
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:184)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:798)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:148)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:250)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:292)
at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(XPathImpl.java:468)
… 2 more

I started to look for the error in my own code, maybe I did something wrong with the XPath object, but Googling for the error didn’t bring a solution rightaway. However, I did notice that a lot of examples of the XPath expression used a Document as input and not an InputSource. So I therefore rewrited the code to make it use a Document object.

DocumentBuilder docBuilder = null;
Document inputSource = null;
File sourceFile = null;

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setIgnoringElementContentWhitespace(true);
dbFactory.setNamespaceAware(true); // never forget this!

docBuilder = dbFactory.newDocumentBuilder();
sourceFile = new File(new URI(fileName));
inputSource = docBuilder.parse(sourceFile);

XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();

String doc = xPath.evaluate(“//pre:definitions//pre:portType//pre:documentation”, inputSource);
String msgStyle = xPath.evaluate(“//pre:definitions//pre:binding//soap:binding/@style”, inputSource);

Now this code works like a charm! But the issue that remains is why? Apparently you can not ‘search’ an XML document twice with a Sax inputsource as source. I guess that make sense in some way, since SAX responds to events when reading the XML. But if this is true then I am surprised it didn’t say anything about it in the Javadoc (or I didn’t search hard enough?) and couldn’t there be made a more friendly error message pointing to a possible solution for this issue? If I am wrong about this, please let me know!

About Pascal Alma

Pascal is a senior IT consultant and has been working in IT since 1997. He is monitoring the latest development in new technologies (Mobile, Cloud, Big Data) closely and particularly interested in Java open source tool stacks, cloud related technologies like AWS and mobile development like building iOS apps with Swift. Specialties: Java/JEE/Spring Amazon AWS API/REST Big Data Continuous Delivery Swift/iOS
This entry was posted in XML/ XSD/ XSLT and tagged . Bookmark the permalink.

2 Responses to Using JDK5 XPath functionality

  1. Paul Campbell says:

    I had a similiar result. I think that you are correct that the original method fails because it uses a SAX parser and the docBuilder.parse is DOM.
    Thanks for your suggestion.

    I am a little disapointed in the execution time.

    I was trying to replace a memory hog that groveled thru strings with
    XPath, but it seems to be an order of magnitude slower, 20 ms went to 300ms

  2. sandeep says:

    good call… documnet obj works like a charm

Comments are closed.