如何验证一个 XSD 架构是否是另一个 XSD 架构的子集?
我们正在使用“蓝图”XSD 模式的集合(定义子组件可用的所有可能的输入或输出)创建一个系统应用程序。许多子组件正在被实现,并且这些子组件使用 XML 文件在它们之间传递数据。每个子组件都会创建相关蓝图 XSD 架构的子集(以指示它选择实现哪些可能的输入或输出)。针对子集 XSD 架构进行验证的任何 XML 数据文件也必须针对蓝图 XSD 架构进行验证,但反之则不然(因为子集 XSD 架构可能不包含蓝图 XSD 架构中的所有“可选”或“选择”XML 元素,并且它可以选择进一步限制现有 XML 标记上允许的数据值)。系统将根据子组件的子集 XSD 架构验证该子组件的所有 XML 输入(以标记任何错误输入并隔离数据相关问题的根源)。
在测试期间,我们打算验证每个子组件的子集 XSD 架构确实是关联蓝图 XSD 架构的子集,但我们没有执行此验证的自动化方法。这些 XSD 模式相当大且难看,需要手动进行此测试。最好有一种“根据 XSD 文件 2 验证 XSD 文件 1”命令,类似于 Java 如何根据 XSD 模式执行 XML 文件验证。我们想要确认每个子组件的子集 XSD 架构将不允许任何违反蓝图 XSD 架构的 XML 输入/输出组合。借助这种模式到模式的功能,验证子组件 A 的输出 XML 是否适合用作子组件 B 的输入也非常有帮助(我们可以轻松地根据 XSD 模式验证单个输出 XML,但是我们想要确认子组件 A 的所有可能的 XML 输出都将根据子组件 B 的 XSD 架构进行验证)。
有用信息:此应用程序是作为 OSGi 捆绑包实现并使用 Maven 2.2.1 编译/执行的 Java 6 应用程序的集合。没有使用任何特定开发 IDE 的要求。该系统正在 Microsoft Windows XP 环境中进行测试,但也计划在其他环境中执行该系统(因此首选跨平台解决方案)。
确保所需关系的最简单方法是通过限制蓝图模式类型来派生子集模式的类型。不过,听起来那艘船似乎已经起航了。
和这里的其他人一样,我不知道有任何工具可以开箱即用地执行此操作(尽管如果 Petru Gardea 说 QT Assistant 可以,那么值得跟进)。
一个复杂之处在于,有两种不同的方式来查看要验证的子集/超集关系:(1) 模式 1 接受为有效的每个文档(或元素)也被模式 2 接受为有效(不参考类型)所做的分配),或(2)针对模式 1 和 2 通过验证(规范中称为后模式验证信息集)生成的类型化文档彼此之间存在适当的关系:如果元素或属性在树1,在树2中有效;树 1 中分配给它的类型是树 2 中分配给它的类型的限制;等等。如果模式 1 和模式 2 是独立开发的,那么它们的类型通过派生相关的可能性很小,所以我猜您心里有第一种方法来解决这个问题。
不过,无论哪种形式,这个问题都是绝对可以解决的。对于任何模式(我仔细使用这个术语),根据定义,都声明了有限数量的类型和有限数量的元素名称;由此可见,元素名称/类型对的数量是有限的(可能很大)。
该算法可以是这样的。
从预期的根元素开始。 (如果有多个可能的根元素,那么在一般情况下,您需要对每个根元素运行此检查。)如果预期的根元素是 E,在模式 1 中类型为 T1,在模式 2 中类型为 T2,则将任务“比较类型 T1 和 T2”放入打开任务队列中。已完成的任务列表将为空。
-
比较两个复杂类型 T1 和 T2:
检查为 T1 和 T2 声明的属性集,了解其名称之间的子集/超集关系。确保预期超集中所需的属性在预期子集中不存在或可选。
为 T1 和 T2 声明的每个属性 A 将被分配一个类型(称为 ST1 和 ST2)。如果 ST1 = ST2,则不执行任何操作;否则,将任务“比较简单类型 ST1 和 ST2”添加到打开任务队列中,除非它位于已完成的比较列表中。
现在检查 T1 和 T2 中可能的子序列——正如 13ren 在评论中建议的那样,这是很容易处理的,因为内容模型本质上是使用元素名称集作为字母表的正则表达式;因此,它们定义的语言是常规的,并且子集/超集关系对于常规语言是可确定的。
每个可能的子元素 C 都由父类型 T1 和 T2 分配了元素声明和类型定义。我们将它们称为 ED1、ED2、CT1 和 CT2。每个同名的子元素都具有相同的类型,但不同的子元素可能匹配不同的元素声明。因此,对于任何可能的名称,只会有一对类型 CT1 和 CT2,但可能有多对 ED1 和 ED2(并且分析需要小心以确保它们正确匹配;这可能很难自动化)。
如果 CT1 = CT2,则不执行任何操作,否则将“比较类型 CT1 和 CT2”放入打开的任务队列中,除非已执行比较。
如果 ED1 和 ED2 结构相同,则不执行任何操作;否则将比较它们的任务放入任务队列中(除非它已经完成)。
要比较两个简单类型 ST1 和 ST2,请比较它们的词法空间(如果您想要模式上子集/超集关系的第一个定义)或它们的值空间(如果您想要第二个)。如果 ST1 和 ST2 都是同一基元类型的限制,您也许可以轻松比较它们的有效的基于分面的限制集。模式方面可能会使事情变得复杂,但因为它定义了一组正则表达式,所以子集/超集关系对于它来说是可判定的。
要比较两个元素声明,您需要比较元素声明的每个属性并检查所需的子集/超集关系。
正如您所看到的,它足够复杂和乏味,以至于您确实希望自动执行此分析,而且它也足够复杂,以至于很容易看出为什么它没有作为开箱即用功能广泛提供。但编码肯定会很有趣。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)