Project

Profile

Help

Serializing XdmValue as a part of SAX stream

Added by Anonymous over 15 years ago

Legacy ID: #5738927 Legacy Poster: David Lee (daldei)

S9API V9 (something - how do I tell?) My "leading question" is "whats the best way to create a document that is composed of manualy created elements as well as XdmValue nodes. To attempt this I am trying using SAX (Via TransformerHandler). The result I want is like this <options> <option name="name"> { some XdmValue content } </option> <option .... > </options> I have a set of XdmValue objects already created (using xpath or xquery or explicitly as string using XdmValue methods) and I want to create the above document. To try that I'm trying the following ... alternate approachs welcome, but I think this exposes a problem in S9API or atleast a lack of feature ... or maybe a lack of my understanding ------------------ TransformerHandler hd = getStdout().asTransformerHandler(); AttributesImpl attrs = new AttributesImpl(); hd.startDocument(); hd.startElement("", kROOT, kROOT, attrs); for( OptionValue option : options ){ AttributesImpl oatt = new AttributesImpl(); oatt.addAttribute("", "name", "name", "CDATA", option.getOption().name ); hd.startElement("", kOPTION, kOPTION, oatt); XValue value = option.getValue(); value.serialize(hd); hd.endElement("", kOPTION, kOPTION); // CRASH HERE } hd.endElement("", kROOT, kROOT); hd.endDocument(); ------------------ For reference, XValue simply wraps an XdmValue and the serialize method looks like this: ( member mValue is an XdmValue ) ------------- public void serialize(ContentHandler content) throws UnsupportedEncodingException, IOException, SaxonApiException { Shell.getProcessor().writeXdmValue( mValue, new SAXDestination(content)); } ------------ Debugging into this , it appears that Processor.writeXdmValue under the hood assumes that it is serializing a full document and calls startDocument() and endDocument(). When it returns the "level" is set to -1 and the endElement above is crashing out because the document is closed. Is there a way to write out the XdmValue without it assuming its an entire document ? Considering the value comes from Saxon libraries in various ways (xquery,xpath, explicit) if this isnt possible, can you recommend an API where I can manually construct at tree and "insert" an XdmValue into it ? ( then serialize the entire tree). This simplistic case I could do as pure text ... but in more complex cases I want to "insert" a XdmValue into some arbitrary complex document output. My next resort, which I've done in another bit of code, is to use XQuery and put the value in as variables. That seems a little overkill but I cant think of another way that would work.


Replies (5)

Please register to reply

RE: Serializing XdmValue as a part of SAX stream - Added by Anonymous over 15 years ago

Legacy ID: #5739220 Legacy Poster: Michael Kay (mhkay)

s9api is intended primarily as an interface to XSLT, XQuery, and XPath processing, not as a completely general-purpose XML API. So the fact that you can't do this isn't necessarily something I would regard as a deficiency. writeXdmValue() does indeed write a complete document, it's not intended to insert a node into an existing SAX stream. To achieve that, you'll probably have to drop into lower level interfaces. You can get the NodeInfo that underpins the s9api XdmValue. This has a copy() method which sends events to a Receiver, which could be a ContentHandlerProxy that wraps a SAX ContentHandler. This should work, as far as I can see, but I have to say it isn't tested for writing a partial document in the way you want to do. But give it a try.

RE: Serializing XdmValue as a part of SAX stream - Added by Anonymous over 15 years ago

Legacy ID: #5739823 Legacy Poster: David Lee (daldei)

Thanks for the suggestion. I think I'm going down a dead end though so I'll do it some other way like using XQuery or maybe using DOM. I did get this code "running but not working": I started getting Null ptr crashes deep within saxon, (first with missing attribtes), and trying to fix them just led to more crashes ... (null receivers ...) so I dont think its a very good way to go. I think I am trying to force behaviour that just wasnt designed to work from the outside like I want. Thats ok, thanks for the suggestion, I'll work approach it some other way ... As for S9API being a "general purpose XML API". In a differnt project I'm using XdmNode natively as a source of a document and parsing the entire document using getAttribute() and iterateAxis methods. It seems to be working OK. I debated using a DOM wrapper so I could use DOM instead but this seems to work. I'm I fighting uphill on this ? Would you suggest I actually use DOM over XdmNode to do things like walk the entire tree ? I've not run into any big problems yet. -david public void serialize(ContentHandler content) throws UnsupportedEncodingException, IOException, SaxonApiException, XPathException, SAXException { ValueRepresentation v = mValue.getUnderlyingValue(); if (v instanceof Value) { Value value = (Value)v; String s = value.getStringValue(); content.characters(s.toCharArray() , 0 , s.length()); } else { NodeInfo node = (NodeInfo)v; ContentHandlerProxy proxy = new ContentHandlerProxy(); proxy.setUnderlyingContentHandler(content); proxy.setPipelineConfiguration(Shell.getProcessor().getUnderlyingConfiguration().makePipelineConfiguration()); node.copy( proxy ,NodeInfo.LOCAL_NAMESPACES, false, 0); } }

