我正在尝试为以下XML构建XSD:
<?xml version="1.0" encoding="UTF-8"?>
<people xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="people.xsd">
<student>
<name>John</name>
<study_year>4</study_year>
<study_level>A+</study_level>
<age>21</age>
</student>
<tutor>
<name>Thomas</name>
<salary>2300</salary>
<age>45</age>
<expertise>Math</expertise>
</tutor>
<student>
<name>Mike</name>
<study_level>B-</study_level>
<age>20</age>
<study_year>22</study_year>
</student>
</people>
目前我有这个XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="people">
<xs:complexType>
<xs:sequence maxOccurs="1">
<xs:choice maxOccurs="unbounded">
<xs:element maxOccurs="unbounded" minOccurs="1" name="student">
<xs:complexType>
<xs:sequence maxOccurs="1">
<xs:group ref="person"/>
<xs:element name="study_year"/>
<xs:element name="study_level"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element maxOccurs="unbounded" minOccurs="1" name="tutor">
<xs:complexType>
<xs:sequence maxOccurs="1">
<xs:group ref="person"/>
<xs:element name="salary"/>
<xs:element name="expertise"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:group name="person">
<xs:sequence>
<xs:element name="name"/>
<xs:element name="age"/>
</xs:sequence>
</xs:group>
</xs:schema>
这只是我试图制作的XSD的一个抽象。我想允许学生和导师之间的任何元素顺序。我还需要xs:group,因为我不想要冗余。
我曾尝试用xs:all替换xs:sequence,但这不是有效的XSD。
是否可以使用XSD来完成此操作?
感谢您的帮助!
不幸的是,根据规范,all
中只能有element
s:http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-所有
我认为没有办法做你想做的事(去掉常见的名字和年龄元素,按任何顺序,只出现一次)。
例如,这里有两种不允许的近似方法:
-
两个CCD_ 4组的CCD_?否,因为
sequence
不能包含all
http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-序列 -
用CCD_ 7?否,因为
all
只能直接出现在group
或complexType
中http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#cos-全部受限(扩展不直接在内部)。尽管从规范来看,你可能会作弊,将all
放在一个组中,并从扩展中引用,但xerces不接受它。
但有三种不同的权衡,可以进行近似:
(1) 。显式枚举的顺序(例如sequences
的choice
:name,age或age,name),并具有它们的序列。因为每个组中只有两个元素,所以它不会爆炸(至少在这个片段中)。它仍然只是一个近似值,而不是您想要的任何顺序(并且不会验证您给出的示例xml):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:group name="person">
<xs:choice>
<xs:sequence>
<xs:element name="name"/>
<xs:element name="age"/>
</xs:sequence>
<xs:sequence>
<xs:element name="age"/>
<xs:element name="name"/>
</xs:sequence>
</xs:choice>
</xs:group>
<xs:element name="people">
<xs:complexType>
<xs:sequence maxOccurs="1">
<xs:choice maxOccurs="unbounded">
<xs:element maxOccurs="unbounded" minOccurs="1" name="student">
<xs:complexType>
<xs:sequence>
<xs:group ref="person"/>
<xs:choice>
<xs:sequence>
<xs:element name="study_year"/>
<xs:element name="study_level"/>
</xs:sequence>
<xs:sequence>
<xs:element name="study_level"/>
<xs:element name="study_year"/>
</xs:sequence>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element maxOccurs="unbounded" minOccurs="1" name="tutor">
<xs:complexType>
<xs:sequence>
<xs:group ref="person"/>
<xs:choice>
<xs:sequence>
<xs:element name="salary"/>
<xs:element name="expertise"/>
</xs:sequence>
<xs:sequence>
<xs:element name="expertise"/>
<xs:element name="salary"/>
</xs:sequence>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
(2) 。或者,你可以放弃只需要一次,并使用允许任何数量的选择的老技巧——然后你可以考虑部分选择:
<xs:choice maxOccurs="unbounded">
<xs:group ref="person"/>
<xs:element name="study_year"/>
<xs:element name="study_level"/>
</xs:choice>
<xs:group name="person">
<xs:choice>
<xs:element name="name"/>
<xs:element name="age"/>
</xs:choice>
</xs:group>
(3) 。因此,似乎最好放弃保理,每次都重复名字和年龄。(听起来你已经不情愿地倾向了)。
我的回答:"不。"你想做这件事是明智的,但我认为这是不可能的。我认为你必须在保理或订购/发生之间做出选择(即,到处都是重复的姓名/年龄;或者要求订购;或者不限制发生)。
虽然这不是一个明确的答案,但希望通过探索各种选择,它能让你对地形有一种感觉。也许这里的一些聪明人可以提出一个变通方法,允许因子分解、非排序和只发生一次(或者给出一个明确的证据,证明不可能有这样的变通方法)。。。?
PS:在任何人编辑之前,我使用了(1).
编号,而不是正确的枚举,因为SO格式化程序被它弄糊涂了,并且没有在第二点内拾取xml代码