8

I tried to register namespace with this:

ET.register_namespace("inv", "http://www.stormware.cz/schema/version_2/invoice.xsd")

but it doesn't work:

Traceback (most recent call last):
  File "C:\tutorial\temp_xml2.py", line 34, in module>
    for listInvoice in root.findall('inv:invoiceHeader'):
  File "C:\Python27\LIB\xml\etree\ElementTree.py", line 390, in findall
    return ElementPath.findall(self, path, namespaces)
  File "C:\Python27\LIB\xml\etree\ElementPath.py", line 293, in findall
    return list(iterfind(elem, path, namespaces))
  File "C:\Python27\LIB\xml\etree\ElementPath.py", line 259, in iterfind
    token = next()
  File "C:\Python27\LIB\xml\etree\ElementPath.py", line 83, in xpath_tokenizer
    raise SyntaxError("prefix %r not found in prefix map" % prefix)
SyntaxError: prefix 'inv' not found in prefix map
>>>

what's wrong with this?


Thanks Martinj

I tried - 1.:

for listInvoice in root.findall('inv:invoiceHeader', namespaces=dict(inv='http://www.stormware.cz/schema/version_2/invoice.xsd')):
    invoiceHeader = listInvoice.find('inv:id', namespaces=dict(inv='http://www.stormware.cz/schema/version_2/invoice.xsd')).text
    print invoiceHeader

Result: (empty)

2.:

nsmap=root.nsmap
print nsmap

Result: AttributeError: 'Element' object has no attribute 'nsmap'

3.:

for listInvoice in root.findall('.//{http://www.stormware.cz/schema/version_2/invoice.xsd}invoiceHeader'):
    invoiceHeader = listInvoice.find('.//{http://www.stormware.cz/schema/version_2/invoice.xsd}id').text
    print invoiceHeader

Result: Works ok.

Is there any chance to register namespaces at once? Then I would like to use listInvoice.find('inv:id').text instead of listInvoice.find('.//{http://www.stormware.cz/schema/version_2/invoice.xsd}id').text (nicer code and easy to read)

casperOne
  • 73,706
  • 19
  • 184
  • 253
peter
  • 4,289
  • 12
  • 44
  • 67

1 Answers1

19

It looks like the documentation hasn't been updated on how to use namespaces and .findall().

The .findall() function (as well as .find(), .findtext() and.iterfind()) takes anamespaces` argument which is supposed to be a mapping. That is the only structure consulted when finding tags:

root.findall('inv:invoiceHeader', namespaces=dict(inv='http://www.stormware.cz/schema/version_2/invoice.xsd'))

The .register_namespace() function is only useful for when serializing a tree out to text again.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Thanks, this works! For `.get()` I needed to prefix with `{namespace-URL}`, e.g. `element.get({http://www.w3.org/1999/02/22-rdf-syntax-ns#}ID)`. – ᴠɪɴᴄᴇɴᴛ Dec 09 '14 at 17:38
  • 2
    @Vincent: yes, attribute access has no support for namespace prefix translation and you need to pass in the fully qualified namespace prefix. – Martijn Pieters Dec 09 '14 at 17:41