【问题标题】:Validating XML with DTD fails to import entity using lxml使用 DTD 验证 XML 无法使用 lxml 导入实体
【发布时间】:2011-04-21 22:39:52
【问题描述】:

我有一个生成 NewsML 类型 XML 文件的工具,我想在生成文件后验证它们。 我收到一个错误:

Attempt to load network entity @987654321@

python调用是:

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

首先我不确定我是否同时需要“load_dtd=True, dtd_validation=True”,但无论如何我都在使用它。 第二个错误似乎来自定义为的导入的 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-ruby-1.mod 还是我必须在本地拥有所有 DTD 文件。

【问题讨论】:

    标签: python xml dtd lxml


    【解决方案1】:

    尝试使用no_network=False 构造解析器。如documentation中所述:

    no_network - 在查找外部文档时阻止网络访问(默认开启)

    导入的 dtd 模块应该由 lxml 检索,但如果不允许网络访问,它将无法这样做(这不计入文档本身,仅用于加载外部引用的文档。事实上,我希望您会在加载 dtd 本身时遇到错误,因此我假设该文档引用了该 dtd 的本地可用副本,并且只有 dtd 本身引用了远程资源?)

    您还可以使用目录来使用本地可用的副本(不仅可以规避这个问题,而且性能更高,并且对 w3c 服务器更友好 ;-))。 Libxml2(由 lxml 使用)将检查 /etc/xml/catalogXML_CATALOG_FILES 环境变量中是否存在目录(请参阅 Libxml2 docs

    (也可以为 lxml 编写自己的resolvers 来拦截和处理请求,但在这种情况下可能有点过分了)

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

    这将使用提供的 dtd 验证已解析的文档,而不管 doctype 声明引用了哪个 dtd(如果有)(这很方便:根据 dtd,并非每个有效的 xml 文件都一定是有效的您 em> 想要)。

    因为 dtd 只需检索和解析一次,如果您要验证大量文档,这应该会更快),并且(如果我没记错的话),您不会遇到 no_network 问题.

    这种方法的另一个好处是:您甚至可以在序列化之前验证您的元素/元素树(如果您的生产工具使用的是 lxml)。

    最后一点:某些文档只有在您可以在解析时访问 dtd 时才能被解析(无法解析的实体...)。如果可以,请避免这种情况。 (虽然不是每个人都同意:如果可能的话,完全避免使用 doctype 声明)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-18
      • 2016-09-18
      • 1970-01-01
      • 2011-11-17
      • 1970-01-01
      • 2011-09-30
      • 2016-04-01
      相关资源
      最近更新 更多