1

I'd like to be able to parse some info from xml data while uses namespaces. I have been trying to read/follow steps in: https://docs.python.org/3/library/xml.etree.elementtree.html#parsing-xml-with-namespaces

This is a sample of how my xml looks like enter image description here

When I try going through xml tree using a nested for loop, it looks like my code can read the sub-elements successfully.

def toXML(s):
    xmlRoot= ET.fromstring(s)
    
    for child in xmlRoot:
        print(child.tag)
        for subchild in child:
            print(subchild.tag)
            for subchild in subchild:
                print(subchild.tag)

Output:

{http://www.w3.org/2003/05/soap-envelope}Body
{http://www.onvif.org/ver10/search/wsdl}GetRecordingSummaryResponse
{http://www.onvif.org/ver10/search/wsdl}Summary

Process finished with exit code 0

However, when I try to do this the nice way

    for child in xmlRoot.find('{http://www.onvif.org/ver10/search/wsdl}Summary'):
        NumberRecordings=child.find('{http://www.onvif.org/ver10/schema}NumberRecordings')
        print(NumberRecordings.text)

I get this error:

for child in xmlRoot.find('{http://www.onvif.org/ver10/search/wsdl}Summary'):
                 ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'NoneType' object is not iterable

Any idea why my child is None ?

3
  • 2
    Use .findall(), not .find(). find() returns a single element or None, you can't iterate over either of them. Commented Apr 2 at 21:40
  • 1
    It doesn't say that child is None. It says that xmlRoot.find() returns None, and you can't loop over that. Commented Apr 2 at 21:40
  • If you do this xmlRoot.find('.//{http://www.onvif.org/ver10/search/wsdl}Summary') this should work. Commented Apr 3 at 10:52

1 Answer 1

0

You can find the text values with find(".//prefix:tagname", namespace). No need for interation.

from lxml import etree

xmlFile = "your_xml_file.xml"
root = etree.parse(xmlFile).getroot()
ns = root.nsmap

dataFrom = root.find(".//tt:Data-From", ns).text
print(dataFrom)

dataUntil = root.find(".//tt:DataUntil", ns).text
print(dataUntil)

numberRecords = root.find(".//tt:NumberRecordings", ns).text
print(numberRecords)

Output:

2025-03-19T15:22:10z
2025-03-19T18:30:52Z
1

Or as an shorter alternative search for <tse:Summary> with find() and iterate over the childs:

for elem in root.find(".//tse:Summary", ns):
    print(elem.text)
Sign up to request clarification or add additional context in comments.

Comments

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.