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

Reply via email to