代码之家  ›  专栏  ›  技术社区  ›  Clutch

用DTD验证XML无法使用LXML导入实体

  •  3
  • Clutch  · 技术社区  · 14 年前

    我有一个工具可以生成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)
    

    首先,我不确定是否需要两个“加载”?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文件。

    1 回复  |  直到 10 年前
        1
  •  4
  •   culix    10 年前

    尝试用构造分析器 no_network=False . 如中所述 documentation :

    无网络-在查找外部文档时阻止网络访问(默认情况下打开)

    导入的DTD模块应该由lxml检索,但如果不允许网络访问,则无法检索(这不包括文档本身,仅限于加载外部引用的文档)。实际上,我希望您在加载DTD本身时出错,因此我假设文档引用了该DTD的本地可用副本,并且只有DTD本身引用了远程资源?)

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

    (也可以自己写 resolvers 对于LXML来说,截取和处理请求,但在本例中,这可能会造成过度杀伤力)

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

    这将使用提供的DTD验证已分析文档,而不管doctype声明引用了哪个DTD(如果有)(这很方便:根据DTD,并非每个有效的XML文件都必须有效 想要)。

    因为DTD只需要检索和解析一次,所以如果您要验证大量文档,这应该更快,而且(如果我没有弄错的话),您不会遇到无网络问题。

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

    最后一点注意:只有在解析时有权访问DTD(不可解析的实体…)才能解析某些文档。如果可以的话,避免这样做。(而且,尽管并非所有人都同意:如果可能,请完全避免doctype声明)。