RE: Serializing XdmValue as a part of SAX stream - Added by Anonymous over 15 years ago

Legacy ID: #5739992 Legacy Poster: David Lee (daldei)

I ran into a releated problem. My next strategy is to wrap the XdmNode into a DOM Node and then put that into a DOM tree I created explicitly outside of Saxon. The code I'm using for this is :(simplified) Document doc = ... (created Document with DocumentBuilder.newDocument) Node node = NodeOverNodeInfo.wrap( (NodeInfo)mValue.getUnderlyingValue() ); Node importedNode = doc.importNode(node,true); ---- I get a NullPointer crash in xerces at this line : boolean domLevel20 = source.getOwnerDocument().getImplementation().hasFeature("XML", "2.0"); ----------- My guess is that getOwnerDocument() or getImplementation is returning NULL when the node is wrapped from a Saxon value. Any suggestions on how to convert a saxon NodeInfo into a w3c Node for insertion into a w3c Document ? Thanks for any suggestions. -David

RE: Serializing XdmValue as a part of SAX stream - Added by Anonymous over 15 years ago

Legacy ID: #5740244 Legacy Poster: Michael Kay (mhkay)

>I started getting Null ptr crashes deep within saxon, (first with missing attribtes), and trying to fix them just led to more crashes ... Well, there are lots of things you might have done wrong. When you're using this level of interface, you need to be prepared to do a bit of debugging. If you get an NPE, it's probably because you failed to initialize something that needs to be initialized, and unless you can tell be exactly what you did and exactly how it failed, I really can't help you much. >As for S9API being a "general purpose XML API". In a differnt project I'm using XdmNode natively as a source of a document and parsing the entire document using getAttribute() and iterateAxis methods. It seems to be working OK. I think the essentials for navigating around the document are probably there. >---- I get a NullPointer crash in xerces at this line : boolean domLevel20 = source.getOwnerDocument().getImplementation().hasFeature("XML", "2.0"); I can't immediately see why that should be, please supply a repro that I can use for debugging. One possibility is that the XdmNode you started with isn't part of a document, in which case getOwnerDocument() returns null (or actually, it might even throw an NPE).

RE: Serializing XdmValue as a part of SAX stream - Added by Anonymous over 15 years ago

Legacy ID: #5740418 Legacy Poster: David Lee (daldei)

I can still provide a test case if you are interested, but your last comment sent me down the path ... It is true the node wasnt part of a document. arg. The node was created with an xquery expreesion "<foo/>" which (obviously in hindsight) isnt part of a document. I keep forgetting that nodes can be created that are not part of a document and that screws things up. I changed the expression to "document { <foo/> }" and that lead to another crash (also obvious in hindsight) ---- quote NOT_SUPPORTED_ERR: The implementation does not support the requested type of object or operation. org.w3c.dom.DOMException: NOT_SUPPORTED_ERR: The implementation does not support the requested type of object or operation. ---- quote Finally changing the expression to : "document { <foo/> }/node()" Actually worked !!!! prety archane syntax but It does point out the problem (in my code, not saxon's). So I think the saxon code is working "as designed" its just I am using it in ways that ouside-the-scope of how the XML API's were intended ... Given this I find this whole document vs not-document thing vastly confusing ... its not saxon in particular, but the whole concept that something like xquery (possibly xslt?) can produce element results that are not part of documents ... I think there is some fundimental concept I'm either deeply missing or deeply misusing where I wish to pass around elements reguardless of if they were part of documents that seems to sometimes work great and sometimes fail miserably. Anyway thanks as always for your help. -David

    (1-5/5)

    Please register to reply