0

I need to extract/modify a child element from a .xml file using Python. For this, I am using the xml.etree.ElementTree but I don't get the desired output from my code. I need to extract the element "name" just under "deployment"(in this case xyz1000_Test_v1) from the .xml file:

<?xml version="1.0" encoding="utf-8"?>
<esc
    xmlns="http://www.test.com/esc/esc">
    <tenants>
        <tenant>
            <name>esc</name>
            <deployments>
                <deployment>
                    <name>xyz1000_Test_v1</name>
                    <networks>
                        <network>
                            <name>tenant_1</name>
                            <admin_state>true</admin_state>
                            <subnet>
                                <name>tenant_1_sub</name>
                                <ipversion>ipv4</ipversion>
                                **<address>10.25.0.0</address>**
                            </subnet>
                        </network>
                        <network> .....

This is the code I'm using:

import xml.etree.ElementTree as ET
tree = ET.parse('csr1kv_file.xml')
root = tree.getroot()
ET.register_namespace("","http://www.test.com/esc/esc")

for DeploymentName in root.iter('{http://www.test.com/esc/esc}name'):
    print(DeploymentName.text)
    name.text="New deplaoyment name"

However, out of the code I'm getting the element value under "deployment", "network" and "subnet". How can I access to a specific element? Thanks in advance.

Update:

Trying to get the "name" out of the "network" element, I have this code. Unfortunately, it's not giving me the expected answer:

for network in root.findall('{http://www.test.com/esc/esc}network'):
    name = network.find('name').text
    print(name)
0

1 Answer 1

1

All elements in the document are bound to the same namespace, and the network element is not an immediate child of the root.

With findall(), use this:

for network in root.findall('.//{http://www.test.com/esc/esc}network'):
    name = network.find('{http://www.test.com/esc/esc}name')

Or use iter():

for network in root.iter('{http://www.test.com/esc/esc}network'):
    name = network.find('{http://www.test.com/esc/esc}name')
    if name is not None:  # Avoid "'NoneType' object has no attribute 'text'"
        name.text= 'new name'
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. I went for iter():. But when I try to modify its value I get the following error: "AttributeError: 'NoneType' object has no attribute 'text'". To change the name I'm simply using: name.text= 'new name', within the 'for' loop. However, when I try with the element "deployment", it works. How could I correct that?
I guess that you have at least one network element that doesn't have a name child. You can check for this by adding if name is not None: before name.text= 'new name'.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.