Поддержка привязки элемента Choice
Этот раздел посвящен технологии прежних версий. Веб-службы XML и клиенты веб-служб XML должны создаваться с использованием Windows Communication Foundation.
Платформа .NET Framework обеспечивает поддержку привязки для элемента <choice>.
Если отдельные элементы выбора отличаются как по типам, так и по именам, программа Xsd.exe применяет к открытому члену только атрибут XmlElementAttribute. Если они отличаются только по имени, программа Xsd.exe дополнительно применяет атрибут XmlChoiceIdentifierAttribute и вставляет дополнительную логику для выбора.
Объяснение
Элемент <choice> содержит не менее двух дочерних элементов, каждый из которых представляет элемент или группу элементов. Он указывает, что, в определенном документе экземпляра, в указанной позиции может появляться только одна из этих сущностей. Варианты выбора могут различаться по имени элемента. Они могут также отличаться типами элементов и, если вариант выбора является группированием (например, элемент <group>), количеством элементов.
Неоднозначные сочетания групп приводят к непредсказуемым результатам.
Различение по типу
Самый простой случай возникает, когда различаются как типы, так и имена индивидуальных элементов. Рассмотрим следующее определение элемента <choice>:
<xsd:choice>
<xsd:element name="numberA" type="xsd:int"/>
<xsd:element name="numberB" type="xsd:decimal"/>
</xsd:choice>
На языке C# программа Xsd.exe преобразует содержимое этой схемы XML в следующий код:
[System.Xml.Serialization.XmlElementAttribute("numberA", typeof(int))]
[System.Xml.Serialization.XmlElementAttribute("numberB", typeof(System.Decimal))]
public object Item;
В созданном коде полю назначен тип object, однако оно также имеет два атрибута XmlElementAttribute. Один атрибут указывает, что этот тип следует сериализовать как экземпляр int; другой указывает, что тип следует сериализовать как экземпляр System.Decimal. В этом случае класс XmlSerializer использует тип, назначенный объекту в это время. С приведенным ниже присвоением объекту int
используется элемент <numberA>
:
Item = 1;
Если варианты выбора имеют различные типы данных схемы XML, программа Xsd.exe выполняет привязку каждого типа данных к отдельному классу. Так как System.Object является корневым классом в иерархии типов платформы .NET Framework, созданное поле всегда принадлежит к базовому типу. Класс Object является самым универсальным общим базовым типом.
Если все варианты выбора являются производными от общего типа данных, определенного в схеме XML, например через конструкцию <extension>, то тип поля является привязкой этого типа данных. Например, допустим, что элемент <choice>
предлагает выбор между элементом <a>
типа DerivedTypeA
и элементом <b>
типа DerivedTypeB
, и оба типа являются расширением типа BaseType
. В C# создается следующий исходный код:
[System.Xml.Serialization.XmlElementAttribute("a", typeof(DerivedTypeA))]
[System.Xml.Serialization.XmlElementAttribute("b", typeof(DerivedTypeB))]
public BaseType Item;
Различение по имени
Если типы вариантов выбора не различаются, при создании документа экземпляра с помощью атрибута XmlChoiceIdentifierAttribute создается выбор по имени элемента. Рассмотрим следующее определение элемента <choice>
:
<xsd:choice>
<xsd:element name="stringA" type="xsd:string"/>
<xsd:element name="stringB" type="xsd:string"/>
</xsd:choice>
Программа Xsd.exe преобразует содержимое этой схемы XML в следующий код:
[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,
}
Поле Item
имеет атрибут XmlChoiceIdentifier в дополнение к двум атрибутам XmlElement. Параметром атрибута XmlChoiceIdentifier является имя экземпляра перечисления. Соответствующий тип перечисления содержит варианты выбора элемента. Экземпляр перечисления имеет атрибут XmlIgnore, поэтому его значение не может быть сериализовано.
Разработчик должен затем написать код для присвоения значения экземпляру перечисления. В следующей строке это сделано для объекта с именем i
.
i.ItemElementName = ItemChoiceType.stringA;
Дополнительные сведения см. в описании класса XmlChoiceIdentifierAttribute.
Example
Следующий входной документ схемы XML демонстрирует различные применения группирования <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>
Классы C#, созданные на основе приведенного выше документа схемы XML:
[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,
}
Основной документ схемы XML, созданный из сборки, скомпилированной на основе предыдущего исходного кода C#. (Не показан второй файл .xsd, который создается для задания произвольных глобальных элементов для сложных типов.)
<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>
Возможные атрибуты | Поддержка привязки |
---|---|
id |
Программа Xsd.exe пропускает атрибут id, который предназначен для обеспечения уникального идентификатора. |
maxOccurs |
Для элемента <choice> значение maxOccurs, равное Для значения Для значения См. описание атрибута Поддержка привязки атрибута MaxOccurs. |
minOccurs |
При создании исходного кода из документа схемы XML программа Xsd.exe не обрабатывает атрибут minOccurs, примененный к элементу <choice>. При создании документа схемы XML из классов программа Xsd.exe создает элемент <choice> со значением атрибута minOccurs, равным См. описание атрибута Поддержка привязки атрибута MinOccurs. |
Возможные родительские элементы: <choice>, <complexType>, <extension>, <group>, <restriction>, <sequence>
Возможные дочерние элементы: <annotation>, <any>, <element>, <group>, <sequence>, <choice>