-
Bug
-
Resolution: Fixed
-
P4
-
8, 11, 12
-
b22
-
x86_64
-
linux_ubuntu
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8226398 | 11.0.5-oracle | Joe Wang | P4 | Resolved | Fixed | b02 |
JDK-8227087 | 11.0.5 | Joe Wang | P4 | Resolved | Fixed | b01 |
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
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
- backported by
-
JDK-8226398 adoptNode corrupts attribute values
- Resolved
-
JDK-8227087 adoptNode corrupts attribute values
- Resolved
- relates to
-
JDK-8238164 Update Xerces2 Java to version 2.12.0
- Resolved