Ошибка синтаксического анализа XML AttributeError: у объекта 'NoneType' нет атрибута 'text' - PullRequest
2 голосов
/ 16 октября 2019

Вероятно, есть простое решение моей проблемы, но я очень плохо знаком с python3, поэтому, пожалуйста, будьте осторожны со мной;)

У меня работает простой скрипт, который уже успешно анализирует информацию из xml-файл с этим кодом

import xml.etree.ElementTree as ET

root = ET.fromstring(my_xml_file)

u = root.find(".//name").text.rstrip()
print("Name: %s\n" % u)

XML-файл, который я анализирую, выглядит следующим образом

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/3.2/style/exchange.xsl"?>
<example:world-data xmlns="http://www.example.org" xmlns:ops="http://example.oorg" xmlns:xlink="http://www.w3.oorg/1999/xlink">
  <exchange-documents>
    <exchange-document system="acb.org" family-id="543672" country="US" doc-number="95962" kind="B2">
      <bibliographic-data>
             <name>SomeName</name>
       ...and so on... and ends like this
   </exchange-document>
  </exchange-documents>
</example:world-data>

(ссылки редактируются в соответствии с политикой stackoverflow)

Вывод, как и ожидалось

SomeName

Однако, если я пытаюсь проанализировать другой xml из того же API, используя те же команды python, я получаю этот код ошибки

AttributeError: 'NoneType' object has no attribute 'text'

Второй xml-файл выглядит следующим образом

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/3.2/style/pub-ftxt-claims.xsl"?>
<ops:world-data xmlns="http://www.example.org/exchange" xmlns:example="http://example.org" xmlns:xlink="http://www.example.org/1999/xlink">
  <ftxt:fulltext-documents xmlns="http://www.examp.org/fulltext" xmlns:ftxt="ww.example/fulltext">
    <ftxt:fulltext-document system="example.org" fulltext-format="text-only">
      <bibliographic-data>
        <publication-reference data-format="docdb">
          <document-id>
            <country>EP</country>
            <doc-number>10000</doc-number>
            <kind>A</kind>
          </document-id>
        </publication-reference>
      </bibliographic-data>
      <claims lang="EN">
        <claim>
          <claim-text>1. Some text.</claim-text>
          <claim-text>2. Some text.</claim-text>
          <claim-text>2. Some text.</claim-text>
        </claim>
      </claims>
    </ftxt:fulltext-document>
  </ftxt:fulltext-documents>
</ops:world-data>

Я попробовал еще раз

root = ET.fromstring(usr_str)

u = root.find(".//claim-text").text.rstrip()
print("Abstract: %s\n" % u)

Ожидаемый вывод

1. Some text.

Но он печатает только вышеупомянутое сообщение об ошибке. Почему я могу анализировать первый xml, но не второй, используя эти команды?

Любая помощь высоко ценится.

edit: код Джека Флитинга работает в консоли python, но, к сожалению, не в моейPyCharm

from lxml import etree
root = etree.XML(my_xml.encode('ascii'))
root2 = etree.XML(my_xml2.encode('ascii'))

root.xpath('//*[local-name()="name"]/text()')
root2.xpath('//*[local-name()="claim-text"]/text()')

Может ли это быть ошибкой в ​​моем PyCharm? Мой первый упомянутый фрагмент кода все еще печатает правильный результат для имени ...

edit: Оказывается, мне пришлось форсировать вывод, используя

a = root3.xpath('//*[local-name()="claim-text"]/text()')
print(a, flush=True)

1 Ответ

0 голосов
/ 16 октября 2019

Несколько проблем здесь, прежде чем мы доберемся до возможного решения. Во-первых, первый предоставленный вами фрагмент xml недействителен (например, <bibliographic-data> не закрыт). Я понимаю, что это всего лишь фрагмент, но так как это то, с чем мы должны работать, я изменил приведенный ниже фрагмент, чтобы исправить это. Во-вторых, оба фрагмента имеют объявление xmlns с несвязанными (неиспользованными) префиксами (example:world-data в первом и ops:world-data во втором). Мне пришлось удалить эти префиксы тоже, чтобы остальные работали.

С учетом этих изменений использование библиотеки lxml должно работать для вас.

Первый измененный фрагмент:

 my_xml = """<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/3.2/style/exchange.xsl"?>
<world-data xmlns="http://www.example.org" xmlns:ops="http://example.oorg" xmlns:xlink="http://www.w3.oorg/1999/xlink">
  <exchange-documents>
    <exchange-document system="acb.org" family-id="543672" country="US" doc-number="95962" kind="B2">
      <bibliographic-data>
             <name>SomeName</name>
       ...and so on... and ends like this
         </bibliographic-data>
   </exchange-document>
  </exchange-documents>
</world-data>"""

И:

my_xml2 = """<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/3.2/style/pub-ftxt-claims.xsl"?>
<world-data xmlns="http://www.example.org/exchange" xmlns:example="http://example.org" xmlns:xlink="http://www.example.org/1999/xlink">
  <ftxt:fulltext-documents xmlns="http://www.examp.org/fulltext" xmlns:ftxt="ww.example/fulltext">
    <ftxt:fulltext-document system="example.org" fulltext-format="text-only">
      <bibliographic-data>
        <publication-reference data-format="docdb">
          <document-id>
            <country>EP</country>
            <doc-number>10000</doc-number>
            <kind>A</kind>
          </document-id>
        </publication-reference>
      </bibliographic-data>
      <claims lang="EN">
        <claim>
          <claim-text>1. Some text.</claim-text>
          <claim-text>2. Some text.</claim-text>
          <claim-text>3. Some text.</claim-text>
        </claim>
      </claims>
    </ftxt:fulltext-document>
  </ftxt:fulltext-documents>
</world-data>"""

Исейчас на работу:

from lxml import etree
root = etree.XML(my_xml.encode('ascii'))
root2 = etree.XML(my_xml2.encode('ascii'))

root.xpath('//*[local-name()="name"]/text()')

вывод:

['SomeName']

root2.xpath('//*[local-name()="claim-text"]/text()')

Вывод:

[ '1. Некоторый текст. ',' 2. Некоторый текст. ',' 3. Немного текста. ']

...