Ответ 1
Ваш код должен быть действительным в XSD 1.1. Для XSD 1.0 вы должны найти обходное решение.
Я определяю элемент пользователя с XSD. В этом примере пользователь имеет имя, адрес электронной почты и одну или несколько национальностей. Я пробовал:
<xs:all>
<xs:element name="name" blabla />
<xs:element name="email" blabla />
<xs:element name="nationality" minOccurs="1" maxOccurs="unbounded" />
</xs:all>
Однако это незаконно. По-видимому, элементы внутри "Все" могут возникать только один раз (или совсем не). Я мог бы исправить это, изменив All to a Sequence, но тогда люди должны были бы ввести свойства в точный порядок, на который мне на самом деле все равно.
Есть ли комбинация этих двух доступных? Не в соответствии с http://www.w3schools.com/Schema/schema_complex_indicators.asp, но, возможно, он скрыт (или мои неопытные глаза его не видят).
По интуиции я также пробовал:
<xs:all>
<xs:element name="name" blabla />
<xs:element name="email" blabla />
<xs:sequence>
<xs:element name="nationality" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:all>
Но это, к сожалению, недействительно.
Вот текущая, настоящая, часть XSD:
<!-- user -->
<xs:complexType name="user">
<xs:sequence>
<xs:element name="firstname" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="appendix" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="lastname" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="address" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="zipcode" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="city" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="username" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="email" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="country" type="country" minOccurs="1" maxOccurs="1"/>
<xs:element name="nationality" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
Ваш код должен быть действительным в XSD 1.1. Для XSD 1.0 вы должны найти обходное решение.
Не могли бы вы просто превратить свою "национальность" в свой собственный complexType, а затем использовать этот новый сложный тип внутри xs: all?
<xs:complexType name="NationalityType">
<xs:sequence>
<xs:element name="nationality" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:all>
<xs:element name="name" blabla />
<xs:element name="email" blabla />
<xs:element name="nationalities" type="NationalityType" />
</xs:all>
У меня нет ничего под рукой, чтобы проверить это, так что это действительно просто с моей головы..... дайте ему попробовать!
EDIT: протестировал его к настоящему времени - он работает, единственная небольшая цена, которую нужно заплатить, заключается в том, что ваш XML будет выглядеть примерно так:
<....>
<email>......</email>
<nationalities>
<nationality>ABC</nationality>
<nationality>CDE</nationality>
</nationalities>
<name>.....</name>
</.....>
Итак, вы получаете дополнительный node, который будет содержать произвольный длинный список элементов <nationality>
.
Марк
Просто сталкивайтесь с аналогичной проблемой (я хотел иметь любое количество каждого элемента в любом порядке) и решил ее с помощью последовательности вариантов. Используя приведенный выше пример:
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name='user'>
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="name" type="xs:string" />
<xs:element name="email" type="xs:string" />
<xs:element name="nationality" />
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Это позволяет вам иметь любое количество имен, электронной почты и гражданства в любом порядке.
Я думаю, что то, что вы ищете, будет противоречить намерениям XML. Казалось бы странным иметь правильный XML-фрагмент, подобный этому:
<user>
<nationality/>
<name/>
<nationality/>
<email/>
<nationality/>
</user>
Похоже, вы просите что-то вроде того, что предложили marc_s:
<user>
<name/>
<email/>
<nationality/>
<nationality/>
<nationality/>
<user>
который нужно вставить:
<user>
<name/>
<email/>
<nationalities>
<nationality/>
<nationality/>
<nationality/>
</nationalities>
<user>
Для XSD 1.0 предлагается предложение leppie.
XSD
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name='user'>
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" />
<xs:element name="email" type="xs:string" />
<xs:choice minOccurs='0' maxOccurs='unbounded'>
<xs:element name="nationality" />
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Пример XML-документа, который проверяет схему
<user>
<name>Name</name>
<email>[email protected]</email>
<nationality>Italian</nationality>
<nationality>Japanese</nationality>
<nationality>Alien</nationality>
</user>
И подтверждение, например. используя xmllint
xmllint --noout --schema test.xsd test.xml
test.xml validate
Или, поскольку "USER" будет настроен с несколькими дочерними элементами, почему бы не настроить его как сложный тип? Что-то вроде этого должно работать.
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="xs:string" />
<xs:element name="Password" type="xs:string" />
<xs:element minOccurs="1" maxOccurs="unbounded" name="Nationality" type="xs:string" />
</xs:sequence>
</xs:complexType>
xs:choice
Не работает? Если нет, просто оберните это в последовательности или наоборот.