Guest00983835
Guest00983835

Reputation: 13

find all ancestors of xml node python using lxml

I am trying to find all ancestors of node.

my xml,

xmldata="""
<OrganizationTreeInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/YSM.PMS.Web.Service.DataTransfer.Models">
<Name>Parent</Name>
<OrganizationId>4345</OrganizationId>
<Children>
    <OrganizationTreeInfo>
    <Name>A</Name>
    <OrganizationId>123</OrganizationId>
        <Children>
            <OrganizationTreeInfo>
                <Name>B</Name>
                <OrganizationId>54</OrganizationId>
                <Children/>
            </OrganizationTreeInfo>
        </Children>
    </OrganizationTreeInfo>
    <OrganizationTreeInfo>
    <Name>C</Name>
    <OrganizationId>34</OrganizationId>
        <Children>
            <OrganizationTreeInfo>
                <Name>D</Name>
                <OrganizationId>32323</OrganizationId>
                <Children>
                    <OrganizationTreeInfo>
                        <Name>E</Name>
                        <OrganizationId>3234</OrganizationId>
                        <Children/>
                    </OrganizationTreeInfo>
                </Children>
            </OrganizationTreeInfo>
        </Children>
    </OrganizationTreeInfo>
</Children>

"""

for e.g. If I input value of OrganizationId as 3234 , then output should be like,

{'parent':4345,'C':34,'D':32323,'E':3234 }

Here is my try,

root = ET.fromstring(xmldata)
for target in root.xpath('.//OrganizationTreeInfo/OrganizationId[text()="3234"]'):
    d = {
        dept.find('Name').text: int(dept.find('OrganizationId').text)
        for dept in target.xpath('ancestor-or-self::OrganizationTreeInfo')
    }
    print(d)

But it is not giving any output. I am unable to find out whats wrong with it.

Upvotes: 0

Views: 1853

Answers (1)

Vivek Sable
Vivek Sable

Reputation: 10223

You are not getting correct answer because of namespace xmlns="http://schemas.datacontract.org/2004/07/YSM.PMS.Web.Service.DataTransfer.Models"

Following code with namespace:

code:

import lxml.etree as ET

root = ET.fromstring(xmldata)

result = {}
count = 1
namespaces1={'xmlns':'http://schemas.datacontract.org/2004/07/YSM.PMS.Web.Service.DataTransfer.Models',}
for target in root.xpath('.//xmlns:OrganizationTreeInfo/xmlns:OrganizationId[text()="3234"]',\
                         namespaces=namespaces1):
    result[count] = {}
    for dept in target.xpath('ancestor-or-self::xmlns:OrganizationTreeInfo', namespaces=namespaces1):
            result[count][dept.find('xmlns:Name', namespaces=namespaces1).text] = int(dept.find('xmlns:OrganizationId', namespaces=namespaces1).text)

    count += 1

import pprint
pprint.pprint(result)

Output:

:~/workspace/vtestproject/study$ python test1.py
{1: {'C': 34, 'D': 32323, 'E': 3234, 'Parent': 4345}}

Replace xmlns= string with other temp string.

code:

import lxml.etree as ET

new_xmldata = xmldata.replace("xmlns=", "xmlnamespace=")

root = ET.fromstring(new_xmldata)#, namespace="{http://schemas.datacontract.org/2004/07/YSM.PMS.Web.Service.DataTransfer.Models}")

result = {}
count = 1
for target in root.xpath('.//OrganizationTreeInfo/OrganizationId[text()="3234"]'):
    result[count] = {}
    for dept in target.xpath('ancestor-or-self::OrganizationTreeInfo'):
            result[count][dept.find('Name').text] = int(dept.find('OrganizationId').text)

    count += 1

import pprint
pprint.pprint(result)

Output:

:~/workspace/vtestproject/study$ python test1.py
{1: {'C': 34, 'D': 32323, 'E': 3234, 'Parent': 4345}}

Upvotes: 1

Related Questions