Skip to Content.
Sympa Menu

xom-interest - Re: [XOM-interest] A novel approach for writing large XML documents with XOM

xom-interest AT lists.ibiblio.org

Subject: XOM API for Processing XML with Java

List archive

Chronological Thread  
  • From: "Asgeir Frimannsson" <asgeirf AT gmail.com>
  • To: "Wolfgang Hoschek" <wolfgang.hoschek AT mac.com>
  • Cc: xom-interest AT lists.ibiblio.org
  • Subject: Re: [XOM-interest] A novel approach for writing large XML documents with XOM
  • Date: Tue, 23 Oct 2007 10:57:44 +1000

On 10/23/07, Wolfgang Hoschek <wolfgang.hoschek AT mac.com> wrote:
>
> How do this compare to this streaming XOM serializer: http://
> dsd.lbl.gov/nux/api/nux/xom/io/StreamingSerializer.html
> Wolfgang.


I had overlooked this in my search for a streaming serializer, thanks! If
I'd seen this earlier, I would have spent my time this weekend more wisely.

Some quick observations:
- My serializer supports all additional features that
nu.xom.Serializersupports (whitespace handling, Unicode NFC -
including across consequtive
Text nodes, preserve base URI)
- I'm not a very big fan of write[Start|End]Tag, writeXMLDeclaration, etc,
as this is pretty much syntactic sugar, XOM attempt to hide much of this,
and that's what I've tried to do as well...
- My approach enforces parentless "child" nodes, and throws an Exception if
the child node cannot be added to the current context node through
appendChild...
- My approach modifies the original Trees, removing Nodes as they are
written. This is both good and bad...
- write(Element) vs my writeNextChild(Element) - my method doesn't close the
tags, so the new context becomes that last descendant element child,
enabling further addition to the child... Not sure which approach is cleaner
though, but my approach seem to enable a bit easier writing of large
sub-trees, e.g. writing the skeleton Document first, then appending children
to the last descendant of the root element afterwards...
- The code is a lot cleaner in your serializer :)

writeNextChild(Element) could however be easily implemented in your approach
as:

writeStartTag(Element);
foreach child in Element
if(last child && child is element)
writeNextChild(child);
else
write(child);

And similarly, in my approach write(Element) can be written as:
ParentNode context = getContext();
writeNextChild(element);
setContext(context);

There are definitely many was of skinning a cat.

cheers,
asgeir


On Oct 22, 2007, at 1:16 AM, Asgeir Frimannsson wrote:
>
> > Hi all,
> >
> > I wrote a streaming serializer for XOM this weekend, and thought
> > perhaps it
> > might be useful to someone else, so I'll throw it on the list.
> >
> > StreamingSerializer is based on the existing Serializer, however,
> > it is not
> > a subclass of Serializer. It allows for creating very large
> > documents and
> > writing them to an outputstream. The serializer removes any nodes
> > in the
> > Document that is out-of-context (already serialized), and thereby
> > frees up
> > memory.
> >
> > Central to this serializer is the concept of a 'context node', which
> > determines the parent of newly inserted nodes. When inserting
> > Elements, the
> > new context node is always set to the last descendant Element of
> > the element
> > being inserted. Rather than inserting children on Elements (using e.g.
> > appendChild) and creating a large in-memory model, use the
> > writeNextChild()
> > methods of the serializer. Alternatively, create small in-memory
> > Element
> > trees and use the writeNextChild() method on the Element. Start the
> > serialization by calling the write(Document) method. The new
> > context is then
> > set to the last descendant Element of the root element. After that,
> > use the
> > public methods of the StreamingSerializer to build your document.
> >
> > // main api
> > class StreamingSerializer{
> >
> > // sets the new context to the parent context
> > ParentNode popContext()
> >
> > // retrieves the current context node
> > ParentNode getContext()
> >
> > // sets the new context node
> > // must be a parent of the current context node
> > void setContext(ParentNode node)
> >
> > // Serializes a document.
> > // The context node is set to the last
> > // Element descendant of the root element
> > void write(Document)
> >
> > // Serializes an element
> > // The context node is set to the last
> > // Element descendant of the element
> > void writeNextChild(Element)
> >
> > // serializes nodes as children of
> > // the current context node.
> > void writeNextChild(Text)
> > void writeNextChild(Comment)
> > void writeNextChild(ProcessingInstruction)
> >
> > // completes the serialization of the document
> > void finishDocument();
> >
> > }
> >
> > An example application:
> >
> > public static void main(String[] args) throws IOException{
> >
> > StreamingSerializer serializer = new StreamingSerializer
> > (System.out);
> > serializer.setIndent(2);
> > Element root = new Element("root-element");
> > Document doc = new Document(root);
> >
> > serializer.write(doc);
> >
> > Element child = new Element("child");
> >
> > for(int i=0;i<100;i++){ // create a small sub-tree and
> > serialize it
> > serializer.setContext(root);
> >
> > Element childX = new Element(child);
> > childX.addAttribute(new Attribute("id",String.valueOf(i)));
> >
> > if(i%7 == 0){
> > childX.appendChild("I'm one out of 7!");
> > }
> > if(i%9 == 0){
> > childX.appendChild(new ProcessingInstruction("php","echo
> > ('I'm
> > one out of 9..');"));
> > }
> >
> > serializer.setContext(root);
> > serializer.writeNextChild(childX);
> > }
> >
> > serializer.finishDocument();
> > }
> >
> > StreamingSerializerTest passes most tests from the existing
> > SerializerTest,
> > except those where subclassing is used in a Serializer-specific
> > way (most
> > of these are not relevant for StreamingSerializer).
> >
> > I have written two sample applications:
> > - ExampleStreamingWriter - creates an XML document using the
> > streaming
> > serializer (similar to example).
> > - ExampleStreamingIndenter - Streams an XML document through a
> > NodeFactory
> > and writes it out with the streaming serializer indented...
> >
> > Some unresolved issues:
> > - The Serializer calls removeChildren() on Elements. Element
> > subclasses
> > might not allow removal of certain nodes, causing this to break..
> > - Haven't put much thought into use-cases for Subclassing
> > StreamingSerializer, some methods should be declared final for now...
> > - Unit tests doesn't cover the new methods
> >
> > Hope this is useful to someone, and that something similar makes it
> > into the
> > main XOM library some day. There's definitely a need for a streaming
> > serializer in XOM...
> >
> > I've put the code up here:
> > http://camouflage.googlecode.com/files/StreamingSerializer.zip
> > Copy the files to the nu.xom source tree, and it should work.
> >
> > cheers,
> > asgeir
> > _______________________________________________
> > XOM-interest mailing list
> > XOM-interest AT lists.ibiblio.org
> > http://lists.ibiblio.org/mailman/listinfo/xom-interest
>
>




Archive powered by MHonArc 2.6.24.

Top of Page