как получить xpath всех элементов в xml файле с пространством имен по умолчанию с помощью python?

Я хотел получить xpath каждого элемента в xml файле.

XML-файл:

<root 
xmlns="http://www.w3.org/TR/html4/"
xmlns:h="http://www.w3schools.com/furniture">

<table>
  <tr>
    <h:td>Apples</h:td>
    <h:td>Bananas</h:td>
  </tr>
</table>
</root>

Код Python: поскольку нулевой префикс в пространстве имен по умолчанию не разрешен, я использовал для этого свой собственный префикс.

from lxml import etree 
root=etree.parse(open("MyData.xml",'r'))
ns={'df': 'http://www.w3.org/TR/html4/', 'types': 'http://www.w3schools.com/furniture'}
for e in root.iter():
   b=root.getpath(e)
   print b
   r=root.xpath(b,namespaces=ns)
   #i need both b and r here

xpath выглядит так (вывод b)

/*
/*/*[1]
/*/*[1]/*[1]
/*/*[1]/*[1]/h:td

Я не могу правильно получить xpath для элементов, имеющих пространство имен по умолчанию, он отображается как * для этих имен элементов. Как правильно получить xpath?


person mariz    schedule 18.07.2016    source источник


Ответы (1)


Вы можете использовать getelementpath, который всегда возвращает элементы в нотации Кларка, и заменяет пространства имен вручную:

x = """
<root 
xmlns="http://www.w3.org/TR/html4/"
xmlns:h="http://www.w3schools.com/furniture">

<table>
  <tr>
    <h:td>Apples</h:td>
    <h:td>Bananas</h:td>
  </tr>
</table>
</root>
"""

from lxml import etree 
root = etree.fromstring(x).getroottree()
ns = {'df': 'http://www.w3.org/TR/html4/', 'types': 'http://www.w3schools.com/furniture'}
for e in root.iter():
    path = root.getelementpath(e)
    root_path = '/' + root.getroot().tag
    if path == '.':
        path = root_path
    else:
        path = root_path + '/' + path
    for ns_key in ns:
        path = path.replace('{' + ns[ns_key] + '}', ns_key + ':')
    print(path)
    r = root.xpath(path, namespaces=ns)
    print(r)

Очевидно, этот пример показывает, что getelementpath возвращает пути относительно корневого узла, например . и dt:table вместо /df:root и /df:root/df:table, поэтому мы используем tag корневого элемента, чтобы вручную построить полный путь.

Выход:

/df:root
[<Element {http://www.w3.org/TR/html4/}root at 0x37f5348>]
/df:root/df:table
[<Element {http://www.w3.org/TR/html4/}table at 0x44bdb88>]
/df:root/df:table/df:tr
[<Element {http://www.w3.org/TR/html4/}tr at 0x37fa7c8>]
/df:root/df:table/df:tr/types:td[1]
[<Element {http://www.w3schools.com/furniture}td at 0x44bdac8>]
/df:root/df:table/df:tr/types:td[2]
[<Element {http://www.w3schools.com/furniture}td at 0x44bdb88>]
person Keith Hall    schedule 18.07.2016
comment
- код работает нормально, но вместо чтения xml из строки я хочу прочитать его из файла xml, например open (MyData.xml, 'r'). Я не знаю точного синтаксиса для root = etree.fromstring ( x) .getroottree () для поддержки чтения файлов. как это сделать? - person mariz; 18.07.2016
comment
@mariz для синтаксического анализа файла с именем MyData.xml, вы можете заменить root = etree.fromstring(x).getroottree() на root = etree.parse('MyData.xml'). Дополнительная информация: lxml.de/parsing.html - person Keith Hall; 18.07.2016