Project

Profile

Help

XdmNode toString, Processor.writeXdmValue prb

Added by Anonymous over 15 years ago

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

This is a more subtle problem then usual as I am integrating 2 S9API based applications (calabash + xmlsh) so finding the exact culprit is more difficult. Any hints as to where to look appreciated. I am getting an XdmNode that was built with TreeBuilder dynamically which includes a namespace'd attribute. If I run either toString() or Processor.writeXdmValue() on this node then the output includes the prefix but not the xmlns declaration. Example: <document> <title test:foo="bar">Some Title</title> <para>Some paragraph.</para> </document> But if I run an XQuery of "." to the same destination then it fixes up the output as: <?xml version="1.0" encoding="UTF-8"?> <document> <title xmlns:test="http://test.com" test:foo="bar">Some Title</title> <para>Some paragraph.</para> </document> So I know that the namespace is declared somewhere or xquery wouldnt find it. The XQuery code that works is (snippet) Processor qtproc = runtime.getProcessor(); XQueryCompiler xqcomp = qtproc.newXQueryCompiler(); XQueryExecutable xqexec = xqcomp.compile("."); XQueryEvaluator xqeval = xqexec.load(); xqeval.setContextItem(result); Serializer serializer = new Serializer(); serializer.setOutputStream(port.asOutputStream()); xqeval.setDestination(serializer); xqeval.run(); But if I take the context (result) and simply do either result.toString() or qtproc.writeXdmValue( result , serializer ) ; then the result doesnt include the xmlns attribute. Any clues where to look for this problem ? I can provide full source but its fairly complex (requires installing 3 projects), I'm not sure If I can issolate the problem down to a small test case. Thanks for any suggestions. -David


Replies (2)

RE: XdmNode toString, Processor.writeXdmValue prb - Added by Anonymous over 15 years ago

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

This is 9.1.0.6, right? The first thing I notice is that XdmNode.toString() and Processor.writeXdmValue() are actually different code. The first one seems to use a pipeline with no NamespaceReducer, while the second one inserts a NamespaceReducer. The NamespaceReducer's job is to perform namespace fixup - generating any missing namespace declarations and removing duplicates. The second thing I notice is that the NamespaceReducer doesn't actually look at attribute nodes - that is, it doesn't perform namespace fixup in respect of namespaced attribute names. That should presumably be done elsewhere. I don't think it should normally be necessary to perform namespace fixup while serializing - the namespaces should already be present in the tree (they are needed to support the namespace axis). So this is a belt-and-braces strategy anyway. The real questions are (a) does the tree contain the namespace declaration, and (b) if not, why not. The answer to (a) is almost certainly "no", but it might be useful to check. If the underlying node is a TinyNodeImpl you could navigate to the TinyTree and call diagnosticDump() on it. Or you could probe it by navigating the Namespace axis. I suspect the namespace isn't there, in which case the question is (b) why not; so we'll need to look at the process that built the tree. The process that creates a namespace node on behalf of a namespaced attribute appears to be the ComplexContentOutputter. If you write a tree without a ComplexContentOutputter on the pipeline, then it's your responsibility to call namespace() before or after writing a namespaced attribute.

RE: XdmNode toString, Processor.writeXdmValue - Added by Anonymous over 15 years ago

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

Definitely on the right track thanks ! Here's the diag dump of the offending element: Tree containing node 3 node type depth next alpha beta name 0 9 0 -1 0 0 -1 1 1 1 0 -1 1 1925 document 2 3 2 3 0 7 -1 3 1 2 5 0 -1 1993 title 4 3 3 3 7 10 -1 5 3 2 6 17 7 -1 6 1 2 8 -1 -1 1276 para 7 3 3 6 24 15 -1 8 3 2 1 39 5 -1 9 11 0 -1 0 0 -1 attr parent name value 0 3 1049897 bar ns parent prefix uri 0 0 1 1 1 1 1 1 I'm not sure how to interpret this. This appears to be the code that adds the namespace'd attribute: public void addAttribute(QName attrName, String newValue) { int nameCode = pool.allocate(attrName.getPrefix(),attrName.getNamespaceURI(),attrName.getLocalName()); int typeCode = StandardNames.XS_UNTYPED_ATOMIC; try { receiver.attribute(nameCode, typeCode, newValue, 0, 0); } catch (XPathException e) { throw new XProcException(e); } } Where receiver was constructred like this : exec = new Executable(controller.getConfiguration()); destination = new XdmDestination(); receiver = destination.getReceiver(controller.getConfiguration()); PipelineConfiguration pipe = controller.makePipelineConfiguration(); pipe.setLocationProvider(xLocationProvider); receiver.setPipelineConfiguration(pipe); -------- I added a a ComplexContentOutputter to the Serialization step instead of a NamespaceReducer and voila the output is right: Here's my new serilize method that works with this case : public void writeXdmValue(XdmValue value, Destination destination) throws SaxonApiException { try { Receiver out = destination.getReceiver(runtime.getProcessor().getUnderlyingConfiguration()); ComplexContentOutputter out2 = new ComplexContentOutputter(); out2.setPipelineConfiguration(runtime.getProcessor().getUnderlyingConfiguration().makePipelineConfiguration()); out2.setReceiver(out); TreeReceiver tree = new TreeReceiver(out2); tree.open(); tree.startDocument(0); for (Iterator<XdmItem> it = value.iterator(); it.hasNext();) { XdmItem item = it.next(); tree.append((Item)item.getUnderlyingValue(), 0, NodeInfo.ALL_NAMESPACES ); } tree.endDocument(); tree.close(); } catch (XPathException err) { throw new SaxonApiException(err); } } My question is this : Should I put a Fence on the Hill or an Ambulance in the Valley ? That is, is there something wrong with the creation of the original attribute ? or is this something that the serialize should handle ? If the former then I will work on getting that code fixed, if the later then I suggest both Processer.writeXdmValue() and XdmValue.toString() should be fixed. (?) Thanks for your help ! -David

    (1-2/2)

    Please register to reply