В файле XSD необходимо определить:
- родительский тип (который содержит 10 узлов).
- 7 дочерних типов (каждый дочерний тип содержит одинаковые 10 узлов, но тип 2-го узла отличается).
Это можно сделать, определив дочерние типы ограничением родительского типа (родительский тип будет базовым типом для дочерних типов). Проблема: в дочерних типах мне приходится заново прописывать все узлы родительского типа (а не только 2-й узел). Вопрос: Могу ли я написать только тот узел, который переопределяю (второй узел)?
Пример: если я определяю следующий родительский тип:
<xs:complexType name="Parent">
<xs:sequence>
<xs:element name="Node1" type="type1" />
<xs:element name="Node2" type="type2" />
<xs:element name="Node3" type="type3" />
...
<xs:element name="Node10" type="type10" />
</xs:sequence>
</xs:complexType>
тогда я должен определить дочерние элементы по ограничению родителя:
<xs:complexType name="Child1">
<xs:complexContent>
<xs:restriction base="Parent">
<xs:sequence>
<xs:element name="Node1" type="type1" />
<xs:element name="Node2" type="type2_derived_1" />
<xs:element name="Node3" type="type3" />
...
<xs:element name="Node10" type="type10" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Child2">
<xs:complexContent>
<xs:restriction base="Parent">
<xs:sequence>
<xs:element name="Node1" type="type1" />
<xs:element name="Node2" type="type2_derived_2" />
<xs:element name="Node3" type="type3" />
...
<xs:element name="Node10" type="type10" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
...
(same for all the 10 childs)
Это много написанного и ДУБЛИРУЕМОГО кода (для каждого дочернего элемента мне приходится СНОВА писать все исходные узлы, которые уже есть у родителя). Я бы предпочел написать только узел, который я переопределяю, примерно так:
<xs:complexType name="Child1">
<xs:complexContent>
<xs:restriction base="Parent">
<xs:changed>
<xs:element name="Node2" type="type2_derived_1" />
</xs:changed>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Child2">
<xs:complexContent>
<xs:restriction base="Parent">
<xs:changed>
<xs:element name="Node2" type="type2_derived_2" />
</xs:changed>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
...
(same for all the 10 childs)
Есть ли способ избежать дублирования кода? Я использую XSD 1.1, поэтому могу использовать все его расширенные функции.
Я знаю, что могу использовать расширение вместо ограничения: например, я мог бы исключить 2-й узел из родительского типа и добавить его по расширению в дочерние элементы. Но в этом случае это будет не 2-й узел, а 10-й узел. Я хочу переопределить (или добавить) 2-й узел у дочерних элементов.
Обновление: решено. Мне нравится обходной путь, предложенный Спербергом-Маккуином: группы моделей. Группа моделей похожа на макрос в C, ее содержимое расширяется. Таким образом, я могу определить группу моделей для узлов перед измененным узлом и другую группу моделей для узлов после него. Например:
<xs:group name="g_node_1">
<xs:sequence>
<xs:element name="Node1" type="type1"/>
</xs:sequence>
</xs:group>
<xs:group name="g_nodes_3to10">
<xs:sequence>
<xs:element name="Node3" type="type3"/>
<xs:element name="Node4" type="type4"/>
<xs:element name="Node5" type="type5"/>
<xs:element name="Node6" type="type6"/>
<xs:element name="Node7" type="type7"/>
<xs:element name="Node8" type="type8"/>
<xs:element name="Node9" type="type9"/>
<xs:element name="Node10" type="type10"/>
</xs:sequence>
</xs:group>
<xs:complexType name="Parent">
<xs:sequence>
<xs:group ref="g_node_1"/>
<xs:element name="Node2" type="type2"/>
<xs:group ref="g_nodes_3to10"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Child1">
<xs:complexContent>
<xs:restriction base="Parent">
<xs:sequence>
<xs:group ref="g_node_1"/>
<xs:element name="Node2" type="type2_derived_1" />
<xs:group ref="g_nodes_3to10"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Child2">
<xs:complexContent>
<xs:restriction base="Parent">
<xs:sequence>
<xs:group ref="g_node_1"/>
<xs:element name="Node2" type="type2_derived_2" />
<xs:group ref="g_nodes_3to10"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
Это требует на 2 строки больше (на тип), чем идеальное решение, но это лучше, чем ничего.