3

我编写了以下简单的解析器(以在我稍微复杂的程序中展示问题),它从DBLP xml 数据库中的所有条目中提取标题。

from lxml import etree

class DBLPTarget(object):
    def __init__(self, outfile):
        self.inField = False
        self.outfile = outfile

    def start(self, tag, attrib):
        if tag == 'title':
            self.inField = True

    def end(self, tag):
        if self.inField and tag == 'title':
            self.inField = False            

    def data(self, data):
        if self.inField:
            self.outfile.write('%s\n' % data)

    def close(self):
        pass

outfile = open('dblp-selected.txt', 'w')
parser = etree.XMLParser(target = DBLPTarget(outfile), load_dtd=True)
infile = 'dblp.xml'
results = etree.parse(infile, parser)
outfile.close()

print("Done.")

在 dblp.xml 文件上运行此代码后,它会运行一段时间(生成大约 72K 的内容),然后引发以下错误消息。

Traceback (most recent call last):
  File "C:/Users/je24621/Desktop/dblp-example2.py", line 30, in <module>
    results = etree.parse(infile, parser)
  File "lxml.etree.pyx", line 3197, in lxml.etree.parse (src\lxml\lxml.etree.c:65042)
  File "parser.pxi", line 1571, in lxml.etree._parseDocument (src\lxml\lxml.etree.c:93101)
  File "parser.pxi", line 1600, in lxml.etree._parseDocumentFromURL (src\lxml\lxml.etree.c:93388)
  File "parser.pxi", line 1500, in lxml.etree._parseDocFromFile (src\lxml\lxml.etree.c:92445)
  File "parser.pxi", line 1047, in lxml.etree._BaseParser._parseDocFromFile (src\lxml\lxml.etree.c:89329)
  File "parsertarget.pxi", line 160, in lxml.etree._TargetParserContext._handleParseResultDoc (src\lxml\lxml.etree.c:100233)
  File "parsertarget.pxi", line 154, in lxml.etree._TargetParserContext._handleParseResultDoc (src\lxml\lxml.etree.c:100143)
  File "lxml.etree.pyx", line 294, in lxml.etree._ExceptionContext._raise_if_stored (src\lxml\lxml.etree.c:9383)
TypeError: function takes exactly 5 arguments (1 given)

作为参考,我在 Windows 7(不是选择)上使用 Python 3.2.5 和 lxml 3.2.1 执行此操作。我该如何修复/调试这个?

4

2 回答 2

1

我不知道你看到的实际问题是什么。我尝试使用 lxml 3.2.1 和 Python 3.3.1 以及今天的 libxml2 快照和 Apple 提供的 2.7.8 版本,在这两种情况下,它都会立即失败,因为 DTD 无效。

只需删除load_dtd=True3.8M 行输出即可使整个工作正常进行。它显然不能正确理解 DTD 中指定的自定义元素和实体。您不依赖这些元素,但实体是一个问题。例如,您得到一个替换字符,而不是替换&auml;为。ä

因此,似乎有四种方法可以解决此问题:

  1. 弄清楚如何让lxml您的 DTD 满意。
  2. 找到一个不同的解析器来处理损坏的 DTD。
  3. 将 DTD 嵌入到 XML 文件中(如本例所示)。
  4. 不要使用 DTD,而是预先解析数据。由于您真正需要的是自定义实体,因此您只需将每个实体替换为其定义即可。当然,您不会以这种方式获得验证……但无论如何您都无法通过验证。
于 2013-07-08T19:45:12.447 回答
0

对于任何有兴趣的人来说,这个问题都没有解决,它只是在图书馆的某个地方出现了一个错误。相反,我使用正则表达式手动解析了 xml。

于 2013-07-10T17:19:40.873 回答