Discussion:
[XOM-interest] StaX/DOM/SAX-to-XOM bridge
Dmitry Katsubo
2010-09-14 15:11:49 UTC
Permalink
Dear XOM users!

I want to benefit from quick StaX/DOM/SAX -to- XOM document creation,
but I was not able to locate any way to do so. Actually, my target API I
want to bind with is javax.xml.bind.Marshaller.marshal(), that accepts
javax.xml.transform.Result, org.xml.sax.ContentHandler or
javax.xml.stream.XMLStreamWriter as possible outputs.

Unfortunately, nu.xom.xslt.XOMResult is not visible, so does
nu.xom.XOMHandler. And there is no XMLStreamWriter -to- NodeFactory
bridge. More over I cannot copy XOMHandler to my package, as
Element.setActualBaseURI(), Node.isElement(), etc are not public. Does
it mean I cannot write my own ContentHandler to create XOM document?

The same concerns DOM-to-XOM converters. What I found is only XOM-to-DOM
nu.xom.converters.DOMConverter.

If somebody has ready-to-use adapters, please, share them. At the moment
I found this [1] discussion with this [2] code example, that reads from
javax.xml.stream.XMLStreamReader and creates XOM document.

I would appreciate, if something similar to following code snapshot
would be possible via core XOM:

final nu.xom.xslt.XOMResult result = new nu.xom.xslt.XOMResult(); //
default constructor that creates new NodeFactory() for me
marshaller.marshal(bean, result);
nu.xom.Document doc = result.getDocument();

Any feedback is very welcomed.

[1] http://lists.ibiblio.org/pipermail/xom-interest/2005-August/002563.html
[2]
http://lists.ibiblio.org/pipermail/xom-interest/2005-September/002617.html
--
With best regards,
Dmitry
Tatu Saloranta
2010-09-14 17:07:09 UTC
Permalink
Post by Dmitry Katsubo
I want to benefit from quick StaX/DOM/SAX -to- XOM document
creation,
One alternative would be to adapt existing DOMWrappingWriter from Woodstox (or rather its Stax2 API ref impl, under src/java/org/codehaus/stax2/ri/dom/DOMWrappingWriter.java), which implements Stax XMLStreamWriter to construct DOM document (or fragment).
Creating equivalent for XOM should be relatively straight-forward.

