我们有一个扁平的 XSD,因此我们考虑以 CSV 格式存储数据,而不是以 XML 格式存储数据,因为数据可能非常庞大。假设我们从 XSD 知道 CSV 中每条记录的元素类型,有没有办法使用基于 Java 的 XML Validator 针对 XSD 验证 CSV 中的每条记录?
3 回答
Saxon XSD 验证器用作 SAX 过滤器,因此您可以通过发送表示输入的 XML 视图的 SAX 事件来进行验证。因此,您所需要的只是一个读取 CSV 文件并发出代表其内容的 SAX 事件的 Java 程序,其中 SAX 事件通过管道传送到 XSD 验证器。
一种方法是执行以下操作:
- 使用 JAXB 编译器从 XSD 创建 Java 类
- 使用类似于Flatworm的产品自动/声明式地将您的记录(或整个文件)解析为上面创建的 Java 类,或者简单地手动等。
- 使用一种方法,例如在 SO上发布的方法来验证您的图表。只要确保您适当地缓存,即重用验证器和 JAXBContext 对象。
考虑到请求的性质,编组到 XML(即使作为 JAXBSource)所产生的开销是不可避免的。您可以做的就是充分利用它...如果 CPU 带宽不是问题,您可以尝试并行化以提高吞吐量(每个线程需要一个验证器,上次我使用 JAXBContent 时它是线程安全的)。而且我会避免加载整个文件,如果有人认为所有记录的 XSD(如与记录匹配的元素将是具有 maxOccurs="unbounded" 的粒子)将是一种更有效的验证方式......对于大文件,您将耗尽内存,很可能......
对于大量数据,使用 XSD 可以被标记为优雅,但效率不高。对于在寻找 .NET 解决方案时遇到这篇文章的人来说,通过调用XmlSchemaDatatype.ParseValue来验证单个字段的效率更高(假设 XSD 没有跨字段约束等)。
“平面 XSD”和“每条记录的元素类型”是什么意思?显然,在将非 XML 格式提供给期望 XML 输入的验证器时,涉及到一些转换或适应过程。因此,所有相关名称都必须可用。
特别是,除非您有额外的列(通常在行的开头),否则您将没有空间对与整行对应的元素的名称进行编码。这与第一行中其他列的名称是子元素(上)还是属性(下)无关。
那么,假设该名称对适配器可用,那么您的“平面 XSD”是什么样的?如果此元素是架构的根或顶级元素(即架构仅描述一行),那么您将必须使用新的顶级元素扩展架构以充当一系列行的容器,这是您的 CSV 文件。换句话说,不是将每一行验证为单独的 XML 文档,您应该将整个 CSV 文件(经过转换或以其他方式改编)验证为单个 XML 文档。
如果您的验证器可以接受管道输入,那么您只需要使用任何方便的脚本语言编写的 CSV 到 XML 转换器。