2016-06-07 68 views
0

我试图生成一个XSD来验证具有未知深度的XML。这是通过来自XML的XSLT完成的。 XML有点类似于类的描述,每个节点都包含有关属性和子节点的信息。 XSD必须检查另一个包含实例的XML。因此,XSD必须检查一个实例是否具有来自其类的所有属性,并且它是祖先。XSD多个级别的扩展问题

这就是为什么我试图解决我的问题与类型相互扩展。

XML测试文件:

<!-- language:xml --> 
<?xml version="1.0" encoding="UTF-8"?> 
<CAEXFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      FileName="Visu_Ruehrreaktor.aml" 
      SchemaVersion="2.15" 
      xsi:noNamespaceSchemaLocation="Validation.xsd"> 
    <HMI> 
     <HMIGraphic Name="Visu_Ruehrreaktor" 
        RefBaseSystemUnitPath="HMISUCLib/Graphic" 
        ID="dce863ca-795b-4d54-9a4c-789b0204f243"> 
     <h>1080</h> 
     <w>1920</w> 
     <HMIVisuObjectTextBoxTermination Name="Text01" 
              RefBaseSystemUnitPath="HMISUCLib/VisuObject/TextBox/Termination" 
              ID="c0215848-b8b6-4f76-aa2c-3996a053f3fc"> 
      <text/> 
      <tagname>Text01</tagname> 
      <x>178</x> 
      <y>152</y> 
      <h>37</h> 
      <w>139</w> 
      <role/> 
      <type>0001</type> 
      <rotation>01</rotation> 
      <com_id/> 
     </HMIVisuObjectTextBoxTermination> 
     </HMIGraphic> 
    </HMI> 
</CAEXFile> 

XSD:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:fn="http://www.w3.org/2005/xpath-functions"> 
    <xs:complexType name="HMI_type"> 
     <xs:choice maxOccurs="unbounded"> 
     <xs:element name="HMIGraphic" type="HMIGraphic_type" minOccurs="0"/> 
     </xs:choice> 
    </xs:complexType> 

    <xs:complexType name="HMIVisuObject_type"> 
     <xs:choice maxOccurs="unbounded"> 
     <xs:element name="tagname" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="x" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="y" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="h" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="w" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="role" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="type" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="rotation" minOccurs="1" maxOccurs="1"/> 
     </xs:choice> 
     <xs:attribute name="Name" type="xs:string" use="required"/> 
     <xs:attribute name="RefBaseSystemUnitPath" type="xs:string" use="required"/> 
     <xs:attribute name="ID" type="xs:string" use="required"/> 
    </xs:complexType> 

    <xs:complexType name="HMIVisuObjectTextBox_type"> 
     <xs:complexContent> 
     <xs:extension base="HMIVisuObject_type"> 
      <xs:choice maxOccurs="unbounded"> 
       <xs:element name="text" minOccurs="1" maxOccurs="1"/> 
      </xs:choice> 
     </xs:extension> 
     </xs:complexContent> 
    </xs:complexType> 
    <xs:complexType name="HMIVisuObjectTextBoxTermination_type"> 
     <xs:complexContent> 
     <xs:extension base="HMIVisuObjectTextBox_type"> 
      <xs:choice maxOccurs="unbounded"> 
      </xs:choice> 
     </xs:extension> 
     </xs:complexContent> 
    </xs:complexType> 
    <xs:complexType name="HMIGraphic_type"> 
     <xs:choice maxOccurs="unbounded"> 
     <xs:element name="HMIVisuObject" type="HMIVisuObject_type" minOccurs="0"/> 
     <xs:element name="HMIVisuObjectTextBox" 
        type="HMIVisuObjectTextBox_type" 
        minOccurs="0"/> 
     <xs:element name="HMIVisuObjectTextBoxTermination" 
        type="HMIVisuObjectTextBoxTermination_type" 
        minOccurs="0"/> 
     <xs:element name="h" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="w" minOccurs="1" maxOccurs="1"/> 
     </xs:choice> 
     <xs:attribute name="Name" type="xs:string" use="required"/> 
     <xs:attribute name="RefBaseSystemUnitPath" type="xs:string" use="required"/> 
     <xs:attribute name="ID" type="xs:string" use="required"/> 
    </xs:complexType> 

    <xs:element name="CAEXFile"> 
     <xs:complexType> 
     <xs:all> 
      <xs:element name="HMI" type="HMI_type" minOccurs="0"/> 
     </xs:all> 
     <xs:anyAttribute processContents="skip"/> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

的问题是,当过我运行验证,找到类型的元素HMIVisuObjectTextBoxTermination_type我得到一个错误,说文本不允许作为元素。

输出/ To_Check.aml:15:元素文本:模式有效性错误:元素'文本':该元素不是期望的。预期是(标记名,x,y,h,w,角色,类型,旋转)之一。

所以基本上只有这个类型链的根元素的元素。我做错了什么,我怎么能解决这个问题。

由于提前

+0

添加了这两个文件。我希望它有帮助。 – Tyreal

回答

0

