如何确定一个XSD架构是另一个XSD架构的一个子集?(How to verify that one

2019-08-06 12:59发布

我如何验证一个XSD架构是另一个XSD架构的一个子集?

我们创建使用“蓝图” XSD模式的集合(其定义了可用到子组件的所有可能的输入或输出)的系统的系统的应用程序。 许多子正在实施,而这些子组件使用XML文件通过相互之间的数据。 每个子组件创建相关蓝图XSD模式的子集(以指示其已经选择了实现可能的输入或输出)。 该验证对一个子集的XSD架构的任何XML数据文件也必须验证对蓝图XSD架构,但反过来是不正确的(如子集XSD架构可能不包含所有“可选”或“选择” XML从蓝图XSD架构元素,并且它可以选择进一步限制在现有的XML标签允许的数据值)。 该系统将验证所有XML输入,针对子组件的子集XSD模式的子组件(以国旗任何坏的投入和隔离与数据有关问题的来源)。

在测试过程中,我们打算验证每个子组件的子集的XSD模式是真正相关的蓝图XSD架构的一个子集,但我们必须执行此验证的没有自动手段。 这些XSD架构是相当大的和丑陋的需要手工做这个测试。 这将是很好,有一种“验证XSD文件1against XSD文件2”命令,类似于Java如何针对XSD架构执行XML文件的验证。 我们要确认每个子组件的子集XSD架构不会允许XML输入/这将违反蓝图XSD模式输出的任意组合。 有了这个架构对架构的能力,这也将是非常有益的,以验证是否从子一个输出XML是适合用来作为输入子B(我们可以很容易地验证对XSD模式的单一输出XML,但我们要确认,从子A的所有可能的XML输出将验证对亚B的XSD架构)。

有用的信息:本申请是为OSGi包实现和编译/使用Maven 2.2.1执行的Java应用程序6的集合。 有使用任何特定的开发IDE没有要求。 该系统正在于微软的Windows XP环境中测试,但有计划地执行在其他环境中,此系统以及(这样一个跨平台的解决方案是首选)。

Answer 1:

确保你想要的关系,最简单的方法是通过限制该类型的蓝图架构的派生类型的子集架构的。 这听起来好像是船已经航行了,虽然。

与其他人一样在这里,我没有意识到这样做开箱即用任何工具(但如果彼得鲁杜米特Gardea说QT助手就可以了,这是值得跟进)。

一个复杂因素是,有两种不同的方式来查看要验证的子集和/超集关系:(1)每个文件(或元件)接受由模式1为有效还通过模式2接受为有效(无参考类型分配执行),或(2)确认产生(在哪些规范要求的架构验证后信息集)对模式1和2架在适当的相对于彼此的输入文件:如果一个元素或属性是有效的树1,它在树2有效; 在树1分配给它的类型是在树2分配给它的类型的限制; 等。如果模式1和2是独立开发,其类型由推导相关的几率就会降低,所以我想你的第一种方法在心中的疑问。

这个问题,不过,绝对是可判定,在两种形式。 对于任何模式(我用认真的术语),有定义的类型数量有限,并宣布元素名称数量有限的; 它遵循有元素名称/类型对有限数量的(可能很大)。

该算法可以去这样的事情。

  1. 开始与预期的根元素。 (如果有多个可能的根元素,则在一般情况下则需要运行该检查,对于它们中的每。)如果预期根元素是E,与类型T1在模式1和类型T2在模式2中,然后请将任务的开放任务队列“比较类型T1和T2”。 已经完成的任务的列表是空的。

  2. 要比较两个复杂类型T1和T2:

    • 检查申报T1和T2因为他们的名字之间的一个子集/超集关系,属性的集合。 确保没有在预定的超集所需的属性是预期的子集缺席或可选的。

    • 每个属性A声明的T1和T2将被分配一个类型(调用它们ST1和ST2)。 如果ST1 = ST2,什么都不做; 否则,添加任务“比较简单类型ST1和ST2”,以开放的任务队列,除非它已经完成了比较的名单上。

    • 现在检查,在T1和T2是可能的子序列 - 如13ren暗示的评论,这是因为温顺的内容模型是其使用set元素名称作为其字母表基本上是正则表达式; 它们定义了语言,因此定期,并且该子集/超集关系可判定为正规语言。

    • 每个可能的子元素C分配两者的元素声明和由父类型T1和T2的类型定义。 让我们称他们为ED1,ED2,CT1,CT2和。 同名的每个孩子都会有相同的类型,但不同的孩子可以搭配不同的元素声明。 因此,对于任何可能的名字,届时会有一对类型CT1和CT2的,但有可能是多对ED1和ED2(和分析将需要小心,以确保它们匹配正确,这可能是很难自动化)。

    • 如果CT1 = CT2,什么也不做,否则就把“比较类型CT1和CT2”到打开的任务队列,除非比较已经被执行。

    • 如果ED1和ED2结构相同,什么都不做; 否则把他们进行比较到任务队列(除非它已经完成)的任务。

  3. 要比较两个简单类型ST1和ST2,比较要么自己词汇空间(如果你想在架构子集/超集关系的第一个定义)或它们的价值空间(如果你想秒)。 如果ST1和ST2都是相同基本类型的两个限制,您可以到一套行之有效的基于面的限制,轻松地比较他们。 图案晶面可以使问题复杂化,而是因为它定义了一组正则表达式,子集/超集关系可判定它。

  4. 要比较两个元素的声明,你需要比较每个属性的元素声明和检查所需的子集/超集关系。

正如你所看到的,它的复杂和繁琐的不足,你真的要这样分析的自动化,并且它也足够复杂,很容易看出为什么它没有被广泛作为外的现成功能提供。 但肯定会是有趣的代码。



Answer 2:

谢谢@ 13ren,为你的“嘟嘟” :)

