Bug #3721
closednet.sf.saxon.tree.linked.ParentNodeImpl.insertChildren
100%
Description
I am attempting to construct am XdmNode tree from Java.
At some point I wish to populate sibling elements in separate threads concurrently, so I do not think the net.sf.saxon.event.Builder approach will work for me.
I therefore have used Linked Tree classes directly. I suppose that using TinyTreeBuilder I could create separate trees and then use TinyTreeBuilder.bulkCopy, which I am exploring now.
However when using LinkedTree classes I found a problem.
If net.sf.saxon.tree.linked.ParentNodeImpl.insertChildren is called for the first time with an Array of child ElementImpl it just copies the array into the children member and does not call cleanUpChildren.
As a consequence the parent and sibling "pointers" are not set. I can set the parent of the children manually, but setting the sibling pointer seems to be a job which is meant to be done by ParentNodeImpl.
So when I serialize the LinkedTree the Serializer goes into infinite recursion.
Attached is a trivial Java program to reproduce the problem. When run without arguments it adds a single child ElementImpl first to the parent, then adds the tail of the array.
When run with the single argument other than 'well' e.g. badly, it adds the child ElementImpls in one go and goes into infinite recursion during serialization.
What is the correct way to create lists of child ElementImpls to avoid this?
Am I approaching things the wrong way?
Would I be better off using TinyTreeBuilder (smaller memory size) and bulkCopy?
Files
Updated by John Francis over 6 years ago
Apologies for making this priority high. Please make it normal
Updated by Michael Kay over 6 years ago
Let me draw your attention to the Javadoc for MutableNodeInfo:
* An extension of the NodeInfo interface defining a node that can be updated. The updating methods are
* closely modelled on the updating primitives defined in the XQuery Update specification, however, their
* semantics should not be assumed to be identical to those primitives.
* <p/>
* <p>These primitives may leave the tree in a state where the type annotations of nodes do not correctly
* describe the structure of the nodes. It is the caller's responsibility to maintain the integrity of
* type annotations.</p>
* <p/>
* <p>This interface was introduced in Saxon 9.1 and modified in Saxon 9.2. It is not yet considered
* 100% stable. Some aspects of the semantics are not clearly specified, for example the effect of each
* operations on namespace bindings, and such details may change in the future. The primary purpose
* of this interface is as an internal interface for use by XQuery Update; applications use it (or
* implement it) at their own risk.</p>
So the effects you observe aren't particularly surprising.
If you want a mutable tree implementation that works with Saxon I would recommend JDOM2 or XOM. Unlike Saxon's linked tree, these have APIs that were designed for public use rather than internal use.
Updated by Michael Kay over 6 years ago
- Category set to Internals
- Assignee set to Michael Kay
- Priority changed from High to Normal
Updated by Michael Kay over 6 years ago
I'm attempting to add the call to cleanUpChildren() in relevant paths.
At present test removeType-valskip-ins-003 is failing with a ClassCastException on one of the added calls.
Updated by Michael Kay over 6 years ago
- Status changed from New to Resolved
- Applies to branch trunk added
- Fix Committed on Branch 9.8, trunk added
Fixed code to call cleanUpChildren() on relevant paths (on 9.8 and trunk). Added new unit test for updating LinkedTree. Regression-tested by running XQuery update tests.
Updated by O'Neil Delpratt over 6 years ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in Maintenance Release 9.8.0.12 added
Bug fix applied in the Saxon 9.8.0.12 maintenance release.
Please register to edit this issue