Project

Profile

Help

Adding a namespace node into MutableNodeInfo

Added by Anonymous over 15 years ago

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

I'm trying to add a namespaced' attribute and its associated xmlns attribute to a MutableNodeInfo. I ALMOST have it working but not quite. I can produce a standalone test (I hope) but maybe this code snipping might uncover something I'm doing thats obviously wrong XdmNode xnode = // an attribute node previously created via XQuery NodeInfo anode = xnode.getUnderlyingNode(); NamePool pool = node.getNamePool(); int nameCode = pool.allocate( anode.getPrefix(), anode.getURI() , anode.getLocalPart() ); node.putAttribute(nameCode, StandardNames.XS_UNTYPED_ATOMIC, anode.getStringValueCS(), 0); int nsCode = pool.allocateNamespaceCode(anode.getPrefix(), anode.getURI()); node.addNamespace(nsCode, false); ============== Given this input Predeclared namespace binding: a=http://foo.bar context: <foo/> xnode attribute {"a:x"}{"xxxx"} Running the above code then serializing with several different methods from Saxon (Serializer, and Processor.writeXdmValue) I get the following output <foo xmlns:fn="http://www.w3.org/2005/xpath-functions" a:x="xxxx"/> So it seems like either a bug in Saxon (unlikely) or a bug in my mind (likely) about how to generate the namespace code. I've also tried : int nsCode = pool.allocateNamespaceCode(nameCode) and it gives the same results. Any suggestions on where to look for this problem ? (saxon 9.1.0.5)


Replies (8)

Please register to reply

RE: Adding a namespace node into MutableNodeInfo - Added by Anonymous over 15 years ago

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

I tried to simulate what you are doing with this code: Configuration config = new SchemaAwareConfiguration(); NamePool pool = config.getNamePool(); config.setTreeModel(Builder.LINKED_TREE); String source = "<foo/>"; DocumentInfo doc = config.buildDocument(new StreamSource(new StringReader(source))); int nameCode = pool.allocate("a", "http://foo.bar/", "x"); int nsCode = pool.allocateNamespaceCode("a", "http://foo.bar/"); MutableNodeInfo elem = (MutableNodeInfo)doc.iterateAxis(Axis.CHILD).next(); elem.putAttribute(nameCode, StandardNames.XS_UNTYPED_ATOMIC, "xxxx", 0); elem.addNamespace(nsCode, true); String s = QueryResult.serialize(elem); System.err.println(s); and it works fine (output is <foo xmlns:a="http://foo.bar/" a:x="xxxx"/>). So I'm going to have to ask you to put together a repro that I can run under the debugger.

RE: Adding a namespace node into MutableNodeInfo - Added by Anonymous over 15 years ago

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

I should mention that I think the most likely explanation is that you've somehow got more than one NamePool in play. But I can't see how that would happen from the fragment of code that you've shown.

RE: Adding a namespace node into MutableNodeInfo - Added by Anonymous over 15 years ago

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

Thanks, that actually gives me some insight ... I'll do some debugging here first. The source document originates as XQuery output from a different Processor instance then is re-built by the new processor ... I may be doing that code wrong. Thanks. -David

RE: Adding a namespace node into MutableNodeInfo - Added by Anonymous over 15 years ago

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

FYI, to answer the obvious question "Why are you mixing 2 Processor instances" ... thats something I've been struggling with. 99% of the use I have only require TinyTree and my tests show it uses 1/3 - 1/2 the memory as Tree (for my tests) but this one tiny, but important case I need a MutableNode ... so I've been trying to "import" a tree created with one model into another model ... obviously without perfect success. I thought I had it right but I guess not. This may end up simply not worth it in the end and I will have to revert to the Tree model throughout. But I am so close :)

RE: Adding a namespace node into MutableNodeInfo - Added by Anonymous over 15 years ago

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

It's perfectly possible to have multiple trees with different tree model implementations under the same Processor. Though I have to confess I'm surprised to discover there is no setTreeModel() method on the DocumentBuilder. However, you can control this by creating an AugmentedSource: Source src = new StreamSource(cccc); AgumentedSource asrc = AugmentedSource.makeAugmentedSource(src); asrc.setTreeModel(Builder.LINKED_TREE); XdmNode doc = documentBuilder.build(arsc); Also, an XdmDestination at present is always a TinyTree. I ought to change that as well to allow the tree model to be controlled. (At the time I introduced s9api, there were no strong reasons for ever using a linked tree, but that has changed with the introduction of Query Update).

RE: Adding a namespace node into MutableNodeInfo - Added by Anonymous over 15 years ago

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

YES ! This works ! FYI, my core problem/misunderstanding was that I started out with an XdmNode from the output of an XQuery (TinyTree model) then tried to convert it to a tree model by using a a builder from a different processor configured for LINKED_TREE, and calling build() on it to produce the new tree. It appeared to work perfectly ... almost ... but under the hood it seems to be doing unexpetected things with the NamePool ... I think allocation of names were done from one Namepool but the serialization was using the other namepool. Using the AugmentedSrc allows me to share the Processor, and hence namepool, for different tree models. I still think the behaviour of my old code could be considered a "bug" but now that I have a way of doing it "the right way" it works great. Thank you !

RE: Adding a namespace node into MutableNodeInfo - Added by Anonymous over 15 years ago

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

>I still think the behaviour of my old code could be considered a "bug" You need to be aware that you are using very low-level interfaces here, you are well out of the comfort zone where methods take responsibility for checking that the caller is doing things that make sense. You're also in territory where I may need to change some of the interfaces: I didn't really think hard about what would happen if people used the MutableNodeInfo methods directly rather than via XQuery Update. I do try to check where I can that nodes all use the same NamePool, but multiple namepools are legal and I can't do much if someone allocates a namecode from one pool and then uses it as if it came from another.

RE: Adding a namespace node into MutableNodeInfo - Added by Anonymous over 15 years ago

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

I agree this is 'scary territory' :) But I think its more subtle then allocating a code from one namepool and using it in another. I allocated and used the namecode from the same namepool but "under the hood" saxon was using a different pool for serilaization then for allocations, due to how I built the tree. But I agree this is not a case where I expect significant support. I'd use XQuery UPdate instead of MutableNodeInfo it it was in SaxonB but for this project (xmlsh, open source) I dont want to force people to use SaxonA for just this one command. If you like i can still produce a standalone test for you that reproduces this problem, now that I know what it is, up to you. I'm happy that I got something to work. -David

    (1-8/8)

    Please register to reply