![](/img/trans.png)
[英]How to define a sequence of elements with same name but different types in XML Schema?
[英]XML Schema for sequence of elements with same name but different attribute values?
如何為實例文檔指定XML模式,如下所示:
<productinfo>
<!-- other stuff -->
<informationset type="Manufacturer">
<!-- content not relevant -->
</informationset>
<informationset type="Ingredients">
<!-- content not relevant -->
</informationset>
</productinfo>
也就是說,“productinfo”元素包含兩個“信息集”子節點的序列,第一個具有@type="Manufacturer"
,第二個具有@type="Ingredients"
?
注意這個答案是不正確的,正如塞爾指出的那樣。
使用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.
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 類型 ,如下所示:
<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%明確的原因 - 任何人都知道規范的相關部分?
你可以嘗試這樣的事情 - 為你的“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>
當然,如果您願意,可以擴展有效屬性名稱列表 - 只需在限制枚舉列表中添加更多元素。
渣
由於XML Schema 1.1 ,有一種方法可以強制執行您的需求,而無需將xsi
命名空間和hack多態導入XML文檔。 XML Schema 1.1帶來了兩個新組件, 斷言和類型替代 ,提供了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>
如果模式的命名空間為null,則可能不需要使用屬性@xpathDefaultNamespace
,但如果模式定義了一個,則必須將其設置為##targetNamespace
,否則元素名稱的評估將失敗。
注意:顯然,要使其工作,必須使用支持XML Schema 1.1的驗證器。 使用OxygenXML時,您只需在XML / XML Parser / XML Schema首選項頁面中將默認XML架構版本設置為1.1。 使用Xerces作為驗證器時,必須激活其他功能 :
http://apache.org/xml/features/validation/cta-full-xpath-checking
:http://apache.org/xml/features/validation/cta-full-xpath-checking
。 否則,它將無法評估您提出的大多數XPath,因為默認情況下它使用的子集不足。
在VS中,報告錯誤: 具有相同名稱且在相同范圍內的元素必須具有相同的類型。
我認為XSD無法滿足您的要求,您可以嘗試從另一個方向解決它。例如,使用xslt來驗證XML。 XSLT是基於xpath和規則的,它可以檢查xml中的每個位置。
XSD + XSLT是一個很好的解決方案,XSD用於模式檢查,XSLT用於信息檢查。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.