Partager via


Prise en charge de la liaison de l'élément Choice

Le .NET Framework prend en charge la liaison pour l'élément <choice>.

Si les noms et les types des éléments choice individuels diffèrent, Xsd.exe applique uniquement les attributs XmlElementAttribute à un membre public. Si seul leur nom diffère, Xsd.exe applique en plus un attribut XmlChoiceIdentifierAttribute et ajoute une logique supplémentaire pour la sélection.

Explication

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 nom d'élément. Ils peuvent également différer par type d'élément et, si l'élément choice est un regroupement (tel qu'un élément <group>), par nombre d'éléments

Des combinaisons ambiguës de groupes entraînent des résultats imprévisibles.

Différenciation par type

Le cas le plus simple survient lorsque les noms et les types des éléments individuels diffèrent. Regardez la définition <choice> suivante :

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

En C#, Xsd.exe traduirait ce contenu de schéma XML en code, comme suit :

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

Dans le code généré, le type object est attribué au champ, mais celui-ci possède également deux attributs XmlElementAttribute. Un attribut demande de sérialiser le type vers une instance int ; l'autre demande de sérialiser le type vers une instance System.Decimal. Dans ce cas, la classe XmlSerializer utilise le type assigné à l'objet à ce moment. Avec l'assignation suivante à un objet int, l'élément <numberA> est utilisé :

Item = 1;

Chaque fois que les éléments choice ont des types de données de schéma XML différents, Xsd.exe lie chacun des types de données à une classe différente. Dans la mesure où System.Object est le type racine de la hiérarchie de types .NET Framework, le champ généré appartient toujours à un type de base commun. La classe d'objet est le type de base commun le plus générique.

Lorsque les choix sont tous dérivés d'un type de données de schéma XML commun, par exemple via la construction <extension>, le type de champ est une liaison de ce type de données. Par exemple, supposons qu'un élément <choice> propose un choix entre l'élément <a> de DerivedTypeA et l'élément <b> de DerivedTypeB, et que ces types étendent le type BaseType. En C#, la source suivante est générée :

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

Différenciation par nom

Si les types de choix ne diffèrent pas, le choix du nom de l'élément lors de la création d'une instance de document est effectué à l'aide de l'attribut XmlChoiceIdentifierAttribute. Regardez la définition <choice> suivante :

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

Xsd.exe traduirait ce contenu de schéma XML en code, comme suit :

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

Le champ Item possède un attribut XmlChoiceIdentifier, en plus des deux attributs XmlElement. Le paramètre pour l'attribut XmlChoiceIdentifier est le nom d'une instance d'énumération. Le type énumération correspondant contient les choix d'élément. L'instance d'énumération apparaît avec un attribut XmlIgnore, de sorte que sa valeur ne peut pas être sérialisée.

Le développeur doit ensuite écrire du code pour assigner une valeur à l'instance d'énumération. La ligne suivante réalise cette opération pour un objet nommé i :

i.ItemElementName = ItemChoiceType.stringA;

Pour plus d'informations, consultez la classe XmlChoiceIdentifierAttribute.

Exemple

Le document de schéma XML d'entrée suivant montre différentes utilisations du regroupement <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>

Classes C# générées à partir du document de schéma XML précédent :

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

Document de schéma XML primaire généré à partir d'un assembly compilé depuis la source C# précédente. (Il existe un deuxième fichier .xsd généré afin de définir des éléments globaux arbitraires pour les types complexes ; ce fichier n'apparaît pas.)

<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>
Attributs possibles Prise en charge de la liaison

id

L'utilitaire Xsd.exe ignore l'attribut id qui a pour but de fournir un identificateur unique.

maxOccurs

Pour l'élément <choice>, 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 une valeur de 1, Xsd.exe produit le code comme expliqué dans Differentiating by Type et Differentiating by Name.

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.

Consultez l'attribut Prise en charge de la liaison de l'attribut MaxOccurs.

minOccurs

Lors de la génération du code source à partir d'un document de schéma XML, Xsd.exe ignore l'attribut minOccurs appliqué à l'élément <choice>.

Lors de la génération d'un document de schéma XML à partir de classes, Xsd.exe génère un élément <choice> avec une valeur minOccurs de 1 si l'élément choice représente un objet seul, ou une valeur de 0 s'il représente un tableau.

Consultez l'attribut Prise en charge de la liaison de l'attribut MinOccurs.

Éléments parents possibles : <choice>, <complexType>, <extension>, <group>, <restriction>, <sequence>

Les éléments enfants possibles:  <annotation>, <any>, <element>, <group>, <sequence>, <choice>

Voir aussi

Référence

XmlSchemaChoice

Footer image

Copyright ©2007 par Microsoft Corporation. Tous droits réservés.