我有一个生成newsml类型xml文件的工具,我想在生成文件后验证它们。
我收到一个错误:
Attempt to load network entity http://www.w3.org/TR/ruby/xhtml-ruby-1.mod
python调用是:

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

首先,我不确定是否同时需要“load_dtd=true,dtd_validation=true”,但我还是在使用它。
第二个错误似乎来自定义为:
<!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-ruby-1.mod,或者我必须在本地拥有所有的dtd文件。

最佳答案

尝试用no_network=False构造解析器。如documentation中所述:
无网络-在查找外部文档时阻止网络访问(默认为打开)
导入的DTD模块应该由LXML检索,但如果不允许网络访问,则无法检索(这不包括文档本身,仅用于加载外部引用文档)。事实上,我希望您在加载DTD本身时出错,所以我假设文档引用了该DTD的本地可用副本,并且只有DTD本身引用了远程资源?)
您还可以使用目录来使用本地可用的副本(不仅可以避免这个问题,而且对w3c服务器的性能更高、更友好;-))。libxml2(由lxml使用)将检查/etc/xml/catalog中是否存在目录,以及XML_CATALOG_FILES环境变量(请参见Libxml2 docs
(也可以为lxml编写自己的resolvers来拦截和处理请求,但在这种情况下,这可能是过分的)
注意,除了parse time validation,还有另一个选项:使用DTD class分别加载dtd,并将其用作验证器。
这将使用提供的dtd验证已解析的文档,而不管doctype声明引用的是哪个dtd(如果有的话)(这可能很方便:根据所需的dtd,并非每个有效的xml文件都必须有效)。
因为dtd只需要检索和解析一次,所以如果要验证很多文档,应该更快,而且(如果我没有搞错的话),您不会遇到无网络问题。
这种方法的另一个好处是:在序列化元素/元素树之前,您甚至可以验证它们(如果您的生成工具使用的是lxml)。
最后一点注意:只有在解析时访问DTD(无法解析的实体…),才能解析某些文档。如果可以的话就避免这样做。(而且,虽然不是每个人都同意:如果可能的话,完全避免doctype声明)。

09-04 02:03
查看更多