len
len

Reputation: 13

Python lxml - can't get to parent

I have an xml tree that I need to search:

<instance>
    <hostName>hostname1</hostName>
    <port enabled="true">9010</port>
    <metadata>
        <branch>master</branch>
    </metadata>
    <vipAddress>vip.address.com</vipAddress>
</instance>
<instance>
    <hostName>hostname2</hostName>
    <port enabled="true">9011</port>
    <metadata>
        <branch>sub_branch</branch>
    </metadata>
    <vipAddress>vip2.address.com</vipAddress>
</instance>

I am trying to do a search via the text in branch then get the grandparent element and get the vipAddress and port but when I use the code below when I try and print the vipAddress and the port it prints all of them instead of the one I was actually looking for:

branch_name = 'master'    
for record in tree.xpath('//branch/text()'):
  if(record == branch_name):
     branch = record.getparent()
     target_environment = branch.xpath('//vipAddress/text()')
     print(target_environment)
     target_port = branch.xpath('//port/text()')

example:

If I was to search for master instead of returning target_environment=vip.address.com and port=9011 it will return target_environment=[vip.address.com, vip2.address.com] and port=[9010,9011]

I am sure I am doing something simple wrong I just can't see what.

Upvotes: 1

Views: 225

Answers (1)

shmeem
shmeem

Reputation: 81

I'm not the best at working with xml in python, but I do see a few issues:

for record in tree.xpath('//branch/text()'): converts your branch elements to string, which you use further down to compare to branch_name. Strings do not have a getparent() method, so you may want to remove the text() from the xpath and compare branch_name to record.text

Once your record is an element, calling getparent() twice on record will give you it's grandparent element instance. I'm sure there's a better way to do this, but it seems to work.

.xpath('//') searches for items matching the query anywhere. Since you just want the element that's a child of <instance>, branch.xpath('vipAddress/text()') should do. Same goes for finding the target_port.

Also I think .xpath always returns a list, so even if this all works your port will look like [9011]

Putting it together I get something like:

branch_name = 'master'
for record in tree.xpath('//branch'):
  if(record.text == branch_name):
     branch = record.getparent().getparent()
     target_environment = branch.xpath('vipAddress/text()')
     print(target_environment)
     target_port = branch.xpath('port/text()')
     print(target_port)

Upvotes: 1

Related Questions