Fixing xml.etree.ElementTree.ParseError: undefined entity &egrave

Fixing xml.etree.ElementTree.ParseError: undefined entity &egrave

我正在处理 .pri 文件。它具有 xml 格式。如下所示。

<?xml version="1.0"?>
<!DOCTYPE text SYSTEM "text.dtd">
<text id="fn000001">
  <au id="fn000001.1" s="N00023">
    <w id="fn000001.1.1">                          hi              </w>
    <w id="fn000001.1.2">                          there           </w>
    <l id="fn000001.1.3">                          ?               </l>
  </au>
</text>

现在如果我调用单个文件,使用下面的命令,它可以正常工作。

import xml.etree.ElementTree as ET
tree = ET.parse('/path/fn000001.pri')
root = tree.getroot()
print(root.get('id'))

现在我想将其应用于文件夹中的所有 .pri 文件。为此,我使用以下命令,

import glob
import xml.etree.ElementTree as ET
a = glob.glob('/path/*.pri')
  
for files in a:
    tree = ET.parse(files)
    print(tree)

这会引发错误,

tree = ET.parse(files)
  File "/usr/lib/python3.6/xml/etree/ElementTree.py", line 1196, in parse
    tree.parse(source, parser)
  File "/usr/lib/python3.6/xml/etree/ElementTree.py", line 597, in parse
    self._root = parser._parse_whole(source)
xml.etree.ElementTree.ParseError: undefined entity &egrave;: line 147, column 52

请提出可能的解决方案。相关 .dtd 在同一文件夹中。

好的!我遇到了很多与这个问题相关的帖子和​​答案。根据一条评论中提供的此错误背后的原因,

As I said, ElementTree does not support entities declared in a separate DTD file. Either declare entities in the XML file or use lxml. Or don't use entities at all.

因此,主要问题是如何做到 ElementTree 支持在单独的 DTD 文件中声明的实体。

  • 解决方案 1:在 XML 文件中声明实体或使用 lxml 所以我使用了 lxml 但没有在 XML 文件中声明实体。它不会解决你的问题。如果您在 XML 文件中声明实体,那么您是否使用 lxml 包都没有关系。因此,在 XML 文件中声明实体如下。

     <!DOCTYPE text [
     <!ENTITY egrave "&#232;">
     ]>
     <text id="fn000001">
       <au id="fn000001.1" s="N00023">
         <w id="fn000001.1.1">                          hi              </w>
         <w id="fn000001.1.2">                          there           </w>
         <l id="fn000001.1.3">                          ?               </l>
       </au>
     </text>
    

此处提供此解决方案。

但是,如果您有 1000 个 XML 文件并且您希望同时解析它们怎么办?那么这个方案就不行了

  • 方案二:这个是永久的。您需要将 dtd 文件映射到 .XML 文件。 这只是一行代码。我使用了 lxml 包。检查下面的代码片段。
    from lxml import etree
    parser = etree.XMLParser(dtd_validation=True)
    tree = etree.parse("file.xml", parser)

您只需要提供 dtd_validation=True,代码将从 .dtd 文件中获取信息并将其映射到您的 .XML 文件。确保 .dtd 文件与所有 XML 文件位于同一目录中。