我正在尝试生成一个XSD来验证深度未知的XML。这是通过XML中的XSLT完成的。 XML有点像类描述,每个节点都包含有关属性和子项的信息。 XSD必须检查包含实例的另一个XML。所以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 类型的元素时,我收到一条错误,指出 text 不允许作为元素。
输出/ To_Check.aml:15:元素文本:架构有效性错误:元素'text':不期望此元素。预期是(标记名,x,y,h,w,角色,类型,旋转)之一。
所以基本上只有这个类型链的根元素的元素。我做错了什么,我怎么能解决这个问题。
先谢谢
答案 0 :(得分: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>
有效实例必须包含三个子序列的串联元素序列,它们匹配:
这里有两个问题:首先,根据您的XML判断,您希望将text
添加到可重复选择中的可能子项集中,而不是要求在所有其他子项之后。其次,当下一个输入项与其子项之一匹配时,满足内容模型中的选择;一个空的选择没有孩子,所以没有什么可以匹配他们中的任何一个。如果需要选择,作为此序列中的第三选择,则选择是不可满足的。这意味着它的包含序列是不可满足的,这反过来意味着它的包含序列是不可满足的,这反过来意味着类型HMIVisuObjectTextBoxTermination_type
没有有效的实例。选择minOccurs="0"
将允许类型具有有效实例,但不允许他们将text
元素放在首位。
[附录] OP问及#34;那么还有另一种方法,试图以我复制所有父属性并创建新类型的方式使我的XSLT递归...?我基本上想要做的是将文本添加到选项列表中,因为它们都需要存在于xml中,但它们可以按任何顺序排列。&#34;
有几种可能的方法可供选择:
为子项指定固定序列。如果修复了子序列,则类型派生问题变得微不足道。
因此,我要非常仔细地检查儿童的秩序必须不受约束的前提;声称这比它的真实情况要频繁得多。如果儿童的序列携带信息(正如通常在自然语言文件中所做的那样),那都是正确的;如果序列没有携带信息,它会怀疑。
为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,请将这些类型中的选项替换为all-groups;在XSD 1.1中,具有all-group的基类型由all-group扩展,产生更大的all-group。