| 23 January 2007 |
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
-
-
InputSource inputSource =
-
-
//Use inputsource as source for the Xpath evaluation of certain expressions
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();
-
inputSource = docBuilder.parse(sourceFile);
-
-
XPathFactory factory = XPathFactory.newInstance();
-
XPath xPath = factory.newXPath();
-
-
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!


3 comments to 'Using JDK5 XPath functionality'
15 August 2007
[...] base for this post is this one, to create a standalone HumanWorkflowReader. If you have this in place (or something similar) [...]
23 August 2007
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
15 June 2008
good call... documnet obj works like a charm