Python Forum

Full Version: How do I get attribute XPATHs list ?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
How do I get attribute XPATHs list ?
======================================

Thanks for reviewing my 1st thread in this forum.

I am trying to list all Xpaths of the input file using Python code.

Here is the input.

Output:
<?xml version="1.0" encoding="UTF-8"?> <data> <country name="Liechtenstein"> <rank>1</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/> <neighbor name="Switzerland" direction="W"/> </country> <country name="Singapore"> <rank>4</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor name="Malaysia" direction="N"/> </country> <country name="Panama"> <rank>68</rank> <year>2012</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> </data>
Here is the python code:

import xml.etree.ElementTree as ET
from lxml import etree
infile = 'D:\Python_work\eclipse-workspace\My1stPythonP\CountryData.xml'
output ="D:\\Python_work\\eclipse-workspace\\My1stPythonP\\outfile.out"
tree = etree.parse(infile)
root = tree.getroot()
f = open(output,'w') #open write to file
count = tree.xpath("count(.//country)")
print (count)
f.write("%s\n" %(count))
xpathf = root.find('.//country')
print(xpathf.get("value"))
xpathf = root.find('.//data/country/year')
print(xpathf.get("value"))
print (tree.getroot() )
xmlstr = ET.tostring(root,  method='xml')
root1 = ET.fromstring(xmlstr)

tree1 = etree.ElementTree(root)
for e in root.iter():
     f.write("%s\n" %(tree1.getpath(e)))
f.close()
1) tree1.getpath(e) getting the list of XPATHs, but attribute XPATHS are missing from the list

2) xpathf = root.find('.//country')
print(xpathf.get("value"))
xpathf = root.find('.//data/country/year')
print(xpathf.get("value"))

are not printing the data value of XPATHs './/country' & './/data/country/year'

I am looking to extract the value based on XPATH.

3) What is the way to extract the attribute value based on XPATHs?

4) If there is the name space spec in input file, the above code produce the XPATH list as

Output:
/* /*/*[1] /*/*[2] /*/*[2]/*[1] /*/*[2]/*[2] /*/*[2]/*[3] /*/*[2]/*[4] /*/*[2]/*[5] /*/*[2]/*[6] /*/*[2]/*[7] /*/*[2]/*[8] /*/*[2]/*[9] /*/*[2]/*[10]
Are there ways to get readable XPATH, when input file contain a namespace spec?

Thanks for your guidance.
(Jun-20-2020, 10:26 PM)MDRI Wrote: [ -> ]2) xpathf = root.find('.//country')
print(xpathf.get("value"))
xpathf = root.find('.//data/country/year')
print(xpathf.get("value"))
When you are using XPath expressions can not use .find(),need to use .xpath().
Here a quick test.
from lxml import etree

root = etree.parse(r'country.xml')
root = root.getroot()
Usage test:
>>> parse = root.xpath('//year')
>>> parse
[<Element year at 0x3a6a8a0>,
 <Element year at 0x3a6a8c8>,
 <Element year at 0x3a6a8f0>]

>>> parse[0].text
'2008'
>>> [tag.text for tag in parse]
['2008', '2011', '2012']

# Using find() it will find first occurrence
>>> parse = root.find('country')
>>> parse.attrib
{'name': 'Liechtenstein'}
>>> parse.find('year')
<Element year at 0x704030>
>>> parse.find('year').text
'2008'

# Example all the child element nodes of the country element
parse = root.xpath('//country/*')
>>> for tag in parse:
...     if tag.text is not None:      
...         print(tag.text)
        
1
2008
141100
4
2011
59900
68
2012
13600
MDRI Wrote:
f.write("%s\n" %(count))
Try not to use this old string formatting anymore
With f-string it look like this.
f.write(f"{count}\n")
Thanks for your guidance.

I am using Eclipse with PyDev for Python . I am not able to get interactive output as you posted.

I need to add Print and run to see output. Is there a way to get interactive output with clipse with PyDev IDE.

Thanks for your guidance.
(Jun-24-2020, 02:55 AM)MDRI Wrote: [ -> ]I am using Eclipse with PyDev for Python . I am not able to get interactive output as you posted.

I need to add Print and run to see output. Is there a way to get interactive output with clipse with PyDev IDE.
There is a Interactive Console in PyDev.

It's a important part of Python to do test of smaller code pies like this.
I often use a standalone like REPL like ptpython(used with code over) or IPython for this.
Can also use both in my main editor VS Code.

-i flag can good to know about.
Load any code to interactive console of choice.
# lxml_test.py
from lxml import etree

root = etree.parse(r'country.xml')
root = root.getroot()
So from command line eg cmder.
[Image: VCVAP5.png]