Требуется установить свойство xsd в соответствии со значением перечисления

У меня есть следующий xsd для моего проекта. Я пытаюсь создать один xsd для xmls ACH и CC на основе атрибута enum Payment Method, если метод оплаты Ach, тогда требуется ACHInfo, иначе CreditCardInfo..

<xs:element name="PaymentMethod">
  <xs:simpleType>
    <xs:restriction base="xs:string">
      <xs:enumeration value="ACH"/>
      <xs:enumeration value="CreditCard"/>
    </xs:restriction>
  </xs:simpleType>
</xs:element>
<xs:element name="CreditCardInfo" minOccurs="0">
  <xs:complexType>
    <xs:all>
      <xs:element name="Cvv2No">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="4"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="CardNumber">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="20"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
     </xs:all>
  </xs:complexType>
</xs:element>
<xs:element name="ACHInfo" minOccurs="0">
  <xs:complexType>
    <xs:all>
      <xs:element name="RoutingNumber" nillable="false">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="50"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="AccountNumber" nillable="false">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="50"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
    </xs:all>
  </xs:complexType>
</xs:element>

Может ли кто-нибудь дать мне решение для этого, какие изменения требуются в xsd, чтобы сделать свойство требуемым в соответствии со значением enum

Благодарю.

1 ответ

Решение

Четыре решения, некоторые из которых включают переосмысление представления вашей информации в формате XML:

Утверждение XSD 1.1

Самый простой способ сделать то, что вы описываете, это использовать XSD 1.1 и определить ограничение, которое вы имеете в виду, с помощью утверждения. Вы не говорите, как называется родительский элемент; Я назову это Оплата. И я буду использовать префикс tns для целевого пространства имен.

<xs:element name="Payment">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="tns:PaymentMethod"/>
      <xs:choice>
        <xs:element ref="tns:ACHInfo" minOccurs="0"/>
        <xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
      </xs:choice>
    </xs:sequence>
    <xs:assert test="(tns:PaymentType = 'ACH' and ./tns:ACHInfo)
                     or
                     (tns:PaymentType = 'CreditCard' 
                       and ./tns:CreditCardInfo)"/>
  </xs:complexType>
</xs:element>

Условное присвоение типов XSD 1.1

Для некоторых целей лучше использовать условное присвоение типа (также функция 1.1) для Платежа. По техническим причинам это означает, что PaymentType должен быть атрибутом Payment, а не дочерним элементом:

<xs:element name="Payment">
  <xs:alternative test="@PaymentMethod='ACH'" 
                  type="tns:ACHPayment"/>
  <xs:alternative test="@PaymentMethod='CreditCard'" 
                  type="tns:CCPayment"/>
  <xs:alternative type="xs:error"/>
</xs:element>

Это объявление означает: если значение атрибута PaymentMethod равно "ACH", тогда элемент Payment имеет тип tns:ACHPayment (который мы определим чуть позже). В противном случае, если значением PaymentMethod является "CreditCard", то типом оплаты будет tns: CCPayment. В противном случае элемент недействителен.

Мы объявляем именованные типы ACHPayment и CCPayment как содержащие соответствующие дочерние элементы (а также предоставляя атрибут PaymentMethod) - мы можем встроить их, но присвоение им имен упрощает просмотр шаблона назначения условных типов:

<xs:complexType name="ACHPayment">
  <xs:sequence>
    <xs:element ref="tns:ACHPayment"/>
  </xs:sequence>
  <xs:attribute name="PaymentMethod" type="tns:PaymentMethod"/>
</xs:complexType>

<xs:complexType name="CCPayment">
  <xs:sequence>
    <xs:element ref="tns:CreditCardPayment"/>
  </xs:sequence>
  <xs:attribute name="PaymentMethod" type="tns:PaymentMethod"/>
</xs:complexType>

И по той же причине мы предоставляем именованное объявление для типа атрибута PaymentMethod:

<xs:simpleType name="PaymentMethod">
  <xs:restriction base="xs:string">
    <xs:enumeration value="ACH"/>
    <xs:enumeration value="CreditCard"/>
  </xs:restriction>
</xs:simpleType>

XSD 1.0, перемещение метода оплаты в модель контента

Но вам не нужен XSD 1.1 для создания XML, который работает для вашего приложения; вам просто нужно по-другому думать о вашем дизайне. Легко сделать ACHinfo обязательной для платежей ACH и CreditCardInfo необходимой для платежей кредитной картой, если вы выбираете тип платежа в названии элемента, а не в содержании. Вместо определения родительского типа как:

<xs:complexType>
  <xs:sequence>
    <xs:element ref="tns:PaymentMethod"/>
    <xs:element ref="CreditCardInfo" minOccurs="0"/>
    <xs:element ref="ACHInfo" minOccurs="0"/>
  </xs:sequence>
</xs:complexType>

Вы могли бы объявить это так:

<xs:complexType>
  <xs:choice>
    <xs:sequence>
      <xs:element ref="tns:ACHPayment"/>
      <xs:element ref="tns:ACHInfo" minOccurs="0"/>
    </xs:sequence>
    <xs:sequence>
      <xs:element ref="tns:CCPayment"/>
      <xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
    </xs:sequence>       
  </xs:choice>
</xs:complexType>

Два элемента флага CCPayment и ACHPayment могут быть пустыми элементами:

<xs:complexType name="EMPTY">
  <xs:sequence/>
</xs:complexType>

<xs:element name='ACHPayment' type="tns:EMPTY"/>
<xs:element name='CCPayment' type="tns:EMPTY"/>

Но, поскольку вещи стоят, ни один из них не делает никакой работы в дизайне.

XSD 1.0, упрощение

Если ни элемент ACHPayment, ни элемент CCPayment не выполняют никакой работы, кроме (а) сигнализации о том, что платеж использует этот метод и (б) обеспечения правильности следующего брата, то ни один из них не выполняет никакой работы вообще.,

Вы также можете легко определить родительский элемент следующим образом:

<xs:element name="Payment">
  <xs:complexType>
    <xs:choice>
      <xs:element ref="tns:ACHInfo" minOccurs="0"/>
      <xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
    </xs:choice>
  </xs:complexType>
</xs:element>

Вы по-прежнему можете видеть, является ли платеж ACH-платежом (дочерний элемент элемента оплаты называется ACHInfo) или платежом по кредитной карте (дочерний элемент называется CreditCardInfo), и вам больше не нужно проверять, чтобы подробная информация соответствовала флаг PaymentMethod, потому что флаг PaymentMethod исчез.

Меньше движущихся частей, меньше делать, меньше идти не так.

Из этих четырех дизайнов я думаю, что четвертый, вероятно, лучший. Ваш пробег, конечно, может отличаться.

Другие вопросы по тегам