Domanda

Sto usando una funzione che assume due elementi Dom - genitore e figlio da diversi documenti.Importiamo l'elemento figlio, trasformalo, quindi aggiungerlo all'elemento principale.Ma l'ultima riga nel seguente codice sta lanciando un'eccezione DOM: org.w3c.dom.domexception: errato_document_err: un nodo viene utilizzato in un documento diverso da quello che lo ha creato.

Si prega di consultare il mio codice qui sotto:

    public void attachNodeToParent (Element parent, Element child) throws Exception {
        Document parent_doc = parent.getOwnerDocument();
        child = (Element)parent_doc.importNode(child, true);
// Imported child Element is shown below:
//      <node id="101">
//        <node id="102">
//          <node id="103" />
//        </node>
//        <node id="104">
//          <node id="103" />
//        </node>
//      </node>

        // convert child Element into String
        Source source = new DOMSource(child);
        StringWriter stringWriter = new StringWriter();
        Result result = new StreamResult(stringWriter);
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer();
        transformer.transform(source, result);
        String childXml = stringWriter.getBuffer().toString();


        // Recursively modify the id attributes of every node
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new InputSource(new StringReader(childXml)));
        XPathFactory xpathFactory = XPathFactory.newInstance();
        XPath xpath = xpathFactory.newXPath();
        NodeList nodes = (NodeList) xpath.compile("//node[@id]").evaluate(doc, XPathConstants.NODESET);
        for (int nodeNumber = 0; nodeNumber < nodes.getLength(); ++nodeNumber) {
            final Element node = (Element) nodes.item(nodeNumber);
            final String nodeId = node.getAttribute("id");
            final String newNodeId = "prefix/" + nodeId;
            node.getAttributeNode("id").setValue(newNodeId);
        }


        final StringWriter writer = new StringWriter();
        transformer.transform(source, new StreamResult(writer));
        writer.flush();
        writer.close();
        String transformedChildXml = writer.toString();

        // Prase transformedChildXml String into XML
        dbf.setNamespaceAware(true);
        DocumentBuilder builder = dbf.newDocumentBuilder();
        Document document = builder.parse(new InputSource(new StringReader(transformedChildXml)));
        document.setXmlStandalone(false);
        child = document.getDocumentElement();

        // child Element is now transformed to:
//        <node id="prefix/101">
//          <node id="prefix/102">
//            <node id="prefix/103" />
//          </node>
//          <node id="prefix/104">
//            <node id="prefix/103" />
//          </node>
//        </node>

        // append transformed child Element to parent Element
        // Throws o rg.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: 
        // A node is used in a different document than the one that created it.
        parent.appendChild(child); 
    }
.

È stato utile?

Soluzione

The short answer is that the child element on the penultimate line belongs to the document created by the line

Document document = builder.parse(new InputSource(new StringReader(transformedChildXml)));

and not the owner document of the parent. So you would have to use importNode again to transfer it to your target document.

But don't do that. Your code has two serialize to String and parse back to Document cycles, which is very inefficient and neither should be necessary. Once you've called importNode at the start, simply fix up the ids in place, and append the child to the parent at the end.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top