Compartir a través de


Compatibilidad con enlaces del atributo MaxOccurs

Este tema es específico de una tecnología heredada. Ahora, los servicios Web XML y los clientes de servicios Web XML deben crearse con Windows Communication Foundation.

.NET Framework proporciona una compatibilidad de enlace parcial para el atributo maxOccurs.

Para la mayoría de elementos que pueden especificar un atributo maxOccurs, Xsd.exe interpreta el valor 0 como 1, y genera un campo que no es de matriz, y un valor mayor que 1 como unbounded, que genera un campo de matriz. Este comportamiento varía según el tipo de elemento.

Explicación

Los atributos maxOccurs y minOccurs limitan el número de veces seguidas que la entidad especificada puede aparecer en la posición correspondiente de un documento XML de instancia.

Estos atributos solo aparecen en definiciones de tipo complejo. Así pues, para que un elemento <element> o <group> pueda disponer de estos atributos, el elemento tiene que ser una declaración local o una referencia a una declaración global, pero no la declaración global propiamente dicha.

En el caso de las clases de enlace con tipos complejos de esquemas XML, .NET Framework no proporciona ningún lenguaje de programación directo equivalente al atributo maxOccurs o minOccurs.

Cuando se genera código fuente a partir de un documento de esquemas XML o cuando se realiza la traducción inversa, Xsd.exe interpreta el atributo maxOccurs de una forma distinta, basándose en el elemento de lenguaje de definición de esquemas XML donde aparece. En la siguiente tabla se explican las interpretaciones según el tipo de elemento:

Elemento Interpretación

<element>

Valores posibles:

  • 1: Xsd.exe genera un campo del tipo correspondiente al tipo de datos del elemento.

  • 0: Xsd.exe no procesa el valor 0, sino que lo considera como el valor 1 predeterminado.

  • unbounded: Xsd.exe genera un campo que es una matriz del tipo correspondiente al tipo de datos del elemento.

  • Cualquier entero mayor que 1: al igual que ocurre con los valores unbounded, Xsd.exe genera un campo que es una matriz del tipo correspondiente al tipo de datos del elemento. Puede imponer valores mayores que 1; para ello, tiene que validar un documento XML con la clase XmlValidatingReader con respecto a un documento de esquemas XML representado por el SOM.

<group>

Para el elemento <group>, el valor maxOccurs de0 lo interpreta Xsd.exe como 1, y un valor mayor que 1 para maxOccurs lo interpreta como ilimitado.

Sin embargo, Xsd.exe considera el valor maxOccurs="unbounded" para el elemento <group> como si cada uno de los elementos secundarios se hubiera especificado con maxOccurs="unbounded". Por ejemplo, si cada uno de los elementos secundarios del elemento <group><element> es un elemento , cada campo generado en la clase subsiguiente es una matriz del tipo apropiado.

Para importar correctamente los grupos contenedores de esquemas con maxOccurs mayor que 1, se recomienda utilizar la opción de línea de comandos /order con Xsd.exe. Cuando se utiliza esta opción, el grupo completo se importa como una matriz única con varios atributos XmlElementAttribute aplicados, uno para cada elemento en el grupo. Los tipos de elementos determinan el tipo de matriz. Es el tipo más derivado al que se pueden asignar todos los elementos. Es decir, si un grupo contiene elementos de tipos Type1 y Type2 que se derivan de TypeBase, la matriz será de tipo TypeBase. Si no existe un tipo base común, la matriz será de tipo Object. Para obtener un ejemplo relacionado, vea el ejemplo de <sequence> al final de este tema.

<all>

Todos los valores del atributo maxOccurs que sean distintos de 1 no serán válidos. Xsd.exe presenta un error con respecto a un valor no válido.

<any>

Valores posibles:

  • 1: Xsd.exe genera un campo de tipo System.Xml.XmlElement, con un atributo System.Xml.Serialization.XmlAnyElementAttribute. Este atributo permite que una clase represente elementos XML arbitrarios sin tener que enlazarlos a tipos que no sean XML identificados por otros posibles miembros de clase.

  • 0: Xsd.exe no procesa el valor 0, sino que lo considera como el valor 1 predeterminado.

  • unbounded: Xsd.exe genera una matriz XmlElement con un atributo XmlAnyElement.

  • Cualquier entero mayor que 1: del mismo modo que en el caso de los valores unbounded, Xsd.exe genera una matriz XmlElement con un atributo XmlAnyElement. Puede imponer valores mayores que 1; para ello, tiene que validar un documento XML con la clase XmlValidatingReader con respecto a un documento de esquemas XML representado por el SOM.

<choice>

El elemento <choice> contiene dos o más elementos secundarios, cada uno de los cuales representa un elemento o grupo de elementos. Este elemento indica que, en un documento de instancia determinado, solo una de dichas entidades puede aparecer en la posición especificada. Las opciones deben diferenciarse por el nombre de elemento; opcionalmente, pueden diferenciarse por el tipo y, en el caso de un grupo, por el número. Para obtener más información, vea el elemento <choice>.

En el caso del elemento <choice> y de los elemento <element> y <any> Xsd.exe interpreta un valor maxOccurs de 0 como 1, y un valor maxOccurs mayor que 1 lo interpreta como unbounded.

