Question

I am using Dom4j to detach a node, like below:

<div name="divName">
    Some Text Here
    <span>Some Text Here</span>
</div>

I am selecting the div node by name and then using the detach method to remove it:

xpathValue = "//*[contains(@name, 'divName')]"
xpath = dom.createXPath(xpathValue)
    if xpath != None:
        nodes = xpath.selectNodes(dom)
        if len(nodes) > 0:
            for node in nodes:
                node.detach()

This seems to remove the div fine, I noticed that it also removes elements and text within that div also. What I am looking to achive is removing the div without removing the elements and text inside the div, resulting in this:

Some Text Here
<span>Some Text Here</span>

Is it possible to achive this with dom4j? If not any suggestions on how to go about this?

Cheers

Eef

Update:

@alamar

I have achived what I wanted by taking your code and editing it a little and this is what I have come up with:

   xpathValue = "//*[contains(@name, 'divName')]"
   xpath = dom.createXPath(xpathValue)
    if xpath != None:
        nodes = xpath.selectNodes(dom)
        if len(nodes) > 0:
            for node in nodes:
                parent = node.getParent()
                nodeContents = node.content()
                    if len(nodeContents) > 0:
                        for subNode in nodeContents:
                            parent.add(subNode.clone().detach())
            node.detach()

This seems to work, but adds the nodes to the end of the parent node in the below situation:

<div name="parent">
    <div name="divName">
        Some Text Here
        <span>Some Text Here</span>
    </div>
    <div name="keep"></div>
</div>

The result is this:

<div name="parent">
    <div name="keep"></div>
    Some Text Here
    <span>Some Text Here</span>
</div>

I am trying to figure out how to get the contents of the removed node to stay in its original position, before thed div named "keep", instead of being added after the div with the name "keep". I have tried a few thing but can not seem achive this, could anyone help?

Eef

Was it helpful?

Solution

If you want to keep the order of elements, you should really ask parent for its content(). In that content (which is a List backed by parent element) collection, you should find your div and replace it with that div's content().

I don't remember idiomatic way to do that in python, frankly.

probably

if xpath != None:
    nodes = xpath.selectNodes(dom)
    if len(nodes) > 0:
        for node in nodes:
            parent = node.getParent()
            index = parent.indexOf(node)
            siblings = parent.content()
            nodeContents = node.content()
                if len(nodeContents) > 0:
                    for subNode in nodeContents:
                        siblings.add(subNode.clone().detach(), index++)
        node.detach()

OTHER TIPS

Try:

if xpath != None:
    nodes = xpath.selectNodes(dom)
    if len(nodes) > 0:
        for div in nodes:
            parent = div.getParent()
            div.detach()
            for(child in node.content())
                child.detach()
                parent.add(child)

I believe it would do the trick.

I.e. after detaching every div, you should reattach every div's child into div's parent.

i had a similar problem and solved it with the following function (works fine for me)

What is it doing: it will simply remove that parent tag and includes every element and node inside the element to the parent at that position.

   private void _replaceTagByContent(Element element) {
        Element parent = element.getParent();
        List elements = parent.elements();
        int insertPosition = elements.indexOf(element);

        // add them all to the parent again
        for (int i = 0, size = elements.size(); i < size; i++) {
            Node node = (Node) elements.get(i);
            if (i == insertPosition) {

                // if we are here, then this has to be an element, since
                // wo do only replace elements ...

                for (int j = element.nodeCount() - 1; j >= 0; j--) {
                    Node theNode = element.node(j);
                    theNode.detach();
                    elements.add(i, theNode);
                }

                // finally remove this node
                elements.remove(node);
            }
        }
    }

enjoy cnsntrk

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top