xsd相同的元素,不同的类型?

时间:2009-08-20 13:45:53

标签: xml 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

这几乎是我想要做的,但我不确定这是可能的。 有没有人对如何解决这个问题有任何进一步的想法?

提前致谢。

3 个答案:

答案 0 :(得分:12)

不,你真的不能这样做。您有一个选项可以创建“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>

你不能让一个标签(例如“发送者”)在一个案例中成为一件事而在另一个案例中成为另一个 - 一个标签必须具有一个明确定义的类型,并且一次又一次具有该类型。

马克

答案 1 :(得分:2)

鉴于您对@mark_s提供的解决方案存在问题,您有以下几种选择:

  • 使用sender的两种类型创建两个单独的XSD。在触发验证的代码中,按顺序运行它们(即人员然后组织)。这样做的另一个好处是,您的代码将知道哪些验证通过(并且可以根据该知识做出选择)。
  • 将选项在XSD中向上移动一级。在ForminfoType内,添加一个包含两个序列的选择节点(一个人,一个组织)。我没有验证,但粗略地说:

    <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>
    

答案 2 :(得分:0)

虽然是很旧的帖子,但这可能对某人有所帮助。

您可以通过子类型化然后在 XML 中使用 xsi:type 属性来实现这一点。您可以参考以下链接了解详细信息和示例。

Subtyping and xsi:type