views:

494

answers:

5

I'm looking for a way to write a search and replace method using W3C DOM to update a tree. I've thought about doing a breadth-first search as below, but can't think of how to do the in place replacement?

import org.w3c.dom.Node;

private Element tree;

public void searchReplace(Node x, Node y){
    Queue<Node> q = new LinkedList<Node>();
    q.add(tree);
    while (!q.isEmpty()) {
        Node current = q.remove();
        if (current == x){
            // do replacement
        }

        NodeList children = current.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            q.add(children.item(i));
        }
    }
}

I'm only interested in replacing the node name not its value.

A: 

I would have thought that in the bottom part of your method, you should be using:

NodeList children = current.getChildNodes()

instead of x.getChildNodes(), else you're just replacing the tree with x getting into an infinite loop (so long as x has at least one child).

In which case, the replacement part is as simple as

current = y;

If I've misunderstood your approach, let me know, otherwise I can't see why this shouldn't work.

Andrzej Doyle
yes, that was a typo - I'll see if it works
Robert
As I thought, all that does is update which node current is pointing to. So nothing is actually changed.
Robert
A: 

Perhaps its possible with a wrapper api, such as JDom, but even then I'm not sure if that will preserve child element orders (doublefull). You are potentially looking at rolling your own implementation of DOM interfaces.

A: 

To replace an Element, you can use Node#replaceChild(). E.g., to replace current by y you would use

current.getParentNode().replaceChild(y, current)
janko
I get an exception doing that HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
Robert
From the JavaDoc: "HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the newChild node, or if the node to put in is one of this node's ancestors or this node itself."
janko
A: 

Use the XPath class for searching the DOM. For usage understanding see this simple example.

techzen
A: 

To rename a node, there is no need a for a searchReplace() method (since you already have the Node in question), just call renameNode() on the Document in question. eg.

document.renameNode(node, null, "new name");
Robert