JDK-8213117 : adoptNode corrupts attribute values
  • Type: Bug
  • Component: xml
  • Sub-Component: org.w3c.dom
  • Affected Version: 8,11,12
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux_ubuntu
  • CPU: x86_64
  • Submitted: 2018-10-26
  • Updated: 2020-01-29
  • Resolved: 2018-11-28
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 12
11.0.5-oracleFixed 12 b22Fixed
Related Reports
Relates :  
Description
A DESCRIPTION OF THE PROBLEM :
Calling adoptNode will not migrate attribute values correctly. Instead, you get attribute names of the new node, but with attribute values of the old node.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create two documents. Adopt a node from doc2 into doc1. Print doc1. Observe that attribute values are not correctly moved. See code example.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
See source code example
ACTUAL -
See source code example

---------- BEGIN SOURCE ----------
import com.sun.org.apache.xerces.internal.dom.DeferredAttrImpl;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;

public class AdoptNodeBugTest {
        private static final String XML1 = "<root><oldNode oldAttrib1=\"old value 1\" oldAttrib2=\"old value 2\"></oldNode></root>";
        private static final String XML2 = "<root><newNode newAttrib=\"new value\"></newNode></root>";

        public static void main(String argv[]) throws Exception {

            DocumentBuilder builder = DocumentBuilderFactory.newInstance()
                   .newDocumentBuilder();


            Document doc1 = getDocument(builder, XML1);
            Document doc2 = getDocument(builder, XML2);

            Element newNode = (Element) doc2.getFirstChild().getFirstChild();

            //fix1(doc2);    // <- either of these method calls with fix the problem
            //fix2(newNode);

            Element replacementNode = (Element) doc1.adoptNode(newNode);
            System.out.println(replacementNode.getAttributes().getNamedItem("newAttrib").getNodeValue()); // <- unexpected value
            Node oldNode = doc1.getFirstChild().getFirstChild();

            doc1.getDocumentElement().replaceChild(replacementNode, oldNode);

            StringWriter sw = new StringWriter();
            Transformer serializer = TransformerFactory.newInstance().newTransformer();
            serializer.transform(new DOMSource(doc1.getFirstChild()), new StreamResult(sw));
            System.out.println(sw.toString()); // <- "old value 2" instead of "new value"
    }

    private static void fix2(Element doc2CElement) {
        DeferredAttrImpl attr = (DeferredAttrImpl) doc2CElement.getAttributes().getNamedItem("newAttrib");
        attr.hasChildNodes(); //This will call synchronizeChildren on the attribute and that fixes it
    }

    private static void fix1(Document doc2) {
        doc2.normalizeDocument();
    }

    private static Document getDocument(DocumentBuilder builder, String xml) throws SAXException, IOException {
                InputStream a=new ByteArrayInputStream(xml.getBytes());
                Document out = builder.parse(a);
                return out;
        }
}


---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
See provided fixes in the source code.

FREQUENCY : always



Comments
Fix Request (11u): This patch is needed to keep up with Oracle 11.0.5. Patch applies cleanly, will be tested in SAP env before pushing.
21-06-2019

To reproduce the issue, run the attached test case: JDK 8u191 - Fail JDK 11.0.1 - Fail JDK 12-ea+16 - Fail Output: openjdk version "12-ea" 2019-03-19 OpenJDK Runtime Environment (build 12-ea+16) OpenJDK 64-Bit Server VM (build 12-ea+16, mixed mode, sharing) old value 2 <?xml version="1.0" encoding="UTF-8"?><root><newNode newAttrib="old value 2"/></root>
30-10-2018