簡體   English   中英

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:assertxs: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-checkinghttp://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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM