Why DOM Node.replaceChild() method does not work in this use case?

时间:2016-07-11 22:50:48

标签: java dom xpath

I am trying to replace a <div> tag by a <span> tag in a DOM Document created from a XHTML String using theNode.replaceChild method. Both tags have the same style attribute style="color: blue;", but my code just work as expected when I uncomment a useless line of code that access the content of the style attribute. This is my test code:

public class DomTest {

    public static void main(String args[]) throws SAXException, IOException, ParserConfigurationException, XPathExpressionException, TransformerException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        Document doc = dbf.newDocumentBuilder().parse(new InputSource(new StringReader( 
                  "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
                + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
                + "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
                + "    <head>\n"
                + "          <title>Title</title>\n"
                + "    </head>\n"
                + "    <body>\n"
                + "          <div style=\"color: blue;\">Content</div>\n"               
                + "    </body>\n"
                + "</html>")));     

        Element element = dbf.newDocumentBuilder().parse(new InputSource(new StringReader(
                "<span style=\"color: blue;\">content</span>"))).getDocumentElement();

        XPath xPath = XPathFactory.newInstance().newXPath();

        Node parentNode = (Node) xPath.compile("/html[1]/body[1]")
                .evaluate(doc, XPathConstants.NODE);

        Node childNode  = (Node) xPath.compile("/html[1]/body[1]/div[1]")
                .evaluate(doc, XPathConstants.NODE);

        // element.getAttributes().item(0).getNodeValue();

        doc.adoptNode(element);     
        parentNode.replaceChild(element, childNode);

        DOMSource domSource = new DOMSource(doc);       
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();    
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");        
        transformer.transform(domSource, result);               

        System.out.println(writer.toString());      
    }
}

When that line is commented, the style attribute is removed. How to explain this strange behaviour?

Output with line commented:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
          <title>Title</title>
    </head>
    <body>
          <span style="">Content</span>
    </body>
</html>

Output with line uncommented:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
          <title>Title</title>
    </head>
    <body>
          <span style="color: blue">Content</span>
    </body>
</html>

1 个答案:

答案 0 :(得分:2)

这是因为您使用了adoptNode()。您应该使用importNode()代替,例如

Node imported = doc.importNode(element, true);
parentNode.replaceChild(imported, childNode);

参考文献:

https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Document.html#adoptNode-org.w3c.dom.Node-

https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/Document.html#importNode-org.w3c.dom.Node-boolean-