ElementTree работает с .iter (), но не с .find () - PullRequest
0 голосов
/ 17 января 2020

Я новичок в ElementTree. Я хочу получить некоторые значения (текст) файла xml. Когда я пытаюсь root .iter (), на выходе появляется много тегов. Но когда я пытаюсь использовать root .find ('someTag') или root .findall ('someTag'), результатом будет None. Я не могу этого понять. Вы можете помочь мне? См. Немного файла xml:

<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl"       href="/3.2/style/exchange.xsl"?>
<ops:world-patent-data xmlns="http://www.epo.org/exchange" xmlns:ops="http://ops.epo.org" xmlns:xlink="http://www.w3.org/1999/xlink">
<exchange-documents>
    <exchange-document system="ops.epo.org" family-id="19768124" country="EP" doc-number="1000000" kind="A1">
        <bibliographic-data>
            <publication-reference>
                <document-id document-id-type="docdb">
                    <country>EP</country>
                    <doc-number>1000000</doc-number>
                    <kind>A1</kind>
                    <date>20000517</date>

Если .iter () показывает теги, почему я не могу найти эти теги с помощью .find ()?

tree = ET.parse('topnewsfeed.xml')
root = tree.getroot()

for x in root.iter():
    print(x.tag)

out положить это:

{http://ops.epo.org}world-patent-data
{http://www.epo.org/exchange}exchange-documents
{http://www.epo.org/exchange}exchange-document
{http://www.epo.org/exchange}bibliographic-data
{http://www.epo.org/exchange}publication-reference
(...)

Если я попытаюсь:

for x in root.find('{http://www.epo.org/exchange}exchange-document'):
    print(x.tag)

Я получаю эту ошибку:

TypeError: 'NoneType' object is not iterable

1 Ответ

0 голосов
/ 18 января 2020

Краткий и быстрый вариант исправления:

  • Заменить найти на findall .
  • As exchange- document не является прямым потомком root, добавьте XPath к . // , чтобы посмотреть на любую глубину.

Поэтому измените свой код на:

for x in root.findall('.//{http://www.epo.org/exchange}exchange-document'):
   print(x.tag)

Но размещение полных пространств имен в каждом XPath не является хорошей идеей. Вместо этого я рекомендую:

  • Определить словарь со всеми ярлыками и пространствами имен, используемыми в ваших XPath.
  • В каждом XPath укажите пространство имен с соответствующим ярлыком (+ двоеточие в качестве разделителя) ), но на этот раз без окружающих скобок.
  • Передайте этот словарь как второй параметр в findall .

Итак, второй (ИМХО более читабельный) Вариант:

ns = {'exch': 'http://www.epo.org/exchange'}
for x in root.findall('.//exch:exchange-document', ns):
    print(x.tag)
...