0

I have an XML file and I need to delete a specific node. The node to be deleted will be defined dynamically based on the logic. I have been searching in internet for a solution but couldn't delete my node still. am getting error - NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist

Below is a sample XML File. I need to delete the node <NameValuePairs> which has <name>Local Variables</name>. Below is my sample XML Files Java Code

Sample XML File

<?xml version="1.0" encoding="UTF-8"?>
<DeploymentDescriptors xmlns="http://www.tibco.com/xmlns/dd">
<name>Test</name>
<version>1</version>
<DeploymentDescriptorFactory>
    <name>RepoInstance</name>
</DeploymentDescriptorFactory>
<DeploymentDescriptorFactory>
    <name>NameValuePairs</name>
</DeploymentDescriptorFactory>
<NameValuePairs>
    <name>Global Variables</name>
    <NameValuePair>
        <name>Connections1</name>
        <value>7222</value>
        <requiresConfiguration>true</requiresConfiguration>
    </NameValuePair>
    <NameValuePair>
        <name>Connections2</name>
        <value>7222</value>
        <requiresConfiguration>true</requiresConfiguration>
    </NameValuePair>
</NameValuePairs>
<NameValuePairs>
    <name>Local Variables</name>
    <NameValuePair>
        <name>Connections3</name>
        <value>8222</value>
        <requiresConfiguration>true</requiresConfiguration>
    </NameValuePair>
    <NameValuePair>
        <name>Connections3</name>
        <value>8222</value>
        <requiresConfiguration>true</requiresConfiguration>
    </NameValuePair>
</NameValuePairs>
</DeploymentDescriptors>

Java Code

File fDestFile = new File("myfile.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document oDoc3 = dBuilder.parse(fDestFile);
NodeList oDestFlowList = oDoc3.getElementsByTagName("NameValuePairs");
for (int m = 0; m < oDestFlowList.getLength(); m++) {
     NodeList oDestchildList = oDestFlowList.item(m).getChildNodes();
     for (int n = 0; n < oDestchildList.getLength(); n++) {
          Node oDestchildNode = oDestchildList.item(n);
          if ("name".equals(oDestchildNode.getNodeName())) {
             //oDestchildNode.getParentNode().removeChild(oDestchildNode);    //Not Working
             //oDoc3.getDocumentElement().removeChild(oDestchildNode); //Not Working
           }
       }
   }   
 }
pvorb
  • 7,157
  • 7
  • 47
  • 74
Lettisha
  • 21
  • 7

2 Answers2

1

You need create a separate reference from the parent node as an Element so that you aren't referencing the node that you are removing:

File fDestFile = new File("src/myfile.xml");
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = null;
    try {
        dBuilder = dbFactory.newDocumentBuilder();
        Document oDoc3 = null;
        oDoc3 = dBuilder.parse(fDestFile);
        NodeList oDestFlowList = oDoc3.getElementsByTagName("NameValuePairs");
        // Loop through all 'NameValuePairs'
        for (int m = oDestFlowList.getLength()-1; m >=0 ; m--) {
            NodeList oDestchildList = oDestFlowList.item(m).getChildNodes();
            // Loop through children of 'NameValuePairs'
            for (int n = oDestchildList.getLength()-1; n >=0 ; n--) {
                // Remove children if they are of the type 'name'
                if(oDestchildList.item(n).getNodeName().equals("name")){
                    oDestFlowList.item(m).removeChild(oDestchildList.item(n));
                    // For debugging
                    System.out.println(oDestchildList.item(n).getNodeName());
                }
            }
        }   
        Source source = new DOMSource(oDoc3);
        Result result = new StreamResult(fDestFile);
        Transformer transformer = null;
        transformer = TransformerFactory.newInstance().newTransformer();
        // Transform your XML document (i.e. save changes to file)
        transformer.transform(source, result);
    } catch (Exception e) {
        // Catch the exception here
        e.printStackTrace();
    }
}

If you are still having issues, then I would think that it is an issue with the node types. This was working for me before I put the check in for 'oDestchildNode.getNodeType()' but I would look at what type of node you are returning and go from there.

