Есть ли какой-либо способ обеспечить уникальность элементов в XML-списке с помощью XSD?

#xml #validation #list #xsd

#xml #проверка #Список #xsd

Вопрос:

У меня есть XML-файл и соответствующий XSD-файл.
В файле XSD я определяю атрибут list, в котором элементы в списке являются частью перечисления.

Вот пример того, что я делаю.

 <xs:simpleType name="Colors">
    <xs:list itemType="ColorEnum"/>
</xs:simpleType>

<xs:simpleType name="ColorEnum">
    <xs:restriction base="xs:token">
        <xs:enumeration value="Red"/>
        <xs:enumeration value="Blue"/>
        <xs:enumeration value="Green"/>
    </xs:restriction>
</xs:simpleType>

<xs:element name="Color">
    <xs:complexType>
        <xs:attribute name="ColorList" type="Colors" />
    </xs:complexType>
</xs:element>
  

XML будет выглядеть примерно так:

 <Color ColorList="Red Blue Green"></Color>
  

Есть ли какой-либо способ убедиться, что элементы в списке уникальны? Например, есть ли какой-либо способ предотвратить попадание Red в этот список дважды?

Ответ №1:

Я думаю, что единственный способ — использовать xsd:pattern . Вы хотите:

 <xs:simpleType name="ColorEnum">
 <xs:restriction base="xs:string">
   <xs:pattern value="(Red){0,1}s(Blue){0,1}s(Green){0,1}"/>
 </xs:restriction>
</xs:simpleType>
  

Это также должно обеспечить соблюдение порядка. Я имею в виду, что вы не можете предоставить последовательность «Синий Зеленый красный». В любом случае это должно быть отправной точкой.


РЕДАКТИРОВАТЬ очень неприятно:

 <xs:simpleType name="ColorEnum">
 <xs:restriction base="xs:string">
   <xs:pattern value="((Red)?s(Blue)?s(Green)?)|((Red)?s(Green)?s(Blue)?)|((Green)?s(Blue)?s(Red)?)|((Green)?s(Red)?s(Blue)?)|((Blue)?s(Green)?s(Red)?)|((Blue)?s(Red)?s(Green)?)"/>
 </xs:restriction>
</xs:simpleType>
  

Редактировать

Количество комбинаций задается факториалом общего количества элементов, которые вы используете в последовательности. Я надеюсь, что тогда вы не превысите трех элементов 🙂

Ответ №2:

В XSD 1.1 (доступен сейчас в Xerces и Saxon) вы можете сделать

 <xs:assertion test="count(tokenize($value, 's ')) = 
                    count(distinct-values(tokenize($value, 's ')))"/>
  

Комментарии:

1. 1 Приятно знать. @webe0316: смотрите ibm.com/developerworks/library/x-xml11pt2

Ответ №3:

Боюсь, что это невозможно с xs:enumeration , вы можете использовать какое-нибудь неприятное регулярное выражение вроде:

   <xs:simpleType name="ColorEnum">
    <xs:restriction base="xs:string">
      <xs:pattern value="(Red)?( Blue)?( Green)?"/>
    </xs:restriction>
  </xs:simpleType>
  

В этом случае порядок элементов фиксирован.