Convert Java w3c to XMLStreamReader

I would like to reuse some existing code in our code base that accepts XMLStreamReader my application has the necessary data in the form of a w3c document.

The following example is a minimal 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 look something like this: NextTag:Groups , but instead, the following is called:

 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.

Additional Information: The ZephyrParserFactory # jaxpSourcetoXMLInputSource source seems to indicate that the Source object is converted by copying its SystemId , and not the actual contents of the DOMSource.

Update:. My orignal test case was actually launched using my path to the project class, which actually includes the JAXB 2.2.1 library, which in turn pulls in sjsxp 1.0.1. Running on a clean class path 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 is suitable for @Gary Rowe's answer.

+4
source share
5 answers

This is somewhat confusing, but any XQuery implementation that supports the XQJ API (such as Saxon) will allow you to provide the DOM as input to the request. " and get the result as an XMLStreamReader. Despite the fact that many heavy vehicles are involved, it should be ideally efficient.

With Saxon, you can also short-circuit the side of XQuery 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.

+2
source

It seems to me that DOMSource not an instance of StreamSource , therefore it is pushed.

+1
source

My pragmatic solution was to output the Document to a byte array using ByteArrayOutputStream and then pass it back when using ByteArrayInputStream

 Transformer xformer = TransformerFactory.newInstance().newTransformer(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); StreamResult out = new StreamResult(outputStream); xformer.transform(source, out); reader = xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(outputStream.toByteArray())); 

This is not very, but it works.

+1
source

I encountered the same error (Windows 7 / Oracle JDK 7) using the following code:

 DOMSource domSource = new DOMSource(element); XMLEventReader parser = XMLInputFactory.newInstance().createXMLEventReader(domSource); 

I fixed it by adding a new Woodstox dependency:

 <dependency> <groupId>org.codehaus.woodstox</groupId> <artifactId>woodstox-core-lgpl</artifactId> <version>4.1.5</version> </dependency> 

But this is also an unpleasant decision.

+1
source

Woodstox provides exactly what you need with the WstxDOMWrappingReader class. See Javadoc at https://fasterxml.imtqy.com/woodstox/javadoc/5.0/com/ctc/wstx/dom/WstxDOMWrappingReader.html

A small example:

  DOMSource domSource = new DOMSource(node); ReaderConfig config = ReaderConfig.createFullDefaults(); XMLStreamReader reader = WstxDOMWrappingReader.createFrom(domSource, config); 
+1
source

All Articles