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'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.