choice 元素绑定支持

本主题专门介绍一项旧有技术。现在应通过使用以下链接来创建 XML Web 服务和 XML Web 服务客户端: Windows Communication Foundation.

.NET Framework 为 <choice> 元素提供绑定支持。

如果各个 choice 元素的类型和名称均不相同,则 Xsd.exe 仅将 XmlElementAttribute 特性应用于公共成员。如果它们只是名称不同,则 Xsd.exe 还将应用 XmlChoiceIdentifierAttribute,并添加用来进行选择的额外逻辑。

说明

<choice> 元素包含两个或更多个子元素,其中每个子元素都表示一个或一组元素。这意味着,在给定的实例文档中,只有其中一个实体可以出现在指定的位置。选项的元素名称必须各不相同。它们还可以在元素类型上存在不同,而且,如果选项是一个分组(例如,一个 <group> 元素),则它们还可以在元素数目上存在不同。

如果组的组合不明确,则会产生不可预知的结果。

按类型区分

当各个元素的类型和名称均不相同时,会出现最简单的情况。请考虑下面的 <choice> 定义:

<xsd:choice>
    <xsd:element name="numberA" type="xsd:int"/>
    <xsd:element name="numberB" type="xsd:decimal"/>
</xsd:choice>

在 C# 中,Xsd.exe 会将此 XML 架构内容转换为下面的代码:

[System.Xml.Serialization.XmlElementAttribute("numberA", typeof(int))]
[System.Xml.Serialization.XmlElementAttribute("numberB", typeof(System.Decimal))]
public object Item;

在所生成的代码中,该字段被赋予 object 类型,但是它还具有两个 XmlElementAttribute 特性。一个特性用来将该类型序列化为 int 实例;另一个特性用来将该类型序列化为 System.Decimal 实例。在本例中,XmlSerializer 类使用此时分配给该对象的类型。在对 int 对象进行如下分配时,使用 <numberA> 元素:

Item = 1;

只要选项有不同的 XML 架构数据类型,Xsd.exe 就会将每个数据类型绑定到一个不同的类。由于 System.Object 是 .NET Framework 类型层次结构的根类型,因此所生成的字段总是属于一个公共基类型。Object 类是最一般的公共基类型。

如果选项全部都是从一个由 XML 架构定义的公共数据类型派生的(例如,通过 <extension> 构造),则字段类型是该数据类型的绑定。例如,假定 <choice> 元素允许在 DerivedTypeA<a> 元素与 DerivedTypeB<b> 元素之间进行选择,并假定这两个类型均扩展 BaseType 类型。在 C# 中,会生成下面的源代码:

[System.Xml.Serialization.XmlElementAttribute("a", typeof(DerivedTypeA))]
[System.Xml.Serialization.XmlElementAttribute("b", typeof(DerivedTypeB))]
public BaseType Item;

按名称区分

如果选项类型没有区别,则可以通过使用 XmlChoiceIdentifierAttribute 特性在创建实例文档时选择元素名称。请考虑下面的 <choice> 定义:

<xsd:choice>
    <xsd:element name="stringA" type="xsd:string"/>
    <xsd:element name="stringB" type="xsd:string"/>
</xsd:choice>

Xsd.exe 会将此 XML 架构内容转换为下面的代码:

