如何为实例文档指定XML模式,如下所示:
<productinfo>
<!-- other stuff -->
<informationset type="Manufacturer">
<!-- content not relevant -->
</informationset>
<informationset type="Ingredients">
<!-- content not relevant -->
</informationset>
</productinfo>
即包含两个“信息集”子项序列的“productinfo”元素,第一个包含@type="Manufacturer"
,第二个包含@type="Ingredients"
?
答案 0 :(得分:3)
注意这个答案是不正确的,正如Serge指出的那样。
使用 xerces进行测试会出现此错误:type.xsd:3:21: cos-element-consistent: Error for type '#AnonType_productinfo'. Multiple elements with name 'informationset', with different types, appear in the model group.
cos-element-consistent的规范中有更多详细信息。
但是有一个解决方案,类似于下面Marc的答案,但仍然使用类型。如果它们位于超类型的minOccurs / maxOccurs列表中,则可以多次出现相同的不同类型,这些列表由其他类型扩展。也就是说,就像java或C#中的多态类列表一样。这克服了上面的问题,因为尽管该元素名称可以在xml中出现多次,但它只在xsd中出现一次。
以下是xsd和xml示例 - 这次使用 xerces 进行测试!:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="productinfo">
<xs:complexType>
<xs:sequence>
<xs:element name="informationset" type="supertype" minOccurs="2" maxOccurs="2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="supertype">
</xs:complexType>
<xs:complexType name="Manufacturer">
<xs:complexContent>
<xs:extension base="supertype">
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Ingredients">
<xs:complexContent>
<xs:extension base="supertype">
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
<productinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<informationset xsi:type="Manufacturer"></informationset>
<informationset xsi:type="Ingredients"></informationset>
</productinfo>
注意:您无法控制不同类型的订单,或每种类型出现的次数(每种类型可能出现一次,多次或根本不出现) - 就像java或C#中的多态类列表。但是你至少可以指定整个列表的确切长度(如果你愿意)。
例如,我已将上述示例限制为两个元素,但未设置顺序(即制造商可以是第一个,或者成分可以是第一个);并且没有设置重复次数(即它们可以是制造商,或者两者都是成分,或者两者之一)。
您可以使用XML Schema type ,如:
<productinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<informationset xsi:type="Manufacturer"></informationset>
<informationset xsi:type="Ingredients"></informationset>
</productinfo>
XSD为每一个定义了单独的复杂类型:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="productinfo">
<xs:complexType>
<xs:sequence>
<xs:element name="informationset" type="Manufacturer"/>
<xs:element name="informationset" type="Ingredients"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Manufacturer">
</xs:complexType>
<xs:complexType name="Ingredients">
</xs:complexType>
</xs:schema>
这是xsi:type
的一个特例。通常,不要认为您可以指定属性在同一个元素的元素中具有不同的值,因为它们是同一元素的不同定义。
我不是100%明确原因 - 任何人都知道规范的相关部分吗?
答案 1 :(得分:2)
您可以尝试这样的方法 - 为“informationSet”元素创建单独的complexType,并将属性限制为有效字符串列表:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="productinfo">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded"
name="informationset" type="informationSetType" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="informationSetType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="type" type="validAttributeType" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="validAttributeType">
<xs:restriction base="xs:string">
<xs:enumeration value="Manufacturer" />
<xs:enumeration value="Ingredients" />
</xs:restriction>
</xs:simpleType>
</xs:schema>
当然,如果您愿意,可以扩展有效属性名称列表 - 只需在限制枚举列表中添加更多元素。
马克
答案 2 :(得分:1)
感谢 XML Schema 1.1 ,有一种方法可以强制执行您的需求,而无需将xsi
命名空间和hack多态性导入XML文档。 XML Schema 1.1带来了两个新组件assertions和type alternatives,提供了xs:assert
和xs:alternative
元素。它们具有@test
属性,其中条件和约束被指定为 XPath 2.0表达式。
即使xs:alternative
显然是你问题的解决方案,但就我而言,我还没有成功地根据元素的位置分配替代类型。 (模式解析器对节点上下文的理解似乎与我根据经验证的XML文档结构所预期的不同。)
无论如何,您可以使用xs:assert
强制执行约束:
<xs:element name="productinfo">
<xs:complexType>
<xs:sequence minOccurs="2" maxOccurs="unbounded">
<xs:element name="informationset">
<xs:complexType>
<xs:attribute name="type" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Manufacturer" />
<xs:enumeration value="Ingredients" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:assert test="informationset[1]/@type='Manufacturer'" xpathDefaultNamespace="##targetNamespace"/>
<xs:assert test="informationset[2]/@type='Ingredients'" xpathDefaultNamespace="##targetNamespace"/>
</xs:complexType>
</xs:element>
如果架构的命名空间为空,则可能不需要使用属性@xpathDefaultNamespace
,但如果架构定义了一个,则必须设置为##targetNamespace
,否则评估元素名称将失败。
注意:显然,要使其工作,必须使用支持XML Schema 1.1的验证器。使用OxygenXML时,您只需在 XML / XML Parser / XML Schema 首选项页面中将默认XML架构版本设置为1.1。使用Xerces作为验证器时,必须激活additional feature:
http://apache.org/xml/features/validation/cta-full-xpath-checking
。否则,它将无法评估您提出的大部分XPath,因为默认情况下它使用的子集不足。
答案 3 :(得分:0)
可能是http://xsd.stylusstudio.com/2001Aug/post03013.htm正是您要找的。 p>
答案 4 :(得分:0)
在VS中,报告错误:具有相同名称且在相同范围内的元素必须具有相同的类型。
我认为XSD无法满足您的要求,您可以尝试从另一个方向解决它。例如,使用xslt来验证XML。 XSLT是基于xpath和规则的,它可以检查xml中的每个位置
XSD + XSLT是一个很好的解决方案,XSD用于模式检查,XSLT用于信息检查。