1

I know that there are a few examples already of retrieving specific attributes from XML nodes, but I've not been successful in doing so with a namespace. I am able to retrieve an attribute without any namespaces, such as in this example.

Suppose I have the following "example.wsdl" file:

<?xml version="1.0" encoding="UTF-8"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="Name of the file">
  <wsdl:documentation>Documentation of the file</wsdl:documentation>
</wsdl:definitions>

I'd like to retrieve the "name" attribute of the node "wsdl:defintions" I have tried doing the below:

from lxml import etree

tree = etree.parse("example.wsdl")
rootWSDL = tree.getroot()

print(tree.find('./wsdl:definitions', rootWSDL.nsmap).attrib['name'])

However, the above returns an empty list with the following message:

AttributeError: 'NoneType' object has no attribute 'attrib'

For what it's worth, the Python version I am using is 3.7.5

Adam
  • 2,384
  • 7
  • 29
  • 66

2 Answers2

3

You can directly access it from the root.

Ex:

from lxml import etree

tree = etree.parse("example.wsdl")
rootWSDL = tree.getroot()
print(rootWSDL.attrib['name'])

#-->Name of the file
Rakesh
  • 81,458
  • 17
  • 76
  • 113
  • Thank you. But suppose I have a use case where the node in question is not directly below the root? I'd like to find a way where I can explicitly specify which node I want to target rather than where it lies in the structure. – Adam Nov 22 '19 at 11:31
  • Use `print(tree.find('wsdl:definitions', rootWSDL.nsmap).attrib['name'])` without `./` – Rakesh Nov 22 '19 at 11:34
  • 2
    Adam: *But suppose I have a use case where the node in question is not directly below the root?* Why did you not ask about that use case in the first place then? @Rakesh did provide a reasonable answer. You have started a bounty, but the XML in the question has not been changed. What exactly are you asking? – mzjn Nov 25 '19 at 15:11
2

In your example you can't find the wsdl:definitions node with find because the rootWSDL is that node. If this is always the case just take rootWSDL.attrib['name'].

Your current xpath will only find elements that are direct children of rootWSDL. If your intent is to find some other namespaced node anywhere in the document simply make it a global xpath, i.e. replace:

'./wsdl:targetElementName' 

with

'//wsdl:targetElementName'
Erik
  • 412
  • 1
  • 5
  • 11