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.

JAVA:
  1. // Translate WSDl file to an InputSOurce
  2. File xmlDocument = new File(new URI(fileName));
  3.  
  4. InputSource inputSource =
  5. new InputSource(new FileInputStream(xmlDocument));
  6.  
  7. //Use inputsource as source for the Xpath evaluation of certain expressions
  8. 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.

JAVA:
  1. DocumentBuilder docBuilder = null;
  2. Document inputSource = null;
  3. File sourceFile = null;
  4.  
  5. DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
  6. dbFactory.setIgnoringElementContentWhitespace(true);
  7. dbFactory.setNamespaceAware(true); // never forget this!
  8.  
  9. docBuilder = dbFactory.newDocumentBuilder();
  10. sourceFile = new File(new URI(fileName));
  11. inputSource = docBuilder.parse(sourceFile);
  12.  
  13. XPathFactory factory = XPathFactory.newInstance();
  14. XPath xPath = factory.newXPath();
  15.  
  16. String doc = xPath.evaluate(//pre:definitions//pre:portType//pre:documentation”, inputSource);
  17. 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!