根据XML模式(xsd)验证带有大文本元素的XML

时间:2019-02-12 10:32:49

标签: python xml xsd stream

我必须处理包含潜在大容量(最大2GB)内容的XML文件。在这些文件中,内容的“较大”部分不会散布在整个文件中,而是包含在一个元素(加密文件,十六进制编码)中。
我没有利用文件源,所以我需要处理这种情况。

一个要求是保持较小的内存占用空间(<500MB)。我能够使用xml.sax以流模式读取和处理文件的内容,这样做很好。

问题是,这些文件也需要针对XML模式定义(.xsd文件)进行验证,而xml.sax似乎不支持。
我发现了一些用于模式验证的最新库,例如xmlschema,但没有一个以流/惰性方式进行验证的库。

有人可以推荐一种方法吗?

2 个答案:

答案 0 :(得分:1)

许多模式处理器(例如Xerces和Saxon)以流模式运行,因此在验证数据时无需将其保存在内存中。但是,一个2Gb的单个文本节点正在扩展Java对字符串和数组大小的限制,即使是流处理器也很可能希望将整个单个节点保留在内存中。

如果对此文本节点的内容没有任何验证约束(例如,您不需要验证它是否有效xs:base64Binary),那么我建议您使用接受SAX输入的模式验证器(例如Saxon) ,然后通过消除或压缩长文本值的SAX过滤器提供输入。 SAX解析器以多个块的形式向ContentHandler提供文本,因此SAX解析器中的文本节点大小不应有限制。 Saxon将尝试将多个块合并为单个字符串(或char数组),并且由于Java限制或可用内存量,在此阶段可能会失败。但是如果您的过滤器切掉了大文本节点,则不会发生这种情况。

答案 1 :(得分:0)

Michael Kay's answer有了一个可以过滤长文本的内容过滤器的好主意。这帮助我解决了我的问题。

我最终写了一个简单的文本收缩器,它通过减少命名标签中的文本内容大小来为我预处理XML文件(例如:“仅将文本的前64个字节保留在'Data'和'CipherValue中'元素,请勿触摸其他任何东西”。

然后生成的文件足够小,可以将其馈送到xmlschema之类的验证器中。

如果有人需要类似的东西:here is the code of the shrinker

如果使用此功能,请小心
如果XML模式定义包含诸如对受影响的元素的最小或最大长度检查之类的内容,这的确会更改XML的内容并可能导致问题。