Можно ли создать что-то похожее на шаблонный класс в схеме XSD? - PullRequest
0 голосов
/ 22 декабря 2018

Я настраиваю схему 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...