maxOccurs 特性绑定支持

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

.NET Framework 为 maxOccurs 特性提供部分绑定支持。

对于可以指定 maxOccurs 特性的大部分元素,Xsd.exe 都将 0 值解释为 1(生成非数组字段),将大于 1 的值解释为 unbounded(生成数组字段)。具体的行为因元素而异。

说明

maxOccursminOccurs 特性限制指定的实体可以连续出现在 XML 实例文档中的对应位置的次数。

这些特性仅出现在复杂类型定义中。因此,要使 <element><group> 元素具有这些特性,元素必须是局部声明或对全局声明的引用,而不能是全局声明本身。

对于具有 XML 架构复杂类型的绑定类,.NET Framework 不提供与 maxOccursminOccurs 特性等效的直接编程语言。

当从 XML 架构文档生成源代码或者执行反向转换时,Xsd.exe 基于 maxOccurs 特性所出现在的 XML 架构定义语言元素以不同的方式来解释它。下表按元素说明这些解释:

元素 解释

<element>

可能的值:

  • 1:Xsd.exe 生成类型与元素的数据类型对应的字段。

  • 0:Xsd.exe 处理值 0 失败,而改为将该值作为默认值 1 处理。

  • unbounded:Xsd.exe 生成一个字段,该字段是类型与元素的数据类型对应的数组。

  • 大于 1 的任何整数:与 unbounded 值相同,Xsd.exe 生成一个字段,该字段是类型与元素的数据类型对应的数组。可以使用 XmlValidatingReader 类对照 SOM 表示的 XML 架构文档验证 XML 文档,从而强制使用大于 1 的值。

<group>

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

但是,默认情况下,Xsd.exe 处理 <group> 元素的 maxOccurs="unbounded" 值的方式就如同每个子元素都指定为 maxOccurs="unbounded" 一样。例如,如果 <group> 元素的每个子级都是一个 <element> 元素,则在结果类中生成的每个字段都是适当类型的数组。

若要正确导入包含 maxOccurs 大于 1 的组的架构,建议对 Xsd.exe 使用 /order 命令行选项。使用此选项时,整个组将作为已应用多个 XmlElementAttribute 特性的单个数组导入,每个特性分别应用于组中的一个成员。数组的类型由元素的类型决定,即数组的类型将是所有元素都能分配到的派生程度最大的类型。也就是说,如果一个组中包含的类型为 Type1 和 Type2 的元素都从 TypeBase 派生而来,则数组的类型将为 TypeBase。如果没有公共基类型,则数组的类型将为 Object。有关相关示例,请参见本主题底部的 <sequence> 示例。

<all>

对于 maxOccurs 特性而言,除 1 以外的任何值都是无效的。对于无效值,Xsd.exe 会报错。

<any>

可能的值:

  • 1:Xsd.exe 使用特性 System.Xml.Serialization.XmlAnyElementAttribute 生成一个 System.Xml.XmlElement 类型的字段。此特性使类可以在不将 XML 元素绑定到由其他可能的类成员标识的非 XML 类型的情况下,表示任意 XML 元素。

  • 0:Xsd.exe 处理值 0 失败,而改为将该值作为默认值 1 处理。

  • unbounded:Xsd.exe 使用 XmlAnyElement 特性生成 XmlElement 数组。

  • 任何大于 1 的整数:与 unbounded 值相同,Xsd.exe 使用 XmlAnyElement 特性生成 XmlElement 数组。可以使用 XmlValidatingReader 类对照 SOM 表示的 XML 架构文档验证 XML 文档,从而强制使用大于 1 的值。

<choice>

<choice> 元素包含两个或更多个子元素,其中每个子元素都表示一个或一组元素。这意味着,在给定的实例文档中,只有其中一个实体可以出现在指定的位置。选项必须按元素名区分,而且还可以在类型上(对于组,还可以在数目上)存在区别。有关更多信息,请参见 <choice> 元素。

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

对于值 1,Xsd.exe 会生成一个公共类型或公共基类型的字段。对于每个选项,都会为该字段应用一个 XmlElementAttribute 类型的特性。如果选项在类型上没有区别,则 Xsd.exe 会生成一个 XmlChoiceIdentifierAttribute 类型的特性,并指定第二个具有表示每个选项的枚举类型的字段。在介绍 <choice> 元素时,将会结合示例详细解释此机制。

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

<sequence>

对于 <sequence> 元素,与前面的大多数元素相同,Xsd.exe 将 maxOccurs0 解释为 1,将大于 1 的 maxOccurs 值解释为 unbounded

但是,Xsd.exe 处理 <sequence> 元素的 maxOccurs="unbounded" 值的方式就如同每个子元素都指定为 maxOccurs="unbounded" 一样。例如,如果 <sequence> 元素的每个子级都是一个 <element> 元素,则在结果类中生成的每个字段都是适当类型的数组。如果 Xsd.exe 执行转换为新 XSD 文档的反向转换,会将此字段结构绑定到包含给定数目的 <element maxOccurs="unbounded"> 元素的 <sequence maxOccurs="1"> 元素。

