How do I remove all selected nodes from an XPath?

13,546

Solution 1

for each node in the returned NodeList:

n.getParentNode().removeChild(n);

Solution 2

I don't understand why the returned nodelist's nodes are returning null for parentNode().

But you could try first selecting all the parents of the nodes you want to remove, with this XPath expression:

"/list/member/friendlist[friend[.='0003']]"

or the equivalent,

"/list/member/friendlist[friend = '0003']]"

Then iterate through the resulting nodelist, and in the context of each one, query for nodes matching the XPath expression

"friend[.='0003']"

That will give you a parent node and a child node to use with removeChild().

Solution 3

Have a look on XUpdate. It's not pretty, but it works.

Share:
13,546
Carven
Author by

Carven

Updated on June 12, 2022

Comments

  • Carven
    Carven about 2 years

    I run an XPath in Java with the following xml and code:

    <?xml version="1.0" encoding="UTF-8"?>
    <list>
        <member name="James">
            <friendlist>
                <friend>0001</friend>
                <friend>0002</friend>
                <friend>0003</friend>
            </friendlist>
        </member>
        <member name="Jamie">
            <friendlist>
                <friend>0003</friend>
                <friend>0002</friend>
                <friend>0001</friend>
            </friendlist>
        </member>
        <member name="Katie">
            <friendlist>
                <friend>0001</friend>
                <friend>0003</friend>
                <friend>0004</friend>
            </friendlist>
        </member>
    </list>
    

    Code:

    try {
        XPath xpath = XPathFactory.newInstance().newXPath();
        XPathExpression pathExpr = xpath.compile("/list/member/friendlist/friend[.='0003']");
    } catch (XPathExpressionException e) {
    

    Of course there are more codes after this but I didn't paste it here because it thought it may confuse even more.

    But the idea is I wish to select all the friend nodes that have the ID 0003 from all the members' friendlist nodes, and then remove it from the XML file. The XPath works by selecting all the "friend" nodes that have the value=0003. I know I can use the removeChild() method of the XML Document object. But the problem is how do I remove all of it directly, without going through layers of loops starting from its parent? The removeChild() method needs me to know its parent's parent's parent.

    Thanks!

    Update: This is how I used my XPath:

    XPath xpath = XPathFactory.newInstance().newXPath();
    XPathExpression pathExpr = null;
    try {
        pathExpr = xpath.compile("/list/member/friendlist/friend[.='0003']");
    } catch (XPathExpressionException e) {
        e.printStackTrace();
    }
    NodeList list = null;
    try {
        list = (NodeList) pathExpr.evaluate(xmlDoc, XPathConstants.NODESET);
    } catch (XPathExpressionException e) {
        e.printStackTrace();
    }
    

    The xmlDoc is an XML document object that has an XML file parsed. The XML works fine. It is only the XML not returning a reference but a whole new nodelist, which makes it impossible for me to refer back to its original xml document to do amendments.

    • jtahlborn
      jtahlborn about 13 years
      is xmlDoc a org.w3c.Document object?
    • Carven
      Carven about 13 years
      Yes, xmlDoc is a regular org.w3c.Document object.
    • jtahlborn
      jtahlborn about 13 years
      are you using the xpath support from the jdk, or some other third-party library? (e.g. what is the actual classname of your XPath instance)
    • Carven
      Carven about 13 years
      I am using the xpath from the JDK. I never use any third party library. The class path for my XPath instance is javax.xml.xpath.XPath.
    • jtahlborn
      jtahlborn about 13 years
      no, not the public api, i mean the actual implementation class (e.g. xpath.getClass())
    • Carven
      Carven about 13 years
      I think I figured out what has happened. jtahlborn is right and his method works. The reason I got a null is because so happen that when I try to get a node whose parent is the main root node of the whole document, it gives a null document. But that's ok because after some trial and error, as long as I create one more level of dummy node on the list to get it down one level, I can get a valid parent to remove it. Thanks!
  • Carven
    Carven about 13 years
    Apparently, when I do a n.getParentNode(), it returns an empty xml. So when I do n.getParentNode().removeChild(n), I will get a nullpointerexception because for some reason the getParentNode() returns a null value. It appears that the Xpath returns another set of xml data and is not making reference to the actual xml document object. Is there anything I have to do to get this work? Thanks!
  • jtahlborn
    jtahlborn about 13 years
    @xEnOn - well, seeing as you have not included any relevant code, it's kind of hard to give much further advice...
  • Carven
    Carven about 13 years
    On most usual xml codes that does the standard procedures from an XML document object, the n.getParentNode().removeChild(n) method works perfectly. It is only when I query a list of nodes through XPath from the XPathFactory, the factory class seems to return a new node list of nodes that I have queried instead of references to the the original nodes in the original XML document object. Therefore, when I use n.getParentNode(), the returned data is incorrect and the removeChild will not work properly.
  • jtahlborn
    jtahlborn about 13 years
    @xEnOn - how are you calling the xpath
  • Carven
    Carven about 13 years
    I have updated my question with how I called the xpath at the bottom of the post. Thanks for any help.
  • Carven
    Carven about 13 years
    Thanks! I tried your method too and it works too! Clever trick!