Xsd тот же самый элемент, разные типы?

У меня есть ситуация, когда элемент в XML файле может иметь два разных типа в XSD.

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

Итак, это в основном это:

<xsd:complexType name="ForminfoType"> `
    <xsd:sequence>
        <xsd:element name="formname" type="xsd:string" />
        <xsd:element name="timestamp" type="xsd:dateTime" />
        <xsd:element name="sender" type="PersonType" minOccurs="0" />
        <xsd:element name="receiver" type="OrganizationType" minOccurs="0" />
        <xsd:element name="signature" type="xsd:string" minOccurs="0" />
    </xsd:sequence>
</xsd:complexType> 

То, что объявляется PersonType, представляет собой в основном 12-значное число, построенное по определенному шаблону. То, что объявляет тип организации, представляет собой просто 10-значное число.

Так что я логически хотел бы сделать это:

<xsd:element name="sender" type="OrganizationType" minOccurs="0" />

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

Я нашел следующее: http://xsd.stylusstudio.com/2007Oct/post05003.htm

Это в значительной степени то, что я хочу сделать, но я не уверен, что это возможно. Кто-нибудь получил какие-либо дальнейшие идеи о том, как это решить?

Спасибо заранее.

Ответы

Ответ 1

Нет, вы не можете этого сделать. Один из вариантов заключается в создании сложного типа "PersonOrOrgSender" в соответствии с:

  <xsd:complexType name="PersonOrOrgType">
    <xsd:choice>
      <xsd:element minOccurs="0" name="PersonSender" type="PersonType" />
      <xsd:element minOccurs="0" name="OrgSender" type="OrganizationType" />
    </xsd:choice>
  </xsd:complexType>

а затем сделайте свой "отправитель" экземпляром этого типа:

<xsd:element name="sender" type="PersonOrOrgType" minOccurs="0" />

но тогда у вас будут данные XML следующим образом:

<FormInfo>
  <formname>string</formname>
  <sender>
    <OrgSender>
      <Name>string</Name>
    </OrgSender>
  </sender>  
  ...
</FormInfo>

или

<FormInfo>
  <formname>string</formname>
  <sender>
    <PersonSender>
      <Name>string</Name>
    </PersonSender>
  </sender>  
  ...
</FormInfo>

Вы не можете создать ни одного тега (например, "отправитель" ) в одном случае, а другой в другом случае - один тег должен иметь ровно один четко определенный тип и имеет этот тип раз и навсегда.

Марк

Ответ 2

Учитывая ваши проблемы с решением, предоставленным @mark_s, у вас есть несколько вариантов:

  • Создайте два отдельных XSD с двумя типами для sender. В коде, который запускает проверку, запускайте их последовательно (например, человек, затем организация). Это имеет дополнительное преимущество в том, что ваш код будет знать, какая проверка прошла (и может делать выбор на основе этих знаний).
  • Переместите выбор до уровня в XSD. Внутри ForminfoType добавьте выбор node с двумя последовательностями (один человек, одна организация). Я не проверял, но грубо:

    <xsd:complexType name="ForminfoType">
        <xsd:choice>
            <xsd:sequence> <!-- person -->
                <xsd:element name="formname" type="xsd:string" />
                <xsd:element name="timestamp" type="xsd:dateTime" />
                <xsd:element name="sender" type="PersonType" minOccurs="0" />
                <xsd:element name="receiver" type="OrganizationType" minOccurs="0" />
                <xsd:element name="signature" type="xsd:string" minOccurs="0" />
            </xsd:sequence>
            <xsd:sequence> <!-- organization -->
                <xsd:element name="formname" type="xsd:string" />
                <xsd:element name="timestamp" type="xsd:dateTime" />
                <xsd:element name="sender" type="OrganizationType" minOccurs="0" />
                <xsd:element name="receiver" type="OrganizationType" minOccurs="0" />
                <xsd:element name="signature" type="xsd:string" minOccurs="0" />
            </xsd:sequence>
        </xsd:choice>
    </xsd:complexType>