首页 > 解决方案 > XML 解析错误 AttributeError:“NoneType”对象没有属性“文本”

问题描述

我的问题可能有一个简单的解决方案,但我对 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

但是,如果我尝试使用相同的 python 命令从同一个 api 解析另一个 xml,我会得到这个错误代码

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 而不是第二个?

非常感谢任何帮助。

编辑:Jack Fleeting 的代码在 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 中的一个错误吗?我第一次提到的代码片段仍然打印出正确的名称结果...

编辑:原来我不得不使用强制输出

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

标签: python-3.xxmlxml-parsing

解决方案


在我们找到可能的解决方案之前,这里有几个问题。一,您提供的第一个 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()')

输出:

['某个名字']

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

输出:

['1。一些文字。','2。一些文字。','3。一些文字。']


推荐阅读