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.
1 2 3 4 5 6 7 8 | // 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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!
Pingback: Pascal’s Blog » Create an ADF ViewObject based on BPEL’s HumanWorkflow Tasklist
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
good call… documnet obj works like a charm