2

I am trying to remove an element and child elements from an xml file. Specifically appender with the name Testlogging.

First this is how my xml file looks.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="null" threshold="null">

<appender class="DailyLogFileAppender" name="Testlogging">
    <param name="encoding" value="UTF-8"/>
    <param name="MaxFileSize" value="100MB"/>
    <param name="MaxBackupIndex" value="2"/>
    <param name="rootDir" value="c:\Logs"/>
    <param name="componentId" value="Testlogging"/>
    <param name="DatePattern" value="yyyyMMdd"/>
    <layout class="SyslogPatternLayout">
        <param ConversionPattern="%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} [%-5p] {%t} %c [%D] - %m%n"/>
    </layout>
</appender>

Here is my java code:

DocumentBuilderFactory dbfact = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbfact.newDocumentBuilder();
Document d = builder.parse(xmlFile);
        XPath xp = XPathFactory.newInstance().newXPath();
        NodeList nl = (NodeList)xp.compile("//appender").evaluate(d,XPathConstants.NODESET);

        for(int i = 0; i < nl.getLength(); i++)
        {
            if(xp.compile("./@name").evaluate(nl.item(i)).equals("Testlogging"))
            {
                Node node = nl.item(i);
                node.removeChild(nl.item(i));
            }
        }

I would like to remove everything for this appender but an exception is being thrown. It's probably something simple I am missing.

Any ideas?

4
  • What's the exception ? Commented Nov 5, 2015 at 15:31
  • Exception in thread "AWT-EventQueue-0" org.w3c.dom.DOMException: NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist. Commented Nov 5, 2015 at 15:33
  • There seems to be the solution here - stackoverflow.com/questions/3719384/…. You seem to be trying to remove an element by treating it as its own child? Commented Nov 5, 2015 at 15:35
  • Sorry I am still confused on how the code fix would work. How should my code look? Commented Nov 5, 2015 at 15:36

1 Answer 1

6

Well you need to call removeChild on the parent node of the node you want to remove and you need to process the NodeList in reverse order (as W3C DOM collections are "live" collections that can change with any DOM manipulation (https://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#td-live)) so use an approach like

    NodeList nl = (NodeList)xp.compile("//appender[@name = 'Testlogging']").evaluate(d,XPathConstants.NODESET);
    for (int i = nl.getLength() - 1; i >= 0; i--) 
    {
       nl.item(i).getParentNode().removeChild(nl.item(i));
    }
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. That worked. Odd that we need to process it in reverse but It does make sense after thinking about it. Thanks :)
It would be cool if you add why we have to iterate the list in reverse order to your answer. But anyways, it works. Thanks
@GabrielBB, I have added a note and link to the reason, namely "live" DOM collections.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.