2010-10-06 69 views
3

我有一个生成NewsML类型XML文件的工具,我想在生成文件后验证它们。 我收到一个错误:使用DTD验证XML无法使用lxml导入实体

Attempt to load network entity http://www.w3.org/TR/ruby/xhtml-ruby-1.mod

蟒蛇电话是:

parser = etree.XMLParser(load_dtd=True, dtd_validation=True) 
treeObject = etree.parse(f, parser) 

首先我不知道如果我需要两个 “load_dtd =真,dtd_validation =真”,但我反正使用它。 二错误似乎是从被定义为进口NITF-3-4.dtd未来:

<!ENTITY % xhtml-ruby.mod PUBLIC 
    "-//W3C//ELEMENTS XHTML Ruby 1.0//EN" "http://www.w3.org/TR/ruby/xhtml-ruby-1.mod"> 
%xhtml-ruby.mod; 

将限于lxml出去检索此XHTML的红宝石1.mod或我有所有的DTD文件在本地。

回答

4

尝试使用no_network=False构建解析器。正如指出的documentation

no_network - prevent network access when looking up external documents (on by default)

进口DTD模块应该由LXML得到恢复,但如果不允许网络访问,将不能够做到这一点(不记入文档本身,只为加载外部引用的文档。事实上,我希望你加载dtd本身时会出错,所以我认为文档引用了该dtd的本地可用副本,并且它只是引用远程资源的dtd本身?)

你也可以使用一个目录来使用本地可用的副本(不仅可以绕过这个问题,而且可以更高效,更友好地向w3c服务器发送;-))。 libxml2的(按LXML使用)会为您在/etc/xml/catalog目录是否存在等,以及XML_CATALOG_FILES环境变量(见Libxml2 docs

(还可以编写自己的resolvers为LXML拦截和处理请求,但在这种情况下可能会过度)

请注意,除解析时间验证外,还有另一个选项:使用DTD class单独加载dtd,并将​​其用作验证程序。

这将验证与所提供的DTD解析文档无论哪个DTD(如果有的话)是由DOCTYPE声明引用(它可以很方便:不是每一个有效的XML文件一定是有效的根据DTD 想) 。

因为dtd只需要检索和解析一次,如果你正在验证大量文档,这应该会更快),(如果我没有弄错),你将不会遇到no_network问题。

接近的另一个好处是:你甚至可以在序列化之前验证元素/元素树(如果你的生成工具使用lxml)。

最后说明:如果您有权访问解析时的dtd(无法解析的实体...),则只能解析某些文档。如果可以的话,避免这种情况。 (尽管不是每个人都会同意:如果可能的话,完全避免doctype声明)。