ghg565
  • 422
  • 6
  • 15
  • Thank You for your quick response. I have tried your solution but we cannot assign a node to element. I am getting casting error with line Element node = (Element) oDestchildList.item(i); – Lettisha May 19 '16 at 21:15
  • I am getting casting error after trying the below 2 options Option 1: Element node = (Element) oDestchildList.item(i); Element elemenet = node.getParentNode(); Option 2: Node oDestchildNode = oDestchildList.item(n); Element elemenet = oDestchildNode.getParentNode(); Can someone please help me to fix this up – Lettisha May 19 '16 at 21:34
  • Are you using `org.w3c.dom.Element` class? – ghg565 May 19 '16 at 21:38
  • Yes am using org.w3c.dom.Element. I am not getting any error now but the child element is not getting deleted. The XML is still the same. Not sure what is the problem here – Lettisha May 23 '16 at 06:37
  • This is working for me. I think that your issue is probably that you aren't saving the changes to the document back to the file. I will add that part into the solution. Let me know if it still doesn't work. – ghg565 May 23 '16 at 15:25
  • My requirement is to compare 2 xml files. Remove duplicate nodes from parent and create a new xml file with the changes made. So I have copied the original file and created a new xml. I am now comparing and making the changes in the new xml file. Could be any problem with the new file that is being created? Please let me know if I am missing out something here. – Lettisha May 23 '16 at 20:52
  • I have updated the code to include the changes. I also reversed the order for the iteration so that any removed items won't cause issues with removing child items by index. If you are having issues, I suggest either putting in some debug breakpoints or using some 'System.out' calls to print items to the console. That should help you track down where you are experiencing the issue. – ghg565 May 23 '16 at 21:18
  • Also check out [THIS](http://stackoverflow.com/questions/141993/best-way-to-compare-2-xml-documents-in-java) SO post about comparing xml files. There are some nice available tools for this sort of thing that may work better depending on your particular situation. – ghg565 May 23 '16 at 21:19
  • Thank You much for all your suggestions. I have learnt many new things while working on this. I could finally fix this up by using XPath and some of your points. Using Xpath has drastically reduced the no of lines of code. I have learnt many new things like traversing in reverse order for deletion, using Transformer to save the changes to the file and the link that you have provided is really very useful. Many new points to learn. Thank You so much :) – Lettisha May 24 '16 at 18:25
  • No worries! If you feel I helped you can up-vote my answer :) You don't need to mark it as the answer since you only used it for advice. Also, don't forget to mark your final piece as the answer to close the question. – ghg565 May 24 '16 at 19:05
  • Is there any problem with voting :( I tried doing that. On clicking the Up arrow the vote changes from 0 to 1. But it immediately reverts back to 0. Will try after some time. I have marked my final piece of code as the Answer. – Lettisha May 25 '16 at 05:09
1

Here is the final piece of code that finally worked

public static void main(String[] args) {
    File fXmlSubFile = new File("Sub.xml");
    File fXmlOriginalFile = new File("Original.xml");
    File fDestFile = new File("myfile.xml");
    DocumentBuilderFactory dbFactory  = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder;
    FileChannel source = null;
    FileChannel destination = null;
    XPath xPath =  XPathFactory.newInstance().newXPath();

    try{
        if (!fDestFile.exists()) {
            fDestFile.createNewFile();
        }
        source = new FileInputStream(fXmlOriginalFile).getChannel();
        destination = new FileOutputStream(fDestFile).getChannel();
        if (destination != null && source != null) {
            destination.transferFrom(source, 0, source.size());
        }
        if (source != null) {
            source.close();
        }
        if (destination != null) {
            destination.close();
        }
        dBuilder = dbFactory.newDocumentBuilder();
        Document oSubDoc = dBuilder.parse(fXmlSubFile);
        Document oDestDoc = dBuilder.parse(fDestFile);
        oSubDoc.getDocumentElement().normalize();
        oDestDoc.getDocumentElement().normalize();

         String sDestExpression = "/DeploymentDescriptors/NameValuePairs";  
         String sSubExpression = "/NameValuePairs"; 
         NodeList nodeDestList = (NodeList) xPath.compile(sDestExpression).evaluate(oDestDoc, XPathConstants.NODESET);
         NodeList nodeSubList  = (NodeList) xPath.compile(sSubExpression).evaluate(oSubDoc, XPathConstants.NODESET);
         for (int i = nodeDestList.getLength()-1; i >=0 ; i--) {
            Node oDestNode = nodeDestList.item(i);
            if (oDestNode.getNodeType() == Node.ELEMENT_NODE) {
               Element oDestElement = (Element) oDestNode;
               for (int j =0; j<nodeSubList.getLength(); j++) {
                    Node oSubNode = nodeSubList.item(j);
                    if (oSubNode.getNodeType() == Node.ELEMENT_NODE) {
                       Element oSubElement = (Element) oSubNode;
                       if(oDestElement.getElementsByTagName("name").item(0).getTextContent().equals(oSubElement.getElementsByTagName("name").item(0).getTextContent())){
                        oDestNode.getParentNode().removeChild(oDestNode);
                       }
                    }
               }
            }
         }
         Source src = new DOMSource(oDestDoc);
         Result result = new StreamResult(fDestFile);
         Transformer transformer = null;
         transformer = TransformerFactory.newInstance().newTransformer();
         // Transform your XML document (i.e. save changes to file)
         transformer.transform(src, result);
    }catch(Exception ex){
        System.out.println("error:"+ex.getMessage());
        ex.printStackTrace();
    }
}
Lettisha
  • 21
  • 7