Supporto dell'associazione all'elemento Choice
Questo argomento è specifico di una tecnologia legacy. Servizi Web XML e client di servizi Web XML devono essere creati attualmente tramite Windows Communication Foundation.
In .NET Framework è incluso il supporto per l'associazione all'elemento <choice> .
Se i tipi dei singoli elementi choice differiscono insieme ai rispettivi nomi, Xsd.exe applica solo attributi XmlElementAttribute a un membro pubblico. Se si distinguono solo in base al nome, Xsd.exe applica un attributo supplementare XmlChoiceIdentifierAttribute e inserisce una logica aggiuntiva che consente di effettuare la scelta.
Descrizione
L'elemento <choice> contiene due o più elementi figlio, ognuno dei quali rappresenta un elemento o un gruppo di elementi e indica che in un determinato documento di istanza è possibile visualizzare solo una di queste entità nella posizione specificata. Le scelte devono distinguersi in base al nome dell'elemento. Possono inoltre differire per tipo di elemento e, se la scelta rappresenta un raggruppamento (ad esempio un elemento <group>), per numero di elementi.
Combinazioni ambigue di gruppi producono risultati imprevedibili.
Differenziazione per tipo
Il caso più semplice si verifica quando i tipi dei singoli elementi si differenziano insieme ai rispettivi nomi. Si consideri la seguente definizione di <choice>:
<xsd:choice>
<xsd:element name="numberA" type="xsd:int"/>
<xsd:element name="numberB" type="xsd:decimal"/>
</xsd:choice>
In C# Xsd.exe convertirebbe questo contenuto di XML Schema nel codice seguente:
[System.Xml.Serialization.XmlElementAttribute("numberA", typeof(int))]
[System.Xml.Serialization.XmlElementAttribute("numberB", typeof(System.Decimal))]
public object Item;
Nel codice generato viene assegnato il tipo object al campo e vengono associati anche due attributi XmlElementAttribute. Un attributo indica di serializzare il tipo come istanza int e l'altro di serializzarlo come istanza System.Decimal. In questo caso la classe XmlSerializer utilizza il tipo correntemente assegnato all'oggetto. Con l'assegnazione seguente a un oggetto int
, viene utilizzato l'elemento <numberA>
:
Item = 1;
Quando le scelte presentano tipi di dati di XML Schema differenti, Xsd.exe associa ogni tipo di dati a una classe differente. PoichéSystem.Object è il tipo radice della gerarchia dei tipi .NET Framework, il campo generato appartiene sempre a un tipo base comune. La classe Object rappresenta il tipo base comune più generico.
Quando le scelte vengono tutte derivate da un tipo di dati comune definito da XML Schema, ad esempio mediante il costrutto <extension>, il tipo di campo è un'associazione di tale tipo di dati. Si supponga, ad esempio, che un elemento <choice>
offra una scelta tra l'elemento <a>
di DerivedTypeA
e l'elemento <b>
di DerivedTypeB
e che entrambi i tipi estendano il tipo BaseType
. In C# viene prodotto il seguente codice sorgente:
[System.Xml.Serialization.XmlElementAttribute("a", typeof(DerivedTypeA))]
[System.Xml.Serialization.XmlElementAttribute("b", typeof(DerivedTypeB))]
public BaseType Item;
Differenziazione per nome
Se i tipi di scelta non differiscono, la scelta del nome dell'elemento durante la creazione del documento di istanza viene effettuata mediante l'attributo XmlChoiceIdentifierAttribute. Si consideri la seguente definizione di <choice>
:
<xsd:choice>
<xsd:element name="stringA" type="xsd:string"/>
<xsd:element name="stringB" type="xsd:string"/>
</xsd:choice>
Xsd.exe convertirebbe questo contenuto di XML Schema nel codice seguente:
[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,
}
Il campo Item
include un attributo XmlChoiceIdentifier, oltre ai due attributi XmlElement. Il parametro dell'attributo XmlChoiceIdentifier è il nome di un'istanza di enumerazione. Il tipo di enumerazione corrispondente contiene le scelte dell'elemento. L'istanza di enumerazione viene visualizzata con un attributo XmlIgnore in modo che non sia possibile serializzarne il valore.
Lo sviluppatore deve quindi scrivere codice per assegnare un valore all'istanza di enumerazione. Nella riga seguente viene effettuata questa operazione per un oggetto denominato i
:
i.ItemElementName = ItemChoiceType.stringA;
Per ulteriori dettagli, vedere la classe XmlChoiceIdentifierAttribute.
Example
Nel documento XML Schema di input riportato di seguito vengono illustrati diversi utilizzi del raggruppamento <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>
Classi C# generate dal precedente documento XML Schema:
[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,
}
Documento XML Schema primario generato da un assembly compilato dal codice sorgente C# precedente: (Non visualizzato in un secondo file xsd generato per definire elementi globali arbitrari per i tipi complessi.)
<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>
Attributi possibili | Supporto per l'associazione |
---|---|
id |
L'utilità Xsd.exe ignora l'attributo id che fornisce un identificatore univoco. |
maxOccurs |
Per l'elemento <choice>, un valore maxOccurs pari a Per un valore di Per il valore Vedere l'attributo Supporto dell'associazione all'attributo MaxOccurs. |
minOccurs |
Durante la generazione di codice sorgente da un documento XML Schema, Xsd.exe ignora l'attributo minOccurs se è applicato all'elemento <choice>. Durante la generazione di un documento XML Schema dalle classi, Xsd.exe produce un elemento <choice> con un valore minOccurs pari a Vedere l'attributo Supporto dell'associazione all'attributo MinOccurs. |
Elementi padre possibili: <choice>, <complexType>, <extension>, <group>, <restriction>, <sequence>
Elementi figlio possibili: <annotation>, <any>, <element>, <group>, <sequence>, <choice>