这是一个漫长的评论,而不是答案。 我会从我的前面有13ren交流开始, more precise, it provides to a user all that is needed to define such an analysis model. 我的意思是,在QTAssistant( 这个 )我们有一个比较XSD功能; 是XSD感知的,它确实已经有很多的事情,文本或XML的比较工具不能做(例如,它并不关心有多少XSD文件,版本等之间的布局改变)对于提供的UI,的区别引擎的工作原理与源模型,而不是在一个PSVI。 我们可以自定义使用PSVI代替,因为后者是一个更接近你的实际需要。 我们还可以包括有设置增强“基地”和“修订”,换言之之间的比较,以允许用户覆盖“=”操作我们目前使用的自定义规则的能力。

我承认,我们没有什么开箱允许覆盖比较XSD的:模式方面; 也不的东西,对人类很容易识别,例如xsd:positiveIntegerxsd:integer + xsd:minInclusive=1 。 或比较的xsd:allxsd:choicexsd:sequence ; 出于同样的,我们不解析出选择和字段XSD约束条件,很像正则表达式,也不是那么容易对付。

假设目标是找到尽可能多的“差异”成为可能,而不是排除他们完全,QTAssistant有三个更多的功能这是有帮助的:

  • 对于一个给定根元素,它创建简单的XPath的完整列表。 它可以作为一个快速的方法来发现“流氓”的数据被应用。 开箱比较这种方法并没有考虑到的结构模式,即,如果XPath1和XPath2表示两个兄妹在一个实例XML,即XPath1必须先XPath2)等
  • 它配备了一个内置的查询分析器XSD 。 可以使用SQL查询一组的XSD元模型,以“点”的事情,指出事物的比较工具可以被设计成忽略(可行性),因此将需要一个人的报告来决定。
    • XSD重构(XSR)。 它是业界唯一引擎(据我所知,至少)是从底层构建了考虑XSD重构和分析。 我认为,如果你能排除XSI:类型和,理想情况下,利用置换组,以及(就这一个我仍然不得不考虑),我们可以使可就是我们所说的“标准化改造” - 看中字转换模式设置为一个俄罗斯套娃的设计风格,所依托的PSVI模型来代替。 有很多事情,可能是在这里打球:使用id属性,多余序列的崩溃,更换单选项XSD的:选择等 - 这就是为什么我们有它的研究与开发,但尚未公布。

