I would like to reuse some existing code in our code base that accepts an XMLStreamReader
my application has the required data as a w3c Document.
The following example is a minimum test case:
public static void main(String[] args) throws Exception {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document doc = builder.newDocument();
Element rootElement = doc.createElement("Groups");
doc.appendChild(rootElement);
Element group = doc.createElement("Group");
group.setTextContent("Wibble");
rootElement.appendChild(group);
DOMSource source = new DOMSource(doc);
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(source);
reader.nextTag();
System.out.println("NextTag:" + reader.getName());
}
The expected output should be something like: NextTag:Groups
but instead the following is thrown:
Exception in thread "main" javax.xml.stream.XMLStreamException: java.net.MalformedURLException
at com.sun.xml.stream.XMLReaderImpl.setInputSource(XMLReaderImpl.java:196)
at com.sun.xml.stream.XMLReaderImpl.<init>(XMLReaderImpl.java:179)
at com.sun.xml.stream.ZephyrParserFactory.createXMLStreamReader(ZephyrParserFactory.java:139)
at Main.main(Main.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.net.MalformedURLException
at java.net.URL.<init>(URL.java:601)
at java.net.URL.<init>(URL.java:464)
at java.net.URL.<init>(URL.java:413)
at com.sun.xml.stream.XMLEntityManager.startEntity(XMLEntityManager.java:762)
at com.sun.xml.stream.XMLEntityManager.startDocumentEntity(XMLEntityManager.java:697)
at com.sun.xml.stream.XMLDocumentScannerImpl.setInputSource(XMLDocumentScannerImpl.java:300)
at com.sun.xml.stream.XMLReaderImpl.setInputSource(XMLReaderImpl.java:193)
... 8
Currently using Java 6 update 22.
Further info: The source to ZephyrParserFactory#jaxpSourcetoXMLInputSource seems to indicate that the Source object is converted by coping it's SystemId
rather than the actual contents of the DOMSource.
Update: My orignal test case above was actually run using my project classpath which actually includes the JAXB 2.2.1 library which in turn pulls in sjsxp 1.0.1. Running on a clean classpath yields:
Exception in thread "main" java.lang.UnsupportedOperationException: Cannot create XMLStreamReader or XMLEventReader from a javax.xml.transform.dom.DOMSource
at com.sun.xml.internal.stream.XMLInputFactoryImpl.jaxpSourcetoXMLInputSource(XMLInputFactoryImpl.java:302)
at com.sun.xml.internal.stream.XMLInputFactoryImpl.createXMLStreamReader(XMLInputFactoryImpl.java:145)
Which fits with @Gary Rowe's answer.
It's somewhat convoluted, but any XQuery implementation that supports the XQJ API (for example Saxon) will allow you to supply a DOM as the input to the query ".", and get the result as an XMLStreamReader. Although there's a lot of heavyweight machinery involved, it should be perfectly efficient.
With Saxon you could also short-circuit the XQuery side of things using something like
Document doc; // the DOM document
XMLStreamReader reader = new PullToStax(PullProvider.makePullProvider(new DocumentWrapper(doc));
but I think the XQJ approach is cleaner.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With