Also, Nux project (http://acs.lbl.gov/software/nux/) has many xom/stax integration pieces so if you haven't yet looked at it, I would suggest doing so.

-+ Tatu +-
Michael Kay
2010-09-14 17:30:53 UTC
Permalink
Nice to see that Nux is back on the air - it seemed to have disappeared
for a while (or moved to a location where it couldn't be found).

The other possibility is to go via Saxon. The code is essentially

StaxBridge stax = new StaxBridge();
stax.setXmlStreamReader(....);
XOMWriter builder = new XOMWriter();
new PullPushCopier(stax, builder).copy();
Document xom = builder.getDocument();

Michael Kay
Saxonica
Post by Tatu Saloranta
Post by Dmitry Katsubo
I want to benefit from quick StaX/DOM/SAX -to- XOM document
creation,
One alternative would be to adapt existing DOMWrappingWriter from Woodstox (or rather its Stax2 API ref impl, under src/java/org/codehaus/stax2/ri/dom/DOMWrappingWriter.java), which implements Stax XMLStreamWriter to construct DOM document (or fragment).
Creating equivalent for XOM should be relatively straight-forward.
Also, Nux project (http://acs.lbl.gov/software/nux/) has many xom/stax integration pieces so if you haven't yet looked at it, I would suggest doing so.
-+ Tatu +-
_______________________________________________
XOM-interest mailing list
XOM-interest at lists.ibiblio.org
http://lists.ibiblio.org/mailman/listinfo/xom-interest
Dmitry Katsubo
2010-09-15 10:41:46 UTC
Permalink
Hello Tatu! Hello Michael!

True, that one can take DOMWrappingWriter as a basis for
XOMXMLStreamWriter. I am not sure I will implement it 100% correct and
optimal when I am looking at XOMHandler implementation.

Michael, I suppose you refer net.sf.saxon.pull.StaxBridge.
Unfortunately, I have no XMLStreamReader in my hands...

Anyway, having in a better integration with other APIs in both
directions is a plus for the library, I think. All APIs became mature
since 2005, but really no significant improvements have been made since
then. Are there any chances it will happen for XOM?
Post by Michael Kay
Nice to see that Nux is back on the air - it seemed to have disappeared
for a while (or moved to a location where it couldn't be found).
The other possibility is to go via Saxon. The code is essentially
StaxBridge stax = new StaxBridge();
stax.setXmlStreamReader(....);
XOMWriter builder = new XOMWriter();
new PullPushCopier(stax, builder).copy();
Document xom = builder.getDocument();
Michael Kay
Saxonica
Post by Tatu Saloranta
Post by Dmitry Katsubo
I want to benefit from quick StaX/DOM/SAX -to- XOM document
creation,
One alternative would be to adapt existing DOMWrappingWriter from
Woodstox (or rather its Stax2 API ref impl, under
src/java/org/codehaus/stax2/ri/dom/DOMWrappingWriter.java), which
implements Stax XMLStreamWriter to construct DOM document (or fragment).
Creating equivalent for XOM should be relatively straight-forward.
Also, Nux project (http://acs.lbl.gov/software/nux/) has many xom/stax
integration pieces so if you haven't yet looked at it, I would suggest
doing so.
-+ Tatu +-
--
With best regards,
Dmitry
Elliotte Rusty Harold
2010-09-15 11:13:34 UTC
Permalink
Post by Dmitry Katsubo
Dear XOM users!
I want to benefit from quick StaX/DOM/SAX -to- XOM document creation,
but I was not able to locate any way to do so. Actually, my target API I
want to bind with is javax.xml.bind.Marshaller.marshal(), that accepts
javax.xml.transform.Result, org.xml.sax.ContentHandler or
javax.xml.stream.XMLStreamWriter as possible outputs.
SAX and DOM are supported. StAX and Trax are not. StAX never really
took off, and Trax is severely underspecified. It's a classic example
of how not to do inheritance. Essentialy the supertypes
javax.xml.transform.Source and javax.xml.transform.Result are
useless. You have to cast to the subtypes and then use their methods
to get anything done, and you have to know the subtypes you support in
advance.

What you need to do is marshal straight to an output stream that is
fed into a Builder. Something like

ByteArrayOutputStream out = new ByteArrayOutputStream();
marshaller.marshal(bean, out);
out.close();
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Builder builder = new Builder();
nu.xom.Document doc = builder.build(in);

You could even do this with piped streams in two threads if you're
concerned about the memory footprint of serializing the entire
document into a string.

If this were a common need, I could think about adding support for
doing this directly through a ContentHandler. off the top of my head,
I think you're the first person to ask for it, and JAXB is the first
API I've noticed that used content handlers like this. Usually I look
for at least two different use cases from two or more people before
adding something to the API.
--
Elliotte Rusty Harold
elharo at ibiblio.org
Dmitry Katsubo
2010-09-15 18:14:25 UTC
Permalink
Hi Elliotte!

Thank you for your reply.
Post by Elliotte Rusty Harold
SAX and DOM are supported.
OK, how can I create org.xml.sax.ContentHandler implementation, that
generates XOM tree? OK, I see your answer below...
Post by Elliotte Rusty Harold
Essentialy the supertypes javax.xml.transform.Source and
javax.xml.transform.Result are useless. You have to cast to the
subtypes and then use their methods to get anything done, and you
have to know the subtypes you support in advance.
Yes, I agree with you, that handling of Source/Result classes for
concrete DOM implementation is troublesome and may look ugly. But as
consumer of this API, if target API supports Trax, it really saves me
time and abates the headache. For example, I have a service, that does
something and serializes the XML. In painful case I have:

doSomethingAndSerialize(OutputStream os);
doSomethingAndSerialize(Writer w);
doSomethingAndSerialize(File f);
doSomethingAndSerialize(Node n);
... and so on ...

All these methods I need to put to interface, forward the call (maybe
with minor code) to target API. Also these calls need to be covered by
Utils tests, even though it is simple. All together simply takes time.
And having javax.xml.transform.Result in my hand I announce only one API
call:

doSomethingAndSerialize(Result r);

and all wrappers are in place. Or I need to re-implement a wheel and
write my own implementations, similar to javax.xml.transform.Result
class hierarchy, to wrap / unwrap all kind of targets.

Maybe I do something totally wrong...
Post by Elliotte Rusty Harold
What you need to do is marshal straight to an output stream that is
fed into a Builder. Something like
ByteArrayOutputStream out = new ByteArrayOutputStream();
marshaller.marshal(bean, out);
out.close();
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Builder builder = new Builder();
nu.xom.Document doc = builder.build(in);
You could even do this with piped streams in two threads if you're
concerned about the memory footprint of serializing the entire
document into a string.
I did it at the moment via org.w3c.dom DOM, e.g. JAXB->DOM->XOM. I don't
have big XMLs, so I don't worry about garbage collector.
Post by Elliotte Rusty Harold
If this were a common need, I could think about adding support for
doing this directly through a ContentHandler.
I am curious (just for my self-education), what are the other ways to
build SAX bridges? Do you have any other API to demonstrate?
Post by Elliotte Rusty Harold
Off the top of my head, I think you're the first person to ask for
it, and JAXB is the first API I've noticed that used content handlers
like this. Usually I look for at least two different use cases from
two or more people before adding something to the API.
OK, of course there should be a real need. Anyway, making XOMHandler /
XOMResult /XOMSource public classes is generally a not bad idea. The
code is there, why not to allow to re-use it?
--
With best regards,
Dmitry
Loading...