另一件事,为此我们不得不准备在我们的比较(你可能要考虑)曾与等价不仅XSD / XML的做的,但(通过JAXB如Java类)从XSD生成的文物; 最糟糕的是,可扩展的模式,那些使用通配符(XSD:任何和anyAttribute)。

我们(QTAssistant)目前有意通过一些更具体的要求与您合作(我们需要开始与代表的XSD的交换,保密协议我会承担,等等),带外的,看看我们确实可以使它工作。 如果你想继续,随时通过我的SO文件相关联的网站的支持地址与我联系。



Answer 3:

由于目前还验证/检查模式对另一种模式没有可用的解决方案,看起来我们必须使用替代方法。 下面是我的尝试。

再论问题:

确定所有的子集架构中定义的数据类型是否存在,是什么在“蓝图”模式定义的(不太严格的)范围内。

一个可能的解决方案:

  1. 的(明显)信息第一部分是该模式允许我们创建XML实例(这是什么意思,甚至看?2)。
  2. 我们有(没有那么明显)的另一条信息是,XML模式本身可以是一个“子集,例如” - 我的意思是:如果你要扭转从XML实例工程的模式,那么你有一个子集架构(这个说法,如果你没有 “名单”或选择元素或其他的“框框”,然后反向工程的子集架构将精确地映射到“蓝图”的模式并非总是如此)。

因此,使用这方面的知识,我们可以构建一个解决方案:

创建一个子集架构(编程做这一步可能是一个挑战)的所有可能的XML实例,验证这些XML实例对“蓝图”的模式。

但是你怎么知道的子集架构是一个“蓝图”模式的子集 ? 好吧,既然你创建了一个子集架构的所有可能的XML实例,它覆盖的是那里的一个子集架构中的所有数据类型。 和验证这些XML实例对“蓝图”模式,本质上是检查数据类型是否存在,都是什么在“蓝图”模式定义的范围内。 因此,确定您的子集架构确实是一个“蓝图”模式的子集。

我知道它不是一个理想的解决方案,但希望这有助于因为没有可用简单的方法来做到你的要求。



Answer 4:

该验证XML对架构的工具已经知道如何做到这一点,因为在的情况下, <xs:complexContent><xs:restriction> ,新定义的类型必须为类型的一个子集的限制。

如果你想进入这个功能,你可以将孩子的架构定义复杂的类型,在你蓝图的架构限制类型。

如果心中没有这个创建的子模式,然而,这也可能仍然可以通过修改子模式到模式下面匹配,然后通过一个架构处理器验证送他们来完成。

例如蓝图架构,blueprintschema.xsd:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="root" type="rootType"/>
  <xs:complexType name="rootType">
    <xs:sequence>
      <xs:element name="child1" minOccurs="0"/>
      <xs:element name="child2" minOccurs="0"/>
      <xs:element name="child3" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

例如儿童模式,它是蓝图架构的一个子集:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="root" type="rootType"/>
  <xs:complexType name="rootType">
    <xs:sequence>
      <xs:element name="child2"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

转变为重新定义构造之后举例子模式:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:redefine schemaLocation="blueprintschema.xsd">
    <xs:complexType name="rootType">
      <xs:complexContent>
        <xs:restriction base="rootType">
          <xs:sequence>
            <xs:element name="child2"/>
          </xs:sequence>
        </xs:restriction>
      </xs:complexContent>
    </xs:complexType>
  </xs:redefine>
  <xs:element name="root" type="rootType"/>
</xs:schema>

然后架构处理器将告诉您重新定义“rootType”是否真的是原始蓝图“rootType”的一个子集

由于架构仅仅是XML,改造可以用正常的XML处理工具来完成。



文章来源: How to verify that one XSD schema is a subset of another XSD schema?