Si el valor es 1, Xsd.exe genera un campo del tipo común o un tipo base común. Para cada opción, se aplica un atributo de tipo XmlElementAttribute al campo. Si las opciones no se diferencian por el tipo, Xsd.exe genera un atributo de tipo XmlChoiceIdentifierAttribute, y especifica un segundo campo con un tipo de enumeración que representa cada opción. Este mecanismo se explica detalladamente, acompañado de ejemplos, con el elemento <choice>.

Si el valor es unbounded, Xsd.exe realiza el mismo enlace, pero en este caso, el campo generado para la opción es una matriz de un tipo adecuado. Si todas las opciones tienen el mismo tipo, el segundo campo (identificado por el atributo XmlChoiceIdentifier) es una matriz del tipo de enumeración generado. Cada uno de los elementos de la segunda matriz elige el nombre del elemento correspondiente de la primera matriz.

<sequence>

En el caso del elemento <sequence>, al igual que ocurre en la mayoría de los elementos anteriores, Xsd.exe interpreta los valores maxOccurs que son iguales a 0 como 1, y los valores de maxOccurs mayores que 1 como unbounded.

Sin embargo, Xsd.exe considera los valores maxOccurs="unbounded" del elemento <sequence> como si cada uno de los elementos secundarios se hubiera especificado con maxOccurs="unbounded". Por ejemplo, si todos los elementos secundarios del elemento <sequence> son elementos <element>, cada campo generado en la clase subsiguiente será una matriz del tipo apropiado. Xsd.exe enlaza esta estructura de campo a un elemento <sequence maxOccurs="1"> que contenga un número determinado de elementos <element maxOccurs="unbounded"> si se ha realizado una traducción inversa a un nuevo documento XSD.

Se aplican atributos XmlElementAttribute, uno por cada elemento del grupo. Los tipos de elementos determinan el tipo de matriz. Es el tipo más derivado al que se pueden asignar todos los elementos. Es decir, si un grupo contiene elementos de tipos Type1 y Type2 que se derivan de TypeBase, la matriz será de tipo TypeBase. Si no existe un tipo base común, la matriz será de tipo Object. Para obtener un ejemplo relacionado, vea el ejemplo de <sequence> al final de este tema.

Cuando se genera un documento de esquemas XML a partir de un conjunto de clases de un ensamblado, Xsd.exe invierte las conversiones anteriores, y genera un valor para el atributo maxOccurs de 1 a partir de una única instancia y un valor para el atributo maxOccurs de unbounded a partir de una matriz.

Cuando Xsd.exe enlaza un valor para el atributo maxOccurs de unbounded a una matriz, también enlaza un valor para el atributo maxOccurs de 1 al elemento principal de una matriz, si lo hubiere.

Un tipo de datos de esquema cuyo nombre comienza con ArrayOf, ha sido creado para representar el elemento principal de la matriz en caso de que el atributo predeterminado System.Xml.Serialization.XmlArrayAttribute se aplique a la matriz. Si en lugar de ello se aplica un atributo System.Xml.Serialization.XmlElementAttribute a la matriz, los elementos de la matriz aparecerán en un documento de instancia como elementos secundarios del elemento que se enlaza a la clase. Para obtener más información sobre los enlaces de matrices, vea Controlar la serialización XML mediante atributos.

Más información sobre los enlaces de matrices. Para poder entender la traducción de valores mayores que 1 en matrices, considere la diferencia que existe entre declarar un objeto de un tipo determinado y asignar un valor (literalmente, una posición de memoria en la pila o el montón) a ese objeto. Empiece por el siguiente elemento XSD:

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

Si escribiera el código manualmente, no expresaría el tamaño de la matriz de cinco en la declaración de tipos, que sería: public string[] items. En su lugar, expresaría el tamaño de la matriz al asignar un valor: items = new string[5].

Las únicas clases de código fuente que genera Xsd.exe a partir de un esquema son declaraciones de tipos y campos, así como metadatos que se pueden aplicar a tipos y campos como atributos. La asignación de valores a objetos supera dicho ámbito.

Para exigir un valor mayor que 1 se puede validar un documento XML con la clase XmlValidatingReader respecto a un documento de esquema XML representado por el Modelo de objetos de esquemas (SOM). Dicho modelo utiliza las propiedades System.Xml.Schema.XmlSchemaParticle.MaxOccurs y las propiedadesSystem.Xml.Schema.XmlSchemaParticle.MaxOccursString; estas dos clases se aplican a todos los elementos que pueden incluir un atributo maxOccurs.

Example

Elemento <choice> de esquema XML de entrada, localizado dentro de una definición de tipos complejos:

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

Pasajes relevantes de la clase de C# generados a partir del documento de esquemas XML anterior, junto a la enumeración que representa las opciones del elemento (suponiendo que el espacio de nombres de destino sea 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,
}

El tipo complejo generado a partir de una clase compilada desde el código fuente de C# anterior es equivalente al tipo complejo original.

<secuencia>

Example

Documento de esquema XML de entrada que contiene una secuencia con el valor de maxOccurs mayor que 1:

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

Clase de C# generada a partir del anterior documento de esquema XML sin ninguna opción de la línea de comandos:

[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;
}

Tipo complejo de esquema XML generado a partir de un ensamblado compilado en el código fuente de C# anterior:

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

Tal como se puede comprobar, el esquema resultante no es equivalente al esquema original. Para importar correctamente un esquema que tiene secuencias con el valor de maxOccurs mayor que 1, utilice la opción de la línea de comandos /order, la cual genera el siguiente resultado:

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

}

Posibles elementos contenedores: <all>, <any>, <choice>, <element>, <group>, <sequence>

Vea también

Referencia

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