Sebastien Ponce wrote:
>
> It seems that a problem appears when cloning an element containing
> attributes. The element an attributes themselves are correctly cloned but
> the resulting attributes return null when calling getOwnerElement, instead
> of the new element.
Which version of Xerces are you using? I can't reproduce the problem
with the latest. I just wrote a small test which seems to say this
operation works just fine...
> This is due to the fact that the implementation of the cloneNode takes care
> to mark cloned attributes as "not owned" since a newly cloned attribute has
> nothing to do with the owner of its model. This is ok but while cloning an
> element, one should take care to mark every attribute as "owned" back and
> puting their owner to the new element.
> This has to be done in org.apache.xerces.dom.ElementImpl.cloneNode(). I
> would thus add there something like :
>
> NamedNodeMap nodemap = getAttributes();
> for (int i = 0; i < nodemap.getLength(); i++) {
> NodeImpl attr = (NodeImpl)nodemap.item(i);
> attr.isOwned(true);
> attr.ownerNode = this;
> }
>
> Could one commiter take care of that ?
This is actually what's done when the map is cloned. Here is the
relevant pieces of code:
ElementImpl:
public Node cloneNode(boolean deep) {
ElementImpl newnode = (ElementImpl) super.cloneNode(deep);
// Replicate NamedNodeMap rather than sharing it.
if (attributes != null) {
newnode.attributes = (AttributeMap)
attributes.cloneMap(newnode);
}
return newnode;
} // cloneNode(boolean):Node
NamedNodeMap:
protected NamedNodeMapImpl(NodeImpl ownerNode) {
this.ownerNode = ownerNode;
}
AttributeMap:
/** Constructs a named node map. */
protected AttributeMap(ElementImpl ownerNode, NamedNodeMapImpl
defaults) {
super(ownerNode);
if (defaults != null) {
// initialize map with the defaults
cloneContent(defaults);
if (nodes != null) {
hasDefaults(true);
}
}
}
public NamedNodeMapImpl cloneMap(NodeImpl ownerNode) {
AttributeMap newmap =
new AttributeMap((ElementImpl) ownerNode, null);
newmap.hasDefaults(hasDefaults());
newmap.cloneContent(this);
return newmap;
} // cloneMap():AttributeMap
/**
* Override parent's method to set the ownerNode correctly
*/
protected void cloneContent(NamedNodeMapImpl srcmap) {
if (srcmap.nodes != null) {
nodes = new Vector(srcmap.nodes.size());
for (int i = 0; i < srcmap.nodes.size(); ++i) {
NodeImpl n = (NodeImpl) srcmap.nodes.elementAt(i);
NodeImpl clone = (NodeImpl) n.cloneNode(true);
clone.isSpecified(n.isSpecified());
nodes.insertElementAt(clone, i);
clone.ownerNode = ownerNode;
clone.isOwned(true);
}
}
} // cloneContent():AttributeMap
--
Arnaud Le Hors - IBM Cupertino, XML Strategy Group