你的复杂类型HMIVisuObjectTextBoxTermination_type可能有一个有效的内容模型这是不是你期待什么。在XSD 1.0中,复杂类型的扩展会创建一个序列,首先包含基本类型的内容模型,然后是扩展添加的材料。 (有些人认为这很有帮助,认为这与在结构的末尾添加新字段类似,用于扩展OO语言中的基类。)由于您有扩展名的扩展名,因此您的效果:

<xs:sequence> 
    <!--* complex type HMIVisuObjectTextBox_type *--> 
    <xs:sequence> 
    <!--* complex type HMIVisuObject_type *--> 
    <xs:choice maxOccurs="unbounded"> 
     <xs:element name="tagname" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="x" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="y" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="h" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="w" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="role" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="type" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="rotation" minOccurs="1" maxOccurs="1"/> 
    </xs:choice> 
    <xs:choice maxOccurs="unbounded"> 
     <xs:element name="text" minOccurs="1" maxOccurs="1"/> 
    </xs:choice> 
    </xs:sequence> 
    <xs:choice maxOccurs="unbounded"> 
    </xs:choice> 
</xs:sequence> 

有效实例必须包含其是三个子序列的串联元件的序列,其匹配:

  • 第一一个或多个标记名,X,Y的,H,W,角色,类型或旋转,后跟
  • 一个或多个文字,后跟
  • 一个或多个空集。

您在这里有两个问题:首先,你的XML来看,你预计text被添加到该组可能孩子在重复的选择,而不是被要求来所有的人后。其次,当下一个输入项与其子项中的某一个相匹配时,内容模型中的选择得以满足;一个空的选择没有孩子,所以没有任何东西可以匹配任何一个。如果选择是必需的,作为该序列的第三选择,则选择是不可满足的。这意味着它的包含序列是不可满足的,这意味着它的包含序列是不可满足的,这意味着类型HMIVisuObjectTextBoxTermination_type没有有效的实例。给出选择minOccurs="0"将允许该类型具有有效的实例,但它们不会被允许具有第一个text元素。

[附录] OP问:“那么,有没有一种方式,而不是试图让我的XSLT递归中,我复制了父母的所有属性的方式,并创建一个新的类型...?我基本上要do实际上是将文本添加到选项列表中,因为它们都需要以xml存在,但它们可以以任何顺序存在。“

几种可能的方法提供自己:

  • 指定为孩子们一个固定的顺序。如果孩子的顺序是固定的,那么类型推导问题就变得微不足道了。

    所以我会非常仔细地研究儿童的秩序必须不受限制的前提;这比声称要多得多。如果儿童的序列携带信息(如通常在自然语言文件中所做的那样),这是真的;怀疑序列是否不包含信息。

  • 为HMIVisuObject_type,HMIVisuObjectTextBox_type等中的选项定义命名的模型组。在相应的命名模型组中定义各种类型的问题。

    <xs:group name="A"> 
        <xs:element ref="tagname"/> 
        <xs:element ref="x"/> 
        <xs:element ref="y"/> 
        ... 
    </ 
    <xs:group name="B"> 
        <xs:element ref="text"/> 
        ... 
    </ 
    <xs:group name="C"> 
        ... 
    </ 
    
    <xs:complexType name="HMIVisuObject_type"> 
        <xs:choice minOccurs="0" maxOccurs="unbounded" ref="A"/> 
        ... 
    </ 
    <xs:complexType name="HMIVisuObjectTextBox_type"> 
        <xs:choice minOccurs="0" maxOccurs="unbounded"> 
        <xs:choice ref="A"/> 
        <xs:choice ref="B"/> 
        </ 
        ... 
    </ 
    <xs:complexType name="HMIVisuObjectTextBoxTermination_type"> 
        <xs:choice minOccurs="0" maxOccurs="unbounded"> 
        <xs:choice ref="A"/> 
        <xs:choice ref="B"/> 
        <xs:choice ref="C"/> 
        </ 
        ... 
    </ 
    

    这显示出三种类型之间的关系清楚地给读者,并避免了同一事物的多个规格。它没有通过类型之间的基类型/派生类型关系来展示关系,并且在某些环境中,它会减少帮助。 (但是如果你依赖于一个面向OO类系统的映射,你将不会首先使用可重复的选择,所以对你来说可能并不重要,尽管这对某些用户很重要。)

  • 反转类型层次结构:将最包含的类型定义为类型,将其他类型定义为它的限制。

    这展示了使用基本/派生链接的类型之间的关系,但是定向链接可能不是您想要的方向。

  • 如果您使用的是XSD 1.1,请将这些类型的选项替换为所有组;在XSD 1.1中,由所有组扩展的所有组的基本类型会生成较大的所有组。

+0

这听起来不太好,但迄今为止感谢! 好的空集可以在我的XSLT中修复。但是这并不能解决我的问题。 那么有没有另一种方法比尝试使我的XSLT递归方式,我复制所有的父母属性和创建一个新的类型,忘记解决方案? 我基本上想要做的事实上是将文本添加到选项列表中,因为它们都需要以xml存在,但它们可以以任何顺序存在。 – Tyreal