XML Schema - only one element should have attribut

2019-04-07 04:22发布

问题:

How can i define an boolean attribute that can be set "true" only in one element. Following snippet must be invalid.

<products>
  <product featured="yes">Prod 1</product>
  <product featured="yes">Prod 2</product>
</products>

回答1:

You can't do that with XML Schemas.

You can define attributes on an element, but not limit them to one instance of the element.



回答2:

You could add an attribute in products element indicating which product is featured.



回答3:

You can't do this with XMLSchema. If you want to specify these constraints in an XML environment try Schematron (http://www.schematron.com/).



回答4:

You could do the following...

<products>
    <product featured="Yes">Prod 1</product>
    <product>Prod 2</product>
</products>

Then use a unique element to constrain the attribute thus...

<xs:unique name="UniqueFeaturedProduct">
      <xs:selector xpath="product"/>
      <xs:field xpath="@featured"/>
</xs:unique>

If you were to restrict the 'featured' attribute to an optional enumeration of one value "Yes" then there could only be one featured attribute. Something like this...

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="products">   
        <xs:complexType>
            <xs:sequence>
                <xs:element name="product" type="productType" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
        <xs:unique name="UniqueFeaturedProduct">
            <xs:selector xpath="product"/>
            <xs:field xpath="@featured"/>
        </xs:unique>
    </xs:element>
    <xs:simpleType name="featuredType">
        <xs:restriction base="xs:string">
            <xs:enumeration value="Yes"/>
        </xs:restriction>
    </xs:simpleType>
    <xs:complexType name="productType">
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attribute name="featured" type="featuredType" use="optional"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>
</xs:schema>


回答5:

My reply is this way, 'cause I cannot add comments yet.

"You could add an attribute in products element indicating which product is featured."

This solution lead to another problem: checking if the attribute points to existing element.

<products featured_id="3">
  <product id="1">Prod 1</product>
  <product id="2">Prod 2</product>
</products>