【发布时间】:2016-10-21 05:21:17
【问题描述】:
我正在尝试使用 Python 最好是标准库从 XML 文档中提取 DTD 信息。乍一看,xml.sax.handler.DTDHandler 似乎是要走的路,所以我编写了以下示例代码来提取一个琐碎的 DocBook v4 文档的 DTD:
import xml.sax
from contextlib import closing
XML_CODE = '''<!DOCTYPE example PUBLIC
"-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
<example><title>Hello World in Python</title>
<programlisting>
print('Hello World!')
</programlisting>
</example>'''
class DTDPrinter(xml.sax.handler.DTDHandler):
def notationDecl(self, name, publicId, systemId):
print('name={}, publicId={}'.format(name, publicId))
if __name__ == '__main__':
with closing(xml.sax.make_parser()) as parser:
parser.setFeature(xml.sax.handler.feature_external_pes, False)
parser.setFeature(xml.sax.handler.feature_validation, False)
parser.setDTDHandler(DTDPrinter())
print('---------- before feed')
parser.feed(XML_CODE)
print('---------- after feed')
我的期望是,当使用 Python 3.5 运行此代码时,输出将类似于:
---------- before feed
name=example, publicId=-//OASIS//DTD DocBook XML V4.1.2//EN
---------- after feed
相反,我得到的输出似乎与各种图像格式相关,但与文档中指定的格式无关:
---------- before feed
name=BMP, publicId=+//ISBN 0-7923-9432-1::Graphic Notation//NOTATION Microsoft Windows bitmap//EN
name=CGM-CHAR, publicId=ISO 8632/2//NOTATION Character encoding//EN
name=CGM-BINARY, publicId=ISO 8632/3//NOTATION Binary encoding//EN
...
name=WMF, publicId=+//ISBN 0-7923-9432-1::Graphic Notation//NOTATION Microsoft Windows Metafile//EN
name=WPG, publicId=None
name=linespecific, publicId=None
---------- after feed
虽然名称为 linespecific 的最后一个条目可能以残缺的方式引用文档 DTD?
我还注意到,尽管文档很简单,但在最后一次输出之后延迟了几秒钟。也许解析器试图连接到互联网?我试图通过设置功能来禁用它
parser.setFeature(xml.sax.handler.feature_external_pes, False)
parser.setFeature(xml.sax.handler.feature_validation, False)
但无济于事。
如何说服 DTDHandler 对文档中出现的 DTD 做出反应而不连接到 Internet?
【问题讨论】:
-
你永远不会调用类的定义方法 notationDecl 来打印输出。
-
@Parfait 那是因为我希望 SAX 解析器在遇到
<!DOCTYPE ...>时调用它。回调使用parser.setDTDHandler(DTDPrinter())行设置。 -
@Parfait 我想我知道你在说什么:在将我的原始代码简化为最小示例时,我从未调用过大部分代码,因为
!=放错了位置。然而,主要问题仍然存在。我用获得的新见解更新了这个问题。 -
“我怎样才能说服 DTDHandler 对文档中出现的 DTD 做出反应而不连接到 Internet?” “文档中”没有 DTD。您在文档中拥有的是一个 DOCTYPE 声明,其中引用了oasis-open.org/docbook/xml/4.1.2/docbookx.dtd 上提供的实际 DTD。要获取 DTD,解析器必须连接到 Internet。