[System.Xml.Serialization.XmlElementAttribute("stringA", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("stringB", typeof(string))]
[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")]
public string Item;

[System.Xml.Serialization.XmlIgnoreAttribute()]
public ItemChoiceType ItemElementName;
...
public enum ItemChoiceType {
        
    stringA,
        
    stringB,
}

Item 字段除了具有两个 XmlElement 特性以外,还具有一个 XmlChoiceIdentifier 特性。XmlChoiceIdentifier 特性的参数是一个枚举实例的名称。对应的枚举类型包含元素选项。枚举实例与 XmlIgnore 特性一起出现,因此它的值无法序列化。

随后,开发人员必须编写代码,以便为枚举实例分配值。下面的代码行为名为 i 的对象执行上述操作:

i.ItemElementName = ItemChoiceType.stringA;

有关更多详细信息,请参见 XmlChoiceIdentifierAttribute 类。

Example

下面的输入 XML 架构文档演示 <choice> 分组的各种用法:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
            targetNamespace="http://example.org/" xmlns="http://example.org/" elementFormDefault="qualified">
    <xsd:element name="choicesInstance" type="MyChoicesType"/>

    <xsd:complexType name="MyComplexType">
        <xsd:sequence>
            <xsd:element name="field1" type="xsd:string"/>
            <xsd:element name="field2" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="DerivedTypeA">
        <xsd:complexContent>
            <xsd:extension base="MyComplexType">
                 <xsd:attribute name="extraInfoForA" type="xsd:string"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="DerivedTypeB">
        <xsd:complexContent>
            <xsd:extension base="MyComplexType">
                 <xsd:attribute name="extraInfoForB" type="xsd:string"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="MyChoicesType">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:choice>
                <xsd:element name="stringA" type="xsd:string"/>
                <xsd:element name="stringB" type="xsd:string"/>
            </xsd:choice>
            <xsd:choice>
                <xsd:element name="numberA" type="xsd:int"/>
                <xsd:element name="numberB" type="xsd:decimal"/>
            </xsd:choice>
            <xsd:choice>
                <xsd:element name="complexA" type="MyComplexType"/>
                <xsd:element name="complexB" type="MyComplexType"/>
                <xsd:element name="simpleC"  type="xsd:string"/>
            </xsd:choice>
            <xsd:choice>
                <xsd:element name="derivedA" type="DerivedTypeA"/>
                <xsd:element name="derivedB" type="DerivedTypeB"/>
            </xsd:choice>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

基于前面的 XML 架构文档生成的 C# 类:

[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/")]
[System.Xml.Serialization.XmlRootAttribute("choicesInstance", Namespace="http://example.org/", IsNullable=false)]
 public class MyChoicesType {
        
     public string name;
        
    [System.Xml.Serialization.XmlElementAttribute("stringA", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("stringB", typeof(string))]
    [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")]
    public string Item;
        
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public ItemChoiceType ItemElementName;
        
    [System.Xml.Serialization.XmlElementAttribute("numberA", typeof(int))]
    [System.Xml.Serialization.XmlElementAttribute("numberB", typeof(System.Decimal))]
    public object Item1;
        
    [System.Xml.Serialization.XmlElementAttribute("complexA", typeof(MyComplexType))]
    [System.Xml.Serialization.XmlElementAttribute("complexB", typeof(MyComplexType))]
    [System.Xml.Serialization.XmlElementAttribute("simpleC", typeof(string))]
    [System.Xml.Serialization.XmlChoiceIdentifierAttribute("Item2ElementName")]
    public object Item2;
        
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public Item2ChoiceType Item2ElementName;
        
    [System.Xml.Serialization.XmlElementAttribute("derivedA", typeof(DerivedTypeA))]
    [System.Xml.Serialization.XmlElementAttribute("derivedB", typeof(DerivedTypeB))]
    public MyComplexType Item3;
}
    
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/", IncludeInSchema=false)]
public enum ItemChoiceType {
        
    stringA,
        
    stringB,
}
    
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/")]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(DerivedTypeB))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(DerivedTypeA))]
public class MyComplexType {
        
    public string field1;
        
    public string field2;
}
    
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/")]
    public class DerivedTypeA : MyComplexType {
        
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string extraInfoForA;
    }
    
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/")]
public class DerivedTypeB : MyComplexType {
        
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string extraInfoForB;
}
    
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/", IncludeInSchema=false)]
public enum Item2ChoiceType {
        
    complexA,
        
    complexB,
        
    simpleC,
}

基于通过前面的 C# 源代码编译得到的程序集生成的主 XML 架构文档。(未显示第二个 .xsd 文件,生成该文件的目的是为复杂类型定义任意全局元素。)

<xs:schema xmlns:tns="http://example.org/" elementFormDefault="qualified" targetNamespace="http://example.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="choicesInstance" type="tns:MyChoicesType" />
  <xs:complexType name="MyChoicesType">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="name" type="xs:string" />
      <xs:choice minOccurs="1" maxOccurs="1">
        <xs:element minOccurs="0" maxOccurs="1" name="stringA" type="xs:string" />
        <xs:element minOccurs="0" maxOccurs="1" name="stringB" type="xs:string" />
      </xs:choice>
      <xs:choice minOccurs="1" maxOccurs="1">
        <xs:element minOccurs="1" maxOccurs="1" name="numberA" type="xs:int" />
        <xs:element minOccurs="1" maxOccurs="1" name="numberB" type="xs:decimal" />
      </xs:choice>
      <xs:choice minOccurs="1" maxOccurs="1">
        <xs:element minOccurs="0" maxOccurs="1" name="complexA" type="tns:MyComplexType" />
        <xs:element minOccurs="0" maxOccurs="1" name="simpleC" type="xs:string" />
        <xs:element minOccurs="0" maxOccurs="1" name="complexB" type="tns:MyComplexType" />
      </xs:choice>
      <xs:choice minOccurs="1" maxOccurs="1">
        <xs:element minOccurs="0" maxOccurs="1" name="derivedB" type="tns:DerivedTypeB" />
        <xs:element minOccurs="0" maxOccurs="1" name="derivedA" type="tns:DerivedTypeA" />
      </xs:choice>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MyComplexType">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="field1" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" name="field2" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="DerivedTypeA">
    <xs:complexContent mixed="false">
      <xs:extension base="tns:MyComplexType">
        <xs:attribute name="extraInfoForA" type="xs:string" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="DerivedTypeB">
    <xs:complexContent mixed="false">
      <xs:extension base="tns:MyComplexType">
        <xs:attribute name="extraInfoForB" type="xs:string" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
</xs:schema>

可能的特性 绑定支持

id

Xsd.exe 实用工具会忽略旨在提供唯一标识符的 id 特性。

maxOccurs

对于 <choice> 元素,Xsd.exe 将 maxOccurs0 解释为 1,将大于 1 的 maxOccurs 值解释为 unbounded

对于值 1,Xsd.exe 会按照按类型区分和按名称区分中说明的那样生成代码。

对于值 unbounded,Xsd.exe 执行相同的绑定,不同之处是为选项生成的字段是适当类型的数组。如果所有选项都具有相同的类型,则第二个字段(由 XmlChoiceIdentifier 特性标识)是一个生成的枚举类型的数组。第二个数组中的每个元素都选择第一个数组中的对应元素的元素名称。

请参见 maxOccurs 特性绑定支持 特性。

minOccurs

当从 XML 架构文档生成源代码时,Xsd.exe 会忽略应用于 <choice> 元素的 minOccurs 特性。

当从类生成 XML 架构文档时,如果该选项表示单个对象,则 Xsd.exe 会生成一个 minOccurs 值为 1<choice> 元素;如果该选项表示一个数组,则 Xsd.exe 会生成一个 minOccurs 值为 0<choice> 元素。

请参见 minOccurs 特性绑定支持 特性。

可能的父元素:<choice>、<complexType><extension><group><restriction><sequence>

可能的子元素:<annotation><any><element><group><sequence>、<choice>

另请参见

参考

XmlSchemaChoice