我必须处理包含可能很大(最多2GB)内容的XML文件。在这些文件中,内容的“大”部分不会分布在整个文件中,而是包含在一个单独的元素中(加密文件,十六进制编码)。 我对文件的来源没有任何影响,所以我需要处理这种情况。
要求是保持较小的内存占用(<500MB)。我能够使用xml.sax以流模式读取和处理文件的内容,这样做很好。
问题是,这些文件还需要针对XML模式定义(.xsd文件)进行验证,这似乎不受xml.sax的支持。 我找到了一些最新的模块验证库,比如xmlschema,但没有用于以流/懒惰的方式进行验证。
谁能推荐一种方法来做到这一点?
许多模式处理器(例如Xerces和Saxon)以流模式运行,因此在验证数据时无需将数据保存在内存中。但是,2Gb单文本节点正在扩展Java对字符串和数组大小的限制,甚至流处理器也很可能希望将整个单个节点保存在内存中。
如果对此文本节点的内容没有验证限制(例如,您不需要验证它是有效的xs:base64Binary),那么我建议使用接受SAX输入的架构验证器(例如Saxon),并提供通过SAX过滤器输入,消除或浓缩长文本值。 SAX解析器以多个块的形式向ContentHandler提供文本,因此SAX解析器对文本节点的大小应该没有限制。 Saxon将尝试将多个块组合成单个字符串(或char数组),并且可能由于Java限制或可用内存量而在此阶段失败;但如果您的过滤器切断了大文本节点,则不会发生这种情况。
Michael Kay's answer有一个内容过滤器的好主意,可以压缩长文本。这有助于我解决我的问题。
我最后写了一个简单的文本缩小器,通过减少命名标签中的文本内容大小来预处理XML文件(例如:“只保留'Data'和'CipherValue'元素中文本的前64个字节,不要碰任何其他事情“)。
然后生成的文件足够小,可以将它提供给像qazxsw poi这样的验证器。
如果有人需要类似的东西:xmlschema
如果使用它,请小心 如果XML模式定义包含受影响元素的最小或最大长度检查等内容,这确实会更改XML的内容并可能导致问题。