Проверка XSD: N детей с дополнительными, различными ограничениями

У меня есть XML, который я хочу проверить с помощью XSD. Это на самом деле простой сценарий, но я не мог найти правильный ответ. Это XML:

<data>
 <point>
 <x>count</x>
 <y>218</y>
 </point>
 <point>
 <x>maxtime</x>
 <y>1</y>
 </point>
 <point>
 <x>mintime</x>
 <y>0</y>
 </point>
 <point>
 <x>mean</x>
 <y>0.11</y>
 </point>
</data>

Я хочу убедиться, что элемент данных содержит 4 элемента точки и что существует только один элемент с x element = count, только один с x = maxtime...

Теперь у меня есть следующее:

<xs:schema attributeformdefault="unqualified" elementformdefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="data">
 <xs:complextype>
 <xs:sequence>
 <xs:element name="point" type="ctPoint" minoccurs="1" maxoccurs="4">
 </xs:element></xs:sequence>
 </xs:complextype>
</xs:element>

<xs:complextype name="ctPoint">
 <xs:sequence minoccurs="1" maxoccurs="4">
 <xs:element name="x" minoccurs="1" maxoccurs="1">
 <xs:simpletype>
 <xs:restriction base="xs:string">
 <xs:enumeration value="count">
 <xs:enumeration value="maxtime">
 <xs:enumeration value="mintime">
 <xs:enumeration value="mean">
 </xs:enumeration></xs:enumeration></xs:enumeration></xs:enumeration></xs:restriction>
 </xs:simpletype>
 </xs:element>
 <xs:element name="y" type="xs:decimal" minoccurs="1" maxoccurs="1">
 </xs:element></xs:sequence>
</xs:complextype>
</xs:schema>

Это корректно проверяется, но это не гарантирует, что есть только 1 счет, только 1 maxtime,...

2 ответа

I want to make sure that the data element contains 4 point elements

Это ограничение вы можете сделать просто с XSD 1.0 minOccurs="4" и maxOccurs="4".

и что существует только один элемент с x element = count, только один с x = maxtime...

Это ограничение должно быть сделано вне диапазона (в коде), если вы застряли с XSD 1.0.

[ Обновление: однако, см. Статью @sergioFC о хорошей идее XSD 1.0 о xs:unique если целью является просто, чтобы все значения x были уникальными в пределах data.]

Если вы можете использовать XSD 1.1, как предложил @lexicore, это сработает. Использовать xs:assert:

<xs:element name="data">
 <xs:complextype>
 <xs:sequence>
 <xs:element name="point" type="ctPoint" minoccurs="4" maxoccurs="4">
 </xs:element></xs:sequence>
 <xs:assert test="count(point[x = 'count']) = 1 and
 count(point[x = 'maxtime']) = 1">
 </xs:assert></xs:complextype>
 </xs:element>


Вы можете использовать xs: uniqe, который также действителен в XSD 1.0.

<xs:element name="data">
 <xs:complextype>
 <xs:sequence>
 <xs:element name="point" type="ctPoint" minoccurs="1" maxoccurs="4">
 </xs:element></xs:sequence>
 </xs:complextype>
 <xs:unique name="myUnique">
 <!-- Select all points in data -->
 <xs:selector xpath="point">
 <!-- The value of x of every selected point should be unique -->
 <xs:field xpath="x">
 </xs:field></xs:selector></xs:unique>
</xs:element>

Кроме того, чтобы сделать это, я думаю, вы должны изменить minOccurs, как сказал пользователь kjhughes в своем ответе.

licensed under cc by-sa 3.0 with attribution.