tags:

views:

44

answers:

1

I can copy a node from one XML file to another using "org.w3c.dom.Document.importNode(Node importedNode, boolean deep)"
However, I can't seem to rename the Element I am copying.

I have something like:
File1.xml

<SomeCustomNode randomAttribute="aValue" another="10/10/2010">  
    <Information>  
        <Yellow name="banana"/>  
        <Orange name="orange"/>  
        <Red name="strawberry"/>  
    </Information>  
    <Some>  
        <IgnoredNode/>  
    </Some>  
</SomeCustomNode>  

and something like this:
FileList.xml

<ListOfNodes date="12/10/2010">  
    <aCopy name="fruit" version="10">  
        <Yellow name="banana"/>  
        <Orange name="orange"/>  
        <Red name="strawberry"/>  
    </aCopy>  
    <aCopy name="vegetables" version="3">  
        <Yellow name="sweetcorn"/>  
        <Orange name="carrot"/>  
        <Red name="tomato"/>  
    </aCopy>  
</SomeCustomNode>  

So, what I am doing is taking a node (and the children) from File1.xml and inserting it into FileList.xml but renaming the "Element" and adding a couple attributes to the Element.
Information becomes aCopy name="fruit" version="10"

I am currently using an XPath expression to get the Information node as a NodeList (only 1 result) and then importing that into File2 like so:

Document docFile1 = XMLDocumentStore.getDoc("/path/to/File1.xml");  
Document docFileList = XMLDocumentStore.getDoc("/path/to/FileList.xml");  
NodeList result = XPathAPI.selectNodeList(docFile1.getFirstChild(), ".//Information");  
Node importNode = docFileList.importNode(result.item(0), true);  
// We want to replace aCopy fruit with the updated version found in File1  
NodeList fruitNode = XPathAPI.selectNodeList(docFileList.getFirstChild(), ".//aCopy[@name=\"fruit\"]");  
Node replaceNode = fruitNode.item(0).getParentNode().replaceChild(importNode, fruitNode.item(0)); // probably a better way to do this  
// Now we want to replace the Element name as it is still set to Information  
docFileList.renameNode(replaceNode, null, "aCopy"); // Error: oracle.xml.parser.v2.XMLDOMException: cannot add attribute belonging to another element  

I get other errors if I move the code around a little, things like: cannot remove or replace node it is not a child node of the current node etc.

Would this be better via XSLT? All I'm doing is taking a specific node (and it's sub-nodes) and putting it into another XML file, but replacing the Element name and adding 2 attributes (with values). It would be the same node for each file (File1 ... File###) and would be renamed in the same way, the attribute values are taken from the source file (e.g. File1.xml for my example) and the sub-nodes don't get changed (Yellow, Orange, Red in my example).
Cheers!

+1  A: 

Why are you using an Oracle XML Parser?

If you use the defaults provided by javax.xml you won't get this error:

import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.org.apache.xpath.internal.XPathAPI;

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

    Document docFile1 = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("File1.xml"));
    Document docFileList = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("FileList.xml"));
    NodeList result = XPathAPI.selectNodeList(docFile1.getFirstChild(), ".//Information");
    Node importNode = docFileList.importNode(result.item(0), true);  
    // We want to replace aCopy fruit with the updated version found in File1  
    NodeList fruitNode = XPathAPI.selectNodeList(docFileList.getFirstChild(), ".//aCopy[@name=\"fruit\"]");
    Node replaceNode = fruitNode.item(0).getParentNode().replaceChild(importNode, fruitNode.item(0)); // probably a better way to do this  
    // Now we want to replace the Element name as it is still set to Information  
    docFileList.renameNode(replaceNode, null, "aCopy"); 

    print(docFileList);

}

Prints out:

<ListOfNodes date="12/10/2010">  
    <Information>  
        <Yellow name="banana"/>  
        <Orange name="orange"/>  
        <Red name="strawberry"/>  
    </Information>  
    <aCopy name="vegetables" version="3">  
        <Yellow name="sweetcorn"/>  
        <Orange name="carrot"/>  
        <Red name="tomato"/>  
    </aCopy>  
</ListOfNodes>
dogbane
Hmm, you're right. Seems to be a problem with my imports. Will have to fix that. I've been building up my tool based on an already existing project but I can swap the imports around or fix it just for this one class. Cheers!
Dan2k3k4