我目前正在用 C++ 设计一个特殊用途的应用程序,它必须处理随不断发展的 XSD 方案 而来的 XML 文件。
- 此应用程序将需要在未来很长一段时间内得到支持,很可能需要支持更新版本的 XML 文件。
主要挑战是:input-XML 文件带有基本相似的 XSD 方案 (它们都是同一个配置数据定义标准的不同版本),只是在结构甚至命名上都不同。
- 目前并不需要文件中包含的所有数据,这可能会改变!
- 目前只需要在应用程序启动后读取数据,这可能会改变!
- 目前只需要读取数据,不需要写回数据,这可能会改变!
事实
- XML 文件可能大到 200MB。
- XSD 方案有 500 多行纯代码(无评论)。
- 现在我需要支持至少 3 个不同的版本(超过 10 个)。
- 将要使用的 XML 解析器必须是命名空间感知的。
- 存在版本的更改日志,但遗憾的是不完整且不够精确。
到目前为止,已做出以下考虑:
为每个版本使用数据绑定(bind)
Code Synthesis XSD提供了一个很好的基于 DOM/SAX 的解析器和数据绑定(bind)生成器。
- 导致巨大(非常大)的代码库
- 需要生成类的接口(interface)
- 面向 future ?
将 SAX 解析器与基于版本的处理程序一起使用
通过使用像 Apache Xerxes 这样的 sax-parser,可以将特定于版本的代码放在 sax-callback-handlers 中。 这些回调处理程序可能隐藏在“VersionReaderFactory”中,它返回特定版本的 XML 文件的正确处理程序。 处理程序会将数据填充到包含必要配置数据的通用数据类中。
- 只读!
使用 XSLT 转换旧 XML
Altova提供了一个很好的 XSLT 处理器,可用于将旧版本的 XML 定义的配置数据转换为最新版本。 执行此转换后,可以使用“简单”数据绑定(bind)来访问数据,因为只支持一个版本。
- 需要为每个版本创建一个 XSL 转换。
- 创建转换代码很容易出错。
- 目前还不清楚所有版本的所有实体是否都可以转换。 (不完整的更新日志)
使用 XPATH
以 XML 作为基础格式,XPATH 将是查询数据的自然选择。 'home-brew-parser' 可以利用一些 'VersionReaderFactory' 为特定版本的 XML 文件返回一组预定义的 XPATH 查询。 这个“home-brew-parser”将用必要的配置数据填充通用数据类。
- 可以连续扩展以满足需求
- 只读!
问题
应用程序的哪一部分应该是版本感知的?
XML | Parser | Application close to data | beneath the application | in the application
您认为上述哪种方法效果最好?
还有其他选择吗?
最佳答案
回想起来,事实证明以下方法足以满足我 99% 的需求:
方法:“版本跳跃”
对于需要支持的给定 XML 文件/XSD 方案的每个版本,已创建 XSL 转换以将给定输入文件转换为下一个版本,最后是 XML-C++ 数据绑定(bind)使用 Code Synthesis XSDe 生成。
每当需要支持新版本时,只需将一个 XSLT 样式表添加到预处理器,代码生成基本上是自动化的 - 每个版本都有几个单元测试以确保支持新版本不会'打破对遗留文件的支持。
方法:“所需数据的提取”
对于需要支持的给定 XML 文件/XSD 模式的每个版本,已创建 XSL 转换以将给定输入文件转换为另一种仅包含所需数据的文件类型。
通过使用这种方法,可以使用简单的 XML 方案甚至众所周知的键值存储文件类型(例如 json)来收集所需数据。
每当需要支持新版本时,只需将一个新的 XSLT 文件添加到预处理器中,生成的输出文件在所有版本中保持相同。
两种方法的预处理器都可以使用 XLST 2+ 创建,在 Saxon HE 上运行。
关于c++ - 在 C++ 中支持基于模式的不断发展的 XML 的技术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28742693/