fractalflame
fractalflame

Reputation: 1091

Delete entire node using lxml

I have a an xml document like the following:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>company</groupId>
    <artifactId>art-id</artifactId>
    <version>RELEASE</version>
</parent>

<properties>
    <tomcat.username>admin</tomcat.username>
    <tomcat.password>admin</tomcat.password>
</properties>

<dependencies>
    <dependency>
        <groupId>asdf</groupId>
        <artifactId>asdf</artifactId>
        <version>[3.8,)</version>
    </dependency>
    <dependency>
        <groupId>asdf</groupId>
        <artifactId>asdf</artifactId>
        <version>[4.1,)</version>
    </dependency>
</dependencies>

how can I delete the entire node "dependencies"?

I have looked at other questions and answers on stackoverflow and what is different about is the namespace aspect of this xml, and the other questions ask to delete a subelement like "dependency" while I want to delete the whole node "dependencies." Is there an easy way using lxml to delete the entire node?

The following gives a 'NoneType' object has no attribute 'remove' error:

from lxml import etree as ET

tree = ET.parse('pom.xml')
namespace = '{http://maven.apache.org/POM/4.0.0}'
root = ET.Element(namespace+'project')
root.find(namespace+'dependencies').remove()

Upvotes: 1

Views: 2299

Answers (2)

Joseph LeClerc
Joseph LeClerc

Reputation: 184

First, grab the root node. Since it is <project ... > (vs <project .../>) the "parent" element of dependencies is project. Example from the documentation:

import xml.etree.ElementTree as ET  
tree = ET.parse('country_data.xml')  
root = tree.getroot() 

Once you have the root, check root.tag(), it should be "project".

Then do root.remove(root.find('dependencies')), where root is the project node.

If it were <project .../> then it would be invalid XML since there must be a root element. I can see exactly where you are coming from, though.

Upvotes: 1

Padraic Cunningham
Padraic Cunningham

Reputation: 180411

You can create a dict mapping for your namespace(s), find the node then call root.remove passing the node, you don't call .remove on the node:

x = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>company</groupId>
    <artifactId>art-id</artifactId>
    <version>RELEASE</version>
</parent>    
<properties>
    <tomcat.username>admin</tomcat.username>
    <tomcat.password>admin</tomcat.password>
</properties>    
<dependencies>
    <dependency>
        <groupId>asdf</groupId>
        <artifactId>asdf</artifactId>
        <version>[3.8,)</version>
    </dependency>
    <dependency>
        <groupId>asdf</groupId>
        <artifactId>asdf</artifactId>
        <version>[4.1,)</version>
    </dependency>
</dependencies>
</project>"""
import lxml.etree as et
from StringIO import StringIO

tree = et.parse(StringIO(x))
root =tree.getroot()

nsmap = {"mav":"http://maven.apache.org/POM/4.0.0"}

root.remove(root.find("mav:dependencies", namespaces=nsmap))

print(et.tostring(tree))

Which would give you:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>company</groupId>
    <artifactId>art-id</artifactId>
    <version>RELEASE</version>
</parent>    
<properties>
    <tomcat.username>admin</tomcat.username>
    <tomcat.password>admin</tomcat.password>
</properties>   
</project>

Upvotes: 1

Related Questions