应用多个 XmlElementAttribute 特性,每个特性分别应用于组中的一个元素。数组的类型由元素的类型决定,即数组的类型将是所有元素都能分配到的派生程度最大的类型。也就是说,如果一个组中包含的类型为 Type1 和 Type2 的元素都从 TypeBase 派生而来,则数组的类型将为 TypeBase。如果没有公共基类型,则数组的类型将为 Object。有关相关示例,请参见本主题底部的 <sequence> 示例。

当基于程序集中的一组类生成 XML 架构文档时,Xsd.exe 执行上述转换的反向转换,从单个实例生成 maxOccurs1,从数组生成 maxOccursunbounded

尽管 Xsd.exe 将 maxOccursunbounded 绑定到数组,但是它将 maxOccurs1 绑定到数组的指定父元素(如果有的话)。

如果将默认的 System.Xml.Serialization.XmlArrayAttribute 应用于该数组,将创建一个名称以 ArrayOf 开头的架构数据类型以表示该数组的父元素。如果 System.Xml.Serialization.XmlElementAttribute 应用于数组,则数组元素以绑定到类的元素的子级的形式出现在实例文档中。有关数组绑定的更多信息,请参见使用特性控制 XML 序列化

有关数组绑定的更多信息。 若要了解如何将大于 1 的值转换为数组,请考虑声明某一类型的对象与为该对象赋值(确切地说是堆栈或堆中的内存位置)之间的不同。从下面的 XSD 元素开始:

<xsd:element minOccurs="5" maxOccurs="5" name="items" type="xsd:token" />

手动编写代码时,您不会在类型声明(可能为 public string[] items)中将数组大小表示为 5,而是在赋值时表示数组大小:items = new string[5]

Xsd.exe 从 XML 架构生成的仅有的几种源代码是类型和字段声明,以及可以作为特性应用于类型和字段的元数据。为对象赋值超越了这一范围。

可以使用 XmlValidatingReader 类对照架构对象模型 (SOM) 表示的 XML 架构文档验证 XML 文档,从而强制使用大于 1 的值。SOM 使用 System.Xml.Schema.XmlSchemaParticle.MaxOccursSystem.Xml.Schema.XmlSchemaParticle.MaxOccursString 属性,两者均应用于可以包含 maxOccurs 特性的所有元素。

Example

在复杂类型定义中找到的输入 XML 架构 <choice> 元素:

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

基于前面的 XML 架构文档生成的 C# 类中的相关代码段,加上表示元素选项的枚举(假定目标命名空间为 http://example.org/):

    [System.Xml.Serialization.XmlElementAttribute("stringA", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("stringB", typeof(string))]
    [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
    public string[] Items;
        
    [System.Xml.Serialization.XmlElementAttribute("ItemsElementName")]
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public ItemsChoiceType[] ItemsElementName;
...
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/", IncludeInSchema=false)]
public enum ItemsChoiceType {
    stringA,
    stringB,
}

基于通过前面的 C# 源代码编译得到的类所生成的复杂类型实际上等同于原始复杂类型。

<sequence>

Example

包含 maxOccurs 大于 1 的序列的输入 XML 架构文档:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      xmlns="http://example.org/" targetNamespace="http://example.org/" elementFormDefault="qualified">
  <xsd:element name="ComplexInstance">
   <xsd:complexType>
     <xsd:sequence maxOccurs="unbounded">
       <xsd:element name="Field1" type="xsd:token"/>
       <xsd:element name="Field2" type="xsd:int" />
     </xsd:sequence>
   </xsd:complexType>
  </xsd:element>
</xsd:schema>

在不使用任何命令行选项的情况下由前面的 XML 架构文档生成的 C# 类:

[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://example.org/", IsNullable=false)]
public class ComplexInstance {        
    [System.Xml.Serialization.XmlElementAttribute("Field1", DataType="token")]
    public string[] Field1;
        
    [System.Xml.Serialization.XmlElementAttribute("Field2")]
    public int[] Field2;
}

基于通过前面的 C# 源代码编译得到的程序集生成的 XML 架构复杂类型:

<xs:complexType name="ComplexInstance">
  <xs:sequence>
    <xs:element minOccurs="0" maxOccurs="unbounded" name="Field1" type="xs:token" />
    <xs:element minOccurs="0" maxOccurs="unbounded" name="Field2" type="xs:int" />
  </xs:sequence>
</xs:complexType>

正如您所看到的,所生成的架构与原始架构不是等效的。若要正确导入包含 maxOccurs 大于 1 的序列的架构,请使用 /order 命令行选项,生成的结果如下所示:

[System.Xml.Serialization.XmlTypeAttribute

(Namespace="http://example.org/")]

[System.Xml.Serialization.XmlRootAttribute

(Namespace="http://example.org/", IsNullable=false)]

public partial class ComplexInstance

{

/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute

("Field1", typeof(string), DataType="token", Order=0)]

[System.Xml.Serialization.XmlElementAttribute("Field2",

typeof(int), Order=0)]

public object[] Items;

}

可能的包含元素:<all><any><choice><element><group><sequence>

另请参见

参考

System.Xml.Schema.XmlSchemaParticle.MaxOccurs
System.Xml.Schema.XmlSchemaParticle.MaxOccursString
XmlSchemaAll
XmlSchemaAny
XmlSchemaChoice
XmlSchemaElement
XmlSchemaGroupRef
XmlSchemaSequence