Prise en charge de la liaison de l'attribut MaxOccurs

Cette rubrique est spécifique à une technologie existante. Les services Web XML et les clients du service Web XML doivent à présent être créés à l'aide de Windows Communication Foundation.

Le .NET Framework fournit la prise en charge de liaison partielle pour l'attribut maxOccurs.

Pour la plupart des éléments qui peuvent spécifier un attribut maxOccurs, Xsd.exe interprète la valeur 0 comme 1, ce qui génère un champ non-tableau, et une valeur supérieure à 1 comme unbounded, ce qui génère un champ de tableau. Le comportement varie entre les éléments.

Explication

Les attributs maxOccurs et minOccurs limitent le nombre d'affichages successifs de l'entité spécifiée dans la position correspondante dans une instance de document XML.

Ces attributs apparaissent uniquement dans des définitions de type complexe. Par conséquent, pour qu'un élément <element> ou <group> ait ces attributs, il doit être une déclaration locale ou une référence à une déclaration globale, et non la déclaration globale elle-même.

Pour les classes de liaison avec des types complexes de schéma XML, le .NET Framework ne fournit pas de langage de programmation sélective équivalent à l'attribut maxOccurs ou minOccurs.

Lors de la génération du code source à partir d'un document de schéma XML ou de l'exécution de la traduction inverse, Xsd.exe interprète différemment l'attribut maxOccurs selon l'élément de langage XSD dans lequel il apparaît. Le tableau suivant explique les interprétations par élément :

Élément Interprétation

<element>

Valeurs possibles :

  • 1 : Xsd.exe génère un champ de type correspondant au type de données de l'élément.

  • 0 : Xsd.exe ne parvient pas à traiter la valeur 0 et traite cette valeur comme s'il s'agissait de la valeur par défaut 1.

  • unbounded : Xsd.exe génère un champ qui est un tableau de type correspondant au type de données de l'élément.

  • Tout entier supérieur à 1 : comme avec une valeur unbounded, Xsd.exe génère un champ qui est un tableau de type correspondant au type de données de l'élément. Vous pouvez appliquer une valeur supérieure à 1 en validant un document XML avec la classe XmlValidatingReader par rapport à un document de schéma XML représenté par le modèle d'objet de schéma.

<group>

Pour l'élément <groupe>, une valeur maxOccurs de 0 est interprétée par Xsd.exe comme 1, et une valeur maxOccurs supérieure à 1 est interprétée comme étant unbounded.

Toutefois, par défaut Xsd.exe traite une valeur maxOccurs="unbounded" pour l'élément <group>maxOccurs="unbounded" comme si chacun des éléments enfants avait été spécifié avec la valeur. Par exemple, si chacun des enfants de l'élément <group><element> est un élément, chaque champ généré dans la classe résultante est un tableau du type approprié.

Pour importer correctement des schémas contenant des groupes avec maxOccurs supérieur à 1, il est recommandé d'utiliser l'option de la ligne de la commande /order avec Xsd.exe. Lorsque cette option est utilisée, le groupe entier est importé comme un tableau unique avec plusieurs attributs XmlElementAttribute appliqués, un pour chaque élément du groupe. Le type du tableau est déterminé par les types des éléments - le type sera le type le plus dérivé auquel tous les éléments peuvent être assignés. C'est-à-dire si un groupe contient des éléments de types Type1 et Type2 que les deux dérivent de TypeBase, le tableau sera de type TypeBase. S'il n'y a aucun type de circuit à base commune, le tableau sera de type Object. Pour obtenir un exemple connexe, consultez l'exemple <sequence> en bas de cette rubrique.

<all>

Toute valeur pour l'attribut maxOccurs autre que 1 n'est pas valide. Xsd.exe signale une erreur pour une valeur non valide.

<any>

Valeurs possibles :

  • 1 : Xsd.exe produit un champ de type System.Xml.XmlElement, avec un attribut System.Xml.Serialization.XmlAnyElementAttribute. Cet attribut permet à une classe de représenter des éléments XML arbitraires sans les lier aux types non XML identifiés par d'autres membres de classe possibles.

  • 0 : Xsd.exe ne parvient pas à traiter la valeur 0 et traite cette valeur comme s'il s'agissait de la valeur par défaut 1.

  • unbounded : Xsd.exe génère un tableau XmlElement, avec un attribut XmlAnyElement.

  • Tout entier supérieur à 1 : comme avec la valeur unbounded, Xsd.exe génère un tableau XmlElement, avec un attribut XmlAnyElement. Vous pouvez appliquer une valeur supérieure à 1 en validant un document XML avec la classe XmlValidatingReader par rapport à un document de schéma XML représenté par le modèle d'objet de schéma.

<choice>

L'élément <choice> contient deux éléments enfants ou plus, qui représentent chacun un élément ou un groupe d'éléments. Il indique que, dans une instance de document donnée, une seule de ces entités peut apparaître dans la position spécifiée. Les éléments choice doivent différer par leur nom d'élément ; ils peuvent éventuellement différer par leur type et, pour un groupe, par leur nombre. Pour plus d'informations, consultez l'élément <choice>.

Pour l'élément <choice> comme pour les éléments <element> et <any>, une valeur maxOccurs de 0 est interprétée par Xsd.exe comme la valeur 1, et une valeur maxOccurs supérieure à 1 est interprétée comme la valeur unbounded.

Pour la valeur 1, Xsd.exe génère un champ de type commun ou un type de base commun. Pour chacun des éléments choice, un attribut de type XmlElementAttribute est appliqué au champ. Si les éléments choice ne diffèrent pas par leur type, Xsd.exe génère un attribut de type XmlChoiceIdentifierAttribute, en spécifiant un deuxième champ avec un type énumération qui représente chacun des éléments. Ce mécanisme est expliqué en détail et accompagné d'exemples, avec l'élément <choice>.

Pour la valeur unbounded, Xsd.exe exécute la même liaison, sauf que le champ généré pour le choix est un tableau d'un type approprié. Si tous les choix ont le même type, le deuxième champ (identifié par l'attribut XmlChoiceIdentifier) est un tableau du type énumération généré. Chaque élément contenu dans le deuxième tableau détermine le nom d'élément de l'élément correspondant dans le premier tableau.

<sequence>

Pour l'élément <sequence> comme pour la plupart des éléments précédents, une valeur maxOccurs de 0 est interprétée par Xsd.exe comme la valeur 1, et une valeur maxOccurs supérieure à 1 est interprétée comme la valeur unbounded.

Toutefois, Xsd.exe traite une valeur maxOccurs="unbounded" pour l'élément <sequence> comme si chacun des éléments enfants avait été spécifié avec la valeur maxOccurs="unbounded". Par exemple, si chacun des enfants de l'élément <sequence> est un élément <element>, alors chaque champ généré dans la classe résultante est un tableau du type approprié. Xsd.exe lie cette structure de champ à un élément <sequence maxOccurs="1"><element maxOccurs="unbounded"> qui contient un nombre donné d'éléments s'il a exécuté une traduction inverse sur un nouveau document XSD.

Attributs XmlElementAttribute appliqués, un pour chaque élément du groupe. Le type du tableau est déterminé par les types des éléments - le type sera le type le plus dérivé auquel tous les éléments peuvent être assignés. C'est-à-dire si un groupe contient des éléments de types Type1 et Type2 que les deux dérivent de TypeBase, le tableau sera de type TypeBase. S'il n'y a aucun type de circuit à base commune, le tableau sera de type Object. Pour obtenir un exemple connexe, consultez l'exemple <sequence> en bas de cette rubrique.

Lors de la génération d'un document de schéma XML à partir d'un ensemble de classes dans un assembly, Xsd.exe inverse les conversions précédentes, en générant une valeur maxOccurs de 1 à partir d'une seule instance et une valeur maxOccurs unbounded à partir d'un tableau.

Alors que Xsd.exe lie une valeur maxOccurs unbounded à un tableau, il lie une valeur maxOccurs de 1 à l'élément parent désigné d'un tableau, le cas échéant.

Un type de données de schéma dont le nom commence par ArrayOf est créé pour représenter l'élément parent du tableau si l'attribut System.Xml.Serialization.XmlArrayAttribute par défaut est appliqué au tableau. En revanche, si un System.Xml.Serialization.XmlElementAttribute est appliqué à un tableau, les éléments du tableau apparaissent dans une instance de document comme les enfants de l'élément qui crée une liaison avec la classe. Pour plus d'informations sur les liaisons de tableau, consultez Contrôle de la sérialisation XML à l'aide d'attributs.

Informations supplémentaires sur les liaisons de tableau. Pour comprendre la traduction d'une valeur supérieure à 1 en tableau, considérez la différence entre la déclaration d'un objet d'un type spécifique et l'assignation d'une valeur (littéralement, un emplacement de mémoire dans la pile ou le tas) à cet objet. Démarrez avec l'élément XSD suivant :

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

En cas d'écriture manuelle du code, vous n'exprimeriez pas la taille du tableau (égale à cinq) dans la déclaration de type, qui serait : public string[] items. En effet, vous exprimeriez la taille du tableau lors de l'assignation d'une valeur : items = new string[5].

Les seuls types de code source générés par Xsd.exe à partir d'un schéma XML sont les déclarations de type et de champ ainsi que les métadonnées qui peuvent être appliquées aux types et aux champs en tant qu'attributs. L'assignation de valeurs à des objets est hors de portée.

L'application d'une valeur supérieure à 1 se fait par la validation d'un document XML avec la classe XmlValidatingReader par rapport à un document de schéma XML représenté par le modèle d'objet de schéma. Le modèle d'objet de schéma utilise les propriétés System.Xml.Schema.XmlSchemaParticle.MaxOccurs et System.Xml.Schema.XmlSchemaParticle.MaxOccursString, qui s'appliquent chacune à tous les éléments pouvant contenir un attribut maxOccurs.

Example

Élément <choice> de schéma XML d'entrée contenu dans une définition de type complexe :

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

Passages pertinents de la classe C# générée à partir du document de schéma XML précédent, ainsi que l'énumération représentant les choix d'élément (avec l'espace de noms cible 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,
}

Le type complexe généré à partir d'une classe compilée du code source C# précédent équivaut au type complexe d'origine.

<sequence>

Example

Document de schéma XML d'entrée qui contient une séquence avec maxOccurs supérieur à 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>

La classe C# générée du document de schéma XML précédent sans option de ligne de commande :

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

Type complexe de schéma XML généré à partir d'un assembly compilé depuis la source C# précédente :

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

Comme vous pouvez le voir, le schéma résultant n'est pas équivalent au schéma d'origine. Pour importer correctement un schéma qui a des séquences avec maxOccurs supérieur à 1, utilisez l'option de ligne de commande /order, ce qui donne :

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

}

Éléments conteneurs possibles : <all>, <any>, <choice>, <element>, <group>, <sequence>

Voir aussi

Référence

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