Я настраиваю схему XSD, чтобы пользователи могли задавать условия в XML, которые будут использоваться для проверки документа.Документ содержит несколько комплектов, каждый из которых содержит несколько полей.Я хочу, чтобы пользователь мог указать, когда должен существовать определенный набор или поле, выполнив что-то вроде:
<field name="A">
<!-- field A must exist if field X has value 746 -->
<condition>
<if field="X" value="746"/>
</condition>
</field>
<field name="B">
<!-- field B must exist if field Y exists and field Z exists -->
<condition>
<and>
<if field="Y"/>
<if field="Z"/>
</and>
</condition>
</field>
<set name="C">
<!-- set C must exist if field B of set D has value 55 -->
<condition>
<if set="D" field="B" value="55"/>
</condition>
</set>
У меня есть все типы, настроенные для логических и условных операторов, а также для условияэлементы;они выглядят так:
<complexType name="Conditional">
<xs:attribute name="value" type="xs:string"/>
<xs:attribute name="field" type="xs:string"/>
<xs:attribute name="set" type="xs:string"/>
</complexType>
<complexType name="Logical">
<xs:sequence>
<xs:element name="if" type="n:Conditional" minOccurs="2"/>
</xs:sequence>
</complexType>
<xs:complexType name="Condition">
<xs:choice>
<xs:element name="if" type="n:Conditional"/>
<xs:element name="and" type="n:Logical"/>
<xs:element name="or" type="n:Logical"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="Field">
<xs:sequence>
<xs:element name="condition" type="n:Condition"/>
<xs:sequence>
<xs:attribute name="name"/>
</xs:complexType>
<xs:complexType name="Set">
<xs:sequence>
<xs:element name="condition" type="n:Condition"/>
<xs:sequence>
<xs:attribute name="name"/>
</xs:complexType>
Проблема с текущей схемой заключается в том, что она позволяет пользователям указывать атрибут «set» для условия в элементе поля, что я не хочу допускать.Я также хотел бы применить атрибут «set» как обязательный для условий в элементе set (в то время как атрибут «field» остается необязательным) и обеспечить атрибут «field» как обязательный для условий в элементе field.Естественно, это приводит меня к абстрактному базовому классу;что-то вроде:
<complexType name="ConditionalBase" abstract="true">
<xs:attribute name="value" type="xs:string"/>
<xs:attribute name="not" type="xs:boolean"/>
</complexType>
<complexType name="FieldConditional">
<complexContent>
<xs:extension base="n:ConditionalBase">
<xs:attribute name="field" type="xs:string" use="required"/>
</xs:extension>
</complexContent>
</complexType>
<complexType name="SetConditional">
<complexContent>
<xs:extension base="n:ConditionalBase">
<xs:attribute name="set" type="xs:string" use="required"/>
<xs:attribute name="field" type="xs:string"/>
</xs:extension>
</complexContent>
</complexType>
<complexType name="FieldLogical">
<xs:sequence>
<xs:element name="if" type="n:FieldConditional" minOccurs="2"/>
</xs:sequence>
</complexType>
<complexType name="SetLogical">
<xs:sequence>
<xs:element name="if" type="n:SetConditional" minOccurs="2"/>
</xs:sequence>
</complexType>
<xs:complexType name="FieldCondition">
<xs:choice>
<xs:element name="if" type="n:FieldConditional"/>
<xs:element name="and" type="n:FieldLogical"/>
<xs:element name="or" type="n:FieldLogical"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="SetCondition">
<xs:choice>
<xs:element name="if" type="n:SetConditional"/>
<xs:element name="and" type="n:SetLogical"/>
<xs:element name="or" type="n:SetLogical"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="Field">
<xs:sequence>
<xs:element name="condition" type="n:FieldCondition"/>
<xs:sequence>
<xs:attribute name="name"/>
</xs:complexType>
<xs:complexType name="Set">
<xs:sequence>
<xs:element name="condition" type="n:SetCondition"/>
<xs:sequence>
<xs:attribute name="name"/>
</xs:complexType>
Это работает, но неуклюже - я должен определить типы «Логический» и «Условие» дважды, даже если их поведение идентично.Это особенно расстраивает, так как я планирую добавить условия для большего количества типов сегментов документа позже.Есть ли способ справиться с этим более элегантно, подобно тому, как функции шаблона работают, например, в C ++?Другими словами, могу ли я определить свои типы "Logical" и "Condition" так, чтобы я мог сделать что-то вроде:
<complexType name="ConditionalBase" abstract="true">
<xs:attribute name="value" type="xs:string"/>
<xs:attribute name="not" type="xs:boolean"/>
</complexType>
<complexType name="FieldConditional">
<complexContent>
<xs:extension base="n:ConditionalBase">
<xs:attribute name="field" type="xs:string" use="required"/>
</xs:extension>
</complexContent>
</complexType>
<complexType name="SetConditional">
<complexContent>
<xs:extension base="n:ConditionalBase">
<xs:attribute name="set" type="xs:string" use="required"/>
<xs:attribute name="field" type="xs:string"/>
</xs:extension>
</complexContent>
</complexType>
<xs:complexType name="Logical" template="T">
<!-- maybe it would look something like this... -->
<xs:sequence>
<xs:element name="if" type="T" minOccurs="2"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Condition" template="T">
<!-- maybe it would look something like this... -->
<xs:choice>
<xs:element name="if" type="T"/>
<xs:element name="and" type="n:Logical<T>"/>
<xs:element name="or" type="n:Logical<T>"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="Field">
<xs:sequence>
<xs:element name="condition" type="n:Condition<FieldConditional>"/>
<xs:sequence>
<xs:attribute name="name"/>
</xs:complexType>
<xs:complexType name="Set">
<xs:sequence>
<xs:element name="condition" type="n:Condition<SetConditional>"/>
<xs:sequence>
<xs:attribute name="name"/>
</xs:complexType>