XSD 确保每个枚举值只能作为属性出现一次

XSD assuring that each enumeration value can only occur once as attribute

假设我有一个架构来定义文章列表。这些文章中的每一篇都有一个长名称列表,每个名称对应一种已知语言。语言是个体长名级别的属性。

我想保证两件事:

  1. 语言属性只能有几个预先确定的值之一(使用枚举解决)。
  2. 在每个 list 长名称中,语言属性的给定值只能出现一次。每篇文章我只能有一个英文长名,一个德文长名,一个法文长名等等

在另一个 post (link) 之后,我在 longName 级别实现了一个唯一约束。它将满足#1,但不满足#2。如果我在同一个 longNames 元素中有两倍于 longName 属性的 'EN',它将认为 xml 有效。

原始样本XML

<article>
        <articleNumber>3019</articleNumber>
        <longNames>
            <longName language="EN">
                <description>A French Omelette with Cheese</description>
            </longName>
            <longName language="FR">
                <description>Un omelette DU(???) fromage</description>
            </longName>
        </longNames>
    </article>

原始XSD架构

    <xs:complexType name="ArticleType">
    <xs:sequence>
        <xs:element name="articleNumber" type="xs:integer" />
        <xs:element type="bl:LongNamesType" name="longNames" />
        <xs:element type="bl:ShortNameType" name="shortName" maxOccurs="3" />
        <xs:element type="bl:AllergensType" name="allergens" maxOccurs="3" />
        <xs:element type="bl:IngredientsType" name="ingredients" maxOccurs="3" />
        <xs:element type="bl:PictureType" name="picture" maxOccurs="3" />
        <xs:element name="barcode" type="xs:integer"/>
    </xs:sequence>
</xs:complexType>

<xs:complexType name="LongNamesType">
    <xs:sequence>
        <xs:element name="longName" maxOccurs="unbounded">
            <xs:complexType>
                <xs:sequence>
                    <!-- <xs:element type="bl:LanguageType" name="language" /> -->
                    <xs:element name="description" type="xs:string" />
                </xs:sequence>
                <xs:attribute name="language" use="required">
                    <xs:simpleType>
                        <xs:restriction base="xs:string">
                            <xs:enumeration value="EN" />
                            <xs:enumeration value="FR" />
                            <xs:enumeration value="DE" />
                        </xs:restriction>
                    </xs:simpleType>
                </xs:attribute>
            </xs:complexType>
            <xs:unique name="uniqueLongNameLanguage">
                <xs:selector xpath="longNames" />
                <xs:field xpath="@language" />
            </xs:unique>              
        </xs:element>
    </xs:sequence>
</xs:complexType>

谁能帮我弄清楚我做错了什么?


编辑:感谢 Yitzak Khabinsky 和 ​​Michael Kay,我设法找到了以下可行的解决方案。诚然,它有点混合了多种风格。感谢所有回复的人!

改进XSD

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema
    xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"
        xmlns:bl="urn:inventoryinput"
        targetNamespace="urn:inventoryinput">

<xs:element name="inventory" type="bl:InventoryType" />
    <xs:complexType name="InventoryType">
            <xs:sequence>
                <xs:element type="bl:ArticleType" name="article"  maxOccurs="unbounded" />
            </xs:sequence>
    </xs:complexType>
        
    <xs:complexType name="ArticleType">
        <xs:sequence>
            <xs:element name="articleNumber" type="xs:integer" />
            <xs:element ref="bl:longNames" minOccurs="0" />
            <xs:element name="barcode" type="xs:integer"/>
        </xs:sequence>
    </xs:complexType>
    
    <xs:element name="longNames">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="bl:longName" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
        <xs:unique name="uniqueLongNameLanguage">
            <xs:selector xpath="bl:longName" />
            <xs:field xpath="@language" />
        </xs:unique>              
    </xs:element>
    
    <xs:element name="longName" >
      <xs:complexType>
        <xs:sequence>
            <xs:element name="description" type="xs:string" />
        </xs:sequence>
        <xs:attribute name="language" use="required">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="NL" />
                    <xs:enumeration value="FR" />
                    <xs:enumeration value="DE" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
    </xs:complexType>
  </xs:element>

...

修改了 XML 示例

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<inventory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:inventoryinput">

        <article>
            <articleNumber>3019</articleNumber>
            <longNames>
                <longName language="NL">
                    <description>DE TROG Ardeens bruin brood Bio 600g</description>
                </longName>
                <longName language="FR">
                    <description>DE TROG pain ardennais complet Bio 600g</description>
                </longName>
            </longNames>

请尝试以下解决方案。

输入XML

<article>
    <articleNumber>3019</articleNumber>
    <longNames>
        <longName language="EN">
            <description>A French Omelette with Cheese</description>
        </longName>
        <longName language="FR">
            <description>Un omelette DU(???) fromage</description>
        </longName>
    </longNames>
</article>

XSD

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="article">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="articleNumber"/>
                <xs:element ref="longNames"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="articleNumber" type="xs:integer"/>
    <xs:element name="longNames">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" ref="longName"/>
            </xs:sequence>
        </xs:complexType>
        <xs:unique name="uniqueLongNameLanguage">
            <xs:selector xpath="longName"/>
            <xs:field xpath="@language"/>
        </xs:unique>
    </xs:element>
    <xs:element name="longName">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="description"/>
            </xs:sequence>
            <xs:attribute name="language" use="required">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:enumeration value="EN"/>
                        <xs:enumeration value="FR"/>
                        <xs:enumeration value="DE"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:attribute>
        </xs:complexType>
    </xs:element>
    <xs:element name="description" type="xs:string"/>
</xs:schema>