lxml: цикл while с узлом одинаковых элементов - PullRequest
0 голосов
/ 13 ноября 2018

Я использую lxml для создания файла json на основе xml.XML-файл имеет такую ​​структуру:

<spots_list>
    <spot id="001" latitude="2011464" longitude="979511">
        <adress>Somewhere</adress>
        <city>BOSTON</city>
        <price category="Intermediate" value="782"/>
        <price category="Expensive" value="2765"/>
        <price category="Cheap" value="12"/>
     </spot>
    <spot id="002" latitude="2101644" longitude="915971">
        <adress>Somewhere else (very very far away)</adress>
        <city>CAMBRIDGE</city>
        <price category="Intermediate" value="472"/>
        <price category="Intermediate (but less expensive)" value="422"/>
        <price category="Expensive" value="20275"/>
        <price category="Cheap" value="12"/>
     </spot>
</spots_list>

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

from lxml import etree

tree = etree.parse("my_file.xml")

for node in tree.xpath("//spots_list/spot"):
    for adress in node.xpath("adress"):
        adr = adress.text
    while node.xpath("price"):
        print(adr)

Я знаю, что это неправильно, потому что первый адрес появляется снова и снова, но я не понимаю, как сформулировать этот цикл для переключения на следующие элементы ...

Заранее спасибо.

1 Ответ

0 голосов
/ 13 ноября 2018

Основная проблема в операторе while состоит в том, что node.xpath(...) возвращает список, который считается True, если он не пустой.Вам просто нужно сделать то же самое, что и на верхнем уровне, то есть перебрать интересующие вас элементы, например,

def parse_spot(el):
    adr = el.find('adress')
    return dict(
        address=adr.text if adr is not None else None,  # error handling if not found
        price=[dict(p.attrib) for p in el.findall('price')]
    )

tree = etree.fromstring(xml)  # xml is your example as string

[parse_spot(el) for el in tree.findall('./spot')]

Вы также можете использовать xpath вместо findall, как вы это делали.

...