Skip to main content

how to... transform xmlstreamreader to dom

7 replies [Last post]
minka99
Offline
Joined: 2008-03-27
Points: 0

I have code which creates an XMLStreamReader for an xml file with a dtd.

I want to get a dom for this. Any tried and true methods?

What I ran into:
The DocumentBuilder routines that parse the xml into a dom do not accept
STaXSource or XMLStreamReaders.

So I was using the transform method, using the identity transform, using pipes,
where the source was StaXSource and the output was the pipe.

I was able to get an InputStream this way from the XmlStreamReader, but the transform itself did not like the dtd, because it appears it was calling SAX, so I got parse errors during the transform itself, before I got to the point of parsing the xml into a dom.

That is, the transform gave parse errors, when I used STaXSource.
These were due to the dtd. When I deleted the dtd, no errors. But the problem is,
I cannot do any configuration of the factory for the parsing that is done "under the hood" of the transform, because the parser is not a visible part of the process.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
minka99
Offline
Joined: 2008-03-27
Points: 0

Okay, here is the bug case.

the xml has an internal dtd.







]>


Oberon's Legacy
Corets, Eva

5.95

The 'Load' takes an XMLStreamReader parameter, which
has been created for above xml file.
The code below shows the bug.
The transform() gets the validation error, not the parse().
It gets:

ERROR: 'ParseError at [row,col]:[9,3]
Message: found: DTD, expected START_ELEMENT or END_ELEMENT'

which is expected, but I don't want to get it from the transform(), I want to
get if from the parse().

public void Load(XMLStreamReader p0) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
TransformerFactory xformFactory = TransformerFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Transformer idTransform = xformFactory.newTransformer();
Source input = new StAXSource(p0);
PipedOutputStream ps = new PipedOutputStream();
PipedInputStream is = new PipedInputStream(ps);
Result output = new StreamResult(ps);
idTransform.transform(input, output);
ps.close();
Node n = builder.parse(is);
} catch (TransformerConfigurationException e) {
throw new XmlException(e.getMessage());
} catch (TransformerFactoryConfigurationError e) {
throw new XmlException(e.getMessage());
} catch (IOException e) {
throw new XmlException(e.getMessage());
} catch (TransformerException e) {
throw new XmlException(e.getMessage());
} catch (Exception e) {
throw new XmlException(e.getMessage());
}
}

joehw
Offline
Joined: 2004-12-15
Points: 0

Thanks. But can you also post the part where you created p0? What's the status of that reader before it's passed to the Load method?

minka99
Offline
Joined: 2008-03-27
Points: 0

Okay, this is a complete test for the code I posted above.

I commented out the parse() below, and it still gets a parse error - from the transform().

String xmlDT = " ]> Oberon's Legacy Corets, Eva
5.95
";
XMLInputFactory f = XMLInputFactory.newInstance();
ByteArrayInputStream xml = new ByteArrayInputStream(xmlDT.getBytes());

XMLStreamReader p0 = f.createXMLStreamReader(xml);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
TransformerFactory xformFactory = TransformerFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Transformer idTransform = xformFactory.newTransformer();
Source input = new StAXSource(p0);
PipedOutputStream ps = new PipedOutputStream();
PipedInputStream is = new PipedInputStream(ps);
Result output = new StreamResult(ps);
idTransform.transform(input, output);
ps.close();
//Node n = builder.parse(is);
} catch (Exception e) {
}

joehw
Offline
Joined: 2004-12-15
Points: 0

Hi minka99,

I wonder if you might have hit this bug:
https://sjsxp.dev.java.net/issues/show_bug.cgi?id=15 : Error in applying XSLT Transformer with StaXSource.

Which JDK version are you using? The above bug was integrated into the JDK6 update 3.

Thanks,
Joe

minka99
Offline
Joined: 2008-03-27
Points: 0

This is helpful - it looks like the same bug. However, my input parms are slightly different and I am on this update and it is not fixed :-(.

I did use this workaround, which I think I'll stick with regardless because it doesn't go through a
stax to sax bridge.

I have the XMLStreamReader, in the workaround I create an XMLEventWriter,
then allocate Events from the XMLStreamReader,
write those to the XmlEventWriter
(which is built on an pipe, so I'm writing the output pipe).
Close the output pipe and voila I have my input stream for the DOM parse.

joehw
Offline
Joined: 2004-12-15
Points: 0

I'm sorry the fix didn't work for you. Could you give us some more details, i.e. what're the input params that are different? Better yet, if you could provide some test code or file a bug using the issuetraker https://jaxp.dev.java.net/servlets/ProjectIssues, that would be really helpful for us to track down the bug.

Glad to know if you've found a workaround. I'm curious about the use case. You could have created the DOM document directly from the xml file since you're now getting it using the underlying inputstream instead of a transformer. So what were other needs in your application that required a XMLStreamReader?

Thanks,
Joe

minka99
Offline
Joined: 2008-03-27
Points: 0

I will extract the bug case for you.

I'll answer your other question in an email.
thanks!