Parse XML namespace with Element Tree findall

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Parse XML namespace with Element Tree findall



How can I use a query element tree findall('Email') given the following xml?


findall('Email')


<DocuSignEnvelopeInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.docusign.net/API/3.0">
<EnvelopeStatus>
<RecipientStatus>
<Type>Signer</Type>
<Email>joe@gmail.com</Email>
<UserName>Joe Shmoe</UserName>
<RoutingOrder>1</RoutingOrder>
<Sent>2015-05-04T09:58:01.947</Sent>
<Delivered>2015-05-04T09:58:14.403</Delivered>
<Signed>2015-05-04T09:58:29.473</Signed>
</RecipientStatus>
</EnvelopeStatus>
</DocuSignEnvelopeInformation>



I have a feeling it has to do with the namespace but I'm not sure. I looked at the docs and had no luck.


tree = <xml.etree.ElementTree.ElementTree object at 0x7f27a47c4fd0>
root = tree.getroot()
root
<Element 'http://www.docusign.net/API/3.0DocuSignEnvelopeInformation' at 0x7f27a47b8a48>

root.findall('Email')




1 Answer
1



You should read the docs more closely, in particular the section on Parsing XML with Namespaces, which includes an example that is almost exactly what you want.



But even without the docs, the answer is actually contained in your example output. When you printed the root element of your document...


>>> tree = etree.parse(open('data.xml'))
>>> root = tree.getroot()
>>> root
<Element http://www.docusign.net/API/3.0DocuSignEnvelopeInformation at 0x7f972cd079e0>



...you can see that it printed the root element name (DocuSignEnvelopeInformation) with a namespace prefix (http://www.docusign.net/API/3.0). You can use this same prefix as part of your argument to findall:


DocuSignEnvelopeInformation


http://www.docusign.net/API/3.0


findall


>>> root.findall('http://www.docusign.net/API/3.0Email')



But this by itself won't work, since this would only find Email elements that are immediate children of the root element. You need to provide an ElementPath expression to cause findall to perform a search of the entire document. This works:


Email


findall


>>> root.findall('.//http://www.docusign.net/API/3.0Email')
[<Element http://www.docusign.net/API/3.0Email at 0x7f972949a6c8>]



You can also perform a similar search using XPath and namespace prefixes, like this:


>>> root.xpath('//docusign:Email',
... namespaces='docusign': 'http://www.docusign.net/API/3.0')
[<Element http://www.docusign.net/API/3.0Email at 0x7f972949a6c8>]



This lets you use XML-like namespace: prefixes instead of the LXML namespace syntax.


namespace:





Thank you, very helpful. I'd like to use your last example of root.xpath but it doesn't look like elementtree elements support .xpath AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'xpath'
– user2954587
May 4 '15 at 21:34


root.xpath


AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'xpath'





This answer assumes you're using lxml.etree.
– larsks
May 4 '15 at 21:43






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard