views:

672

answers:

2

Hey,

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

A: 

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.

alamar
A: 

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()
alamar