文档内模式声明与lxml
根据lxml的官方文档,如果你想要验证一个XML文档是否符合某个XML模式文档,你需要做以下几步:
- 创建一个XMLSchema对象(简单来说,就是解析这个模式文档)
- 创建一个XMLParser,并把刚才的XMLSchema对象作为它的
schema
参数传入 - 使用这个构建好的解析器来解析实际的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属性。不过这也没关系:只需把它们全部放在根元素上就行。