文档内模式声明与lxml

3 投票
1 回答
1885 浏览
提问于 2025-04-15 23:35

根据lxml的官方文档,如果你想要验证一个XML文档是否符合某个XML模式文档,你需要做以下几步:

  1. 创建一个XMLSchema对象(简单来说,就是解析这个模式文档)
  2. 创建一个XMLParser,并把刚才的XMLSchema对象作为它的schema参数传入
  3. 使用这个构建好的解析器来解析实际的XML文档(实例文档)

虽然可能会有一些变化,但无论你怎么做,核心思想都是一样的——模式是“外部指定”的(也就是说,不是在实际的XML文档内部指定)。

如果你按照这个流程来做,验证是会发生的,但如果我理解得没错,这样做完全忽略了xsi中的schemaLocation和noNamespaceSchemaLocation属性的概念。

这就带来了很多限制,首先,你必须自己处理实例文档和模式之间的关系(要么把它存储在外部,要么写一些小技巧从实例文档的根元素中获取模式位置),而且你不能使用多个模式来验证文档(比如说,每个模式管理自己的命名空间)等等。

所以问题是:也许我遗漏了一些非常简单的东西,或者做错了?还是说我对lxml在模式验证方面的限制的说法是正确的?

总结一下,我希望能够:

  • 让解析器在解析/验证时使用实例文档中的模式位置声明
  • 使用多个模式来验证一个XML文档
  • 在非根元素上声明模式位置(这不是特别重要)

也许我应该寻找其他的库?虽然这样做真的很可惜,因为lxml是Python中公认的XML处理库,被大家认为在性能、功能和便利性方面都是最好的(在某种程度上,这个评价是有道理的)。

1 个回答

3

注意:这不是这个问题的完整答案,因为我对lxml了解得不多。

我可以告诉你的是:

  • 在文档中忽略模式位置,而是在应用程序中管理命名空间和模式文件的映射,通常是更好的选择,除非你能保证模式会在文件的一个非常特定的位置。如果你想把它从代码中移出去,可以使用目录或者想出一个配置文件。
  • 如果你确实想使用schemaLocation,并且想要验证多个模式,只需在一个schemaLocation属性中将它们全部包含在一起,用空格分隔,格式是命名空间URI/位置对:xsi:schemaLocation="urn:schema1 schema1.xsd urn:schema2 schema2.xsd
  • 最后,我认为没有任何处理器会找到非根元素上声明的schemaLocation属性。不过这也没关系:只需把它们全部放在根元素上就行。

撰写回答