16

Is there a way to ignore the XML namespace in tage names in elementtree.ElementTree?

I try to print all technicalContact tags:

for item in root.getiterator(tag='{http://www.example.com}technicalContact'):
        print item.tag, item.text

And I get something like:

{http://www.example.com}technicalContact blah@example.com

But what I really want is:

technicalContact blah@example.com

Is there a way to display only the suffix (sans xmlns), or better - iterate over the elements without explicitly stating xmlns?

Adam Matan
  • 128,757
  • 147
  • 397
  • 562
  • See my answer under http://stackoverflow.com/a/25920989/2593383 for a more general solution – nonagon Sep 18 '14 at 19:39
  • see also: [Python ElementTree module: How to ignore the namespace of XML files](https://stackoverflow.com/questions/13412496/python-elementtree-module-how-to-ignore-the-namespace-of-xml-files-to-locate-ma/76601149#76601149) – milahu Jul 03 '23 at 06:49

2 Answers2

8

You can define a generator to recursively search through your element tree in order to find tags which end with the appropriate tag name. For example, something like this:

def get_element_by_tag(element, tag):
    if element.tag.endswith(tag):
        yield element
    for child in element:
        for g in get_element_by_tag(child, tag):
            yield g

This just checks for tags which end with tag, i.e. ignoring any leading namespace. You can then iterate over any tag you want as follows:

for item in get_element_by_tag(elemettree, 'technicalContact'):
    ...

This generator in action:

>>> xml_str = """<root xmlns="http://www.example.com">
... <technicalContact>Test1</technicalContact>
... <technicalContact>Test2</technicalContact>
... </root>
... """

xml_etree = etree.fromstring(xml_str)

>>> for item in get_element_by_tag(xml_etree, 'technicalContact')
...     print item.tag, item.text
... 
{http://www.example.com}technicalContact Test1
{http://www.example.com}technicalContact Test2
Chris
  • 44,602
  • 16
  • 137
  • 156
  • Hopefully the above answers the question. A difference I have noticed is that `item` in the generator example does not have a `next` method. Still, other than this it behaves in the same (similar?) way to `etree.getiterator`. – Chris Jun 27 '12 at 13:27
1

I always end up by using something like

item.tag.split("}")[1][0:]
lebox
  • 56
  • 3
  • It does not address the iterator issue - I still have to iterate over the full tag name. – Adam Matan Jun 27 '12 at 13:01
  • I am not aware of any of the different xml handlers for python that do that. With lxml you could use a xlst on the xml before you parse it. – lebox Jun 27 '12 at 13:22
  • The `[0:]` is pointless. If you are trying to get a copy of it so as not to change the original you can simply do `[:]`. Or, if that isn't a problem, just remove the `[0:]` altogether. – C0deH4cker Jun 27 '12 at 17:37