DataContractSerializer.ReadObject() fails to create object when used with SvcUtils.exe - xsd

I ran SvcUtil.exe against XSD file to generate class. Then tried to create Object out of XML using following line. I get error shown below. Please see the detailed code below.
PersonType prs = (PersonType)xs.ReadObject(new MemoryStream(File.ReadAllBytes(sFileName)));
Error in line 3 position 58. Expecting element 'PersonType' from namespace 'http://service.a1.com/base1/2005/'.. Encountered 'Element' with name 'Person', namespace 'http://service.a1.com/base1/2005/'.
Command Used
svcutil.exe" "C:\Temp\S1\UseXSDExe\UseXSDExe\Sample2\Prs.xsd" /t:code /language:cs /out:C:\SPrxy.cs /dconly
Full code
(class generated by SvcUtils.exe)
[assembly: System.Runtime.Serialization.ContractNamespaceAttribute("http://service.a1.com/base1/2005/", ClrNamespace="service.a1.com.base1._2005")]
namespace service.a1.com.base1._2005
{
using System.Runtime.Serialization;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="PersonType", Namespace="http://service.a1.com/base1/2005/")]
public partial class PersonType : object, System.Runtime.Serialization.IExtensibleDataObject
{
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
private string LastNameField;
private string FirstNameField;
public System.Runtime.Serialization.ExtensionDataObject ExtensionData
{
get
{
return this.extensionDataField;
}
set
{
this.extensionDataField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute(IsRequired=true, EmitDefaultValue=false)]
public string LastName
{
get
{
return this.LastNameField;
}
set
{
this.LastNameField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=1)]
public string FirstName
{
get
{
return this.FirstNameField;
}
set
{
this.FirstNameField = value;
}
}
}
}
(code used for converting XML to object)
public static void convertToObject(string sFileName)
{
DataContractSerializer xs = new DataContractSerializer(typeof(PersonType));
PersonType Person = (PersonType)xs.ReadObject(new MemoryStream(File.ReadAllBytes(sFileName)));
}
(XSD)
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://service.a1.com/base1/2005/" xmlns:bse1="http://service.a1.com/base1/2005/" elementFormDefault="qualified">
<xs:complexType name="PersonType">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="LastName" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="FirstName" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="Person" type="bse1:PersonType"/>
</xs:schema>
(XML)
<?xml version="1.0" encoding="utf-8"?>
<pr:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://service.a1.com/base1/2005/ Prs.xsd"
xmlns:pr="http://service.a1.com/base1/2005/">
<pr:LastName> Lane </pr:LastName>
<pr:FirstName> Fane </pr:FirstName>
</pr:Person>
I ran XSD.exe on same XSD file. Then I was able to convert XML to Object using XmlSerializer.Deserialize().
XSD does not have any attribute. I have validated XML against XSD.
Please let me know why Deserialize() fails.

Your XSD specifies a root element name and data type name that are different:
<xs:element name="Person" type="bse1:PersonType"/>
When svcutil.exe generates data contract classes for this type, it puts the type name into the data contract rather than the root element name. This appears to be intentional, see Svcutil generates wrong Name property value in DataContractAttribute. Perhaps it does this since the contract type itself could be re-used anywhere in the object graph, and there's no data contract equivalent of XmlRoot that applies only when the type in question is the document's root element.
As a workaround, you have a couple options:
Hardcode the expected root element name when constructing the serializer:
var xs = new DataContractSerializer(typeof(service.a1.com.base1._2005.PersonType), "Person", "http://service.a1.com/base1/2005/");
Preload the XML into an XDocument and use the actual root element name when constructing the serializer:
var doc = XDocument.Load(sFileName);
service.a1.com.base1._2005.PersonType person;
var xs = new DataContractSerializer(typeof(service.a1.com.base1._2005.PersonType), doc.Root.Name.LocalName, "http://service.a1.com/base1/2005/");
using (var reader = doc.CreateReader())
{
person = (service.a1.com.base1._2005.PersonType)xs.ReadObject(reader);
}
Or use XmlSerializer.

Related

Mapper library for xml to java objects

We are creating jaxb classes for a predefined schema. The schema contains certain elements which uses xs:choice to create complexTypes. In this case the binding being generated contain a List which makes it complex as we have to identify the actual instance and then cast it. We tried using the binding customization attribute "choiceContentProperty="false"" to change this behavior. But this does not seem to work. Any suggestions to override this behavior?
Disclaimer: I am the author of jaxb2-simplify-plugin.
This is a use case for the jaxb2-simplify-plugin.
This:
<xs:complexType name="typeWithElementsProperty">
<xs:choice maxOccurs="unbounded">
<xs:element name="foo" type="xs:string"/>
<xs:element name="bar" type="xs:int"/>
</xs:choice>
</xs:complexType>
Normally generates this:
#XmlElements({
#XmlElement(name = "foo", type = String.class)
#XmlElement(name = "bar", type = Integer.class),
})
protected List<Serializable> fooOrBar;
But with jaxb2-simplify-plugin you'll get this:
#XmlElement(name = "foo", type = String.class)
protected List<String> foo;
#XmlElement(name = "bar", type = Integer.class)
protected List<Integer> bar;

What should I change to get a different element name on the response XSD of an automatically generated JAX-WS?

I have created a Web Service in Java with JAX-WS. It is a simple one that just returns an uppercased version of a String:
#WebService(endpointInterface = "mod2.Mod2")
public class Mod2Impl implements Mod2 {
#Override
public String mod2(String x) {
return x.toUpperCase();
}
}
and its interface:
#WebService
public interface Mod2 {
#WebMethod
String mod2(String x);
}
JAX generates the mod2.jaxws package for me with the relevant classes. The response is like this:
#XmlRootElement(name = "mod2Response", namespace = "http://mod2/")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "mod2Response", namespace = "http://mod2/")
public class Mod2Response {
#XmlElement(name = "return", namespace = "")
private String _return;
/**
*
* #return
* returns String
*/
public String getReturn() {
return this._return;
}
/**
*
* #param _return
* the value for the _return property
*/
public void setReturn(String _return) {
this._return = _return;
}
}
When deployed it generates the proper WSDL file with an import to an XSD. This is the XSD:
<xs:schema xmlns:tns="http://mod2/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://mod2/">
<xs:element name="mod2" type="tns:mod2"/>
<xs:element name="mod2Response" type="tns:mod2Response"/>
<xs:complexType name="mod2">
<xs:sequence>
<xs:element name="arg0" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="mod2Response">
<xs:sequence>
<xs:element name="return" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Now, what I want is to change the element named "return" in the XSD for whatever I want. I have tried changing the #XmlElement(name = "return", namespace = "") in the Mod2Response class but this throws the following error:
GRAVE: WSSERVLET11: failed to parse runtime descriptor: javax.xml.ws.WebServiceException: class mod2.jaxws.Mod2Response do not have a property of the name return
What is it I have to change to achieve this?
I have found the answer here.
I added #WebResult(name="mod2Result") to my interface:
#WebService
public interface Mod2 {
#WebMethod
#WebResult(name="mod2Result")
String mod2(String x);
}
and then run the wsgen again. Which generated the following Response:
#XmlRootElement(name = "mod2Response", namespace = "http://mod2/")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "mod2Response", namespace = "http://mod2/")
public class Mod2Response {
#XmlElement(name = "mod2Result", namespace = "")
private String mod2Result;
/**
*
* #return
* returns String
*/
public String getMod2Result() {
return this.mod2Result;
}
/**
*
* #param mod2Result
* the value for the mod2Result property
*/
public void setMod2Result(String mod2Result) {
this.mod2Result = mod2Result;
}
}
which also has the #XmlElement(name = "mod2Result") as stated by Joshi but it also changed the name of variable, setter and getter. I tried with the #XmlElement straight in the Response class only with no success.
#WebService
public interface Mod2 {
#WebMethod
#XMLElement(name="returnChanged")
String mod2(String x);
}
You can try this code in your web service. This is a pseudo code.

jaxb xjc creating List< Objects > instead of List< String >

I have an xsd like this -
<xs:element name="teachers" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="teacher" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
When I use XJC to generate class bindings, I see teacher is of type - List < Object > instead of List< String >
protected List<Object> teacher;
public List<Object> getTeacher() {
if (teacher == null) {
teacher = new ArrayList<Object>();
}
return this.teacher;
}
How can I make it to generate List of strings instead of objects? Any help is appreciated.
Update: With the solution provided by 'vamsilp' - After removing the "minOccurs" on "teachers" element, it worked just fine!That XSD is autogenerated by Jersey from this code:
#XmlElementWrapper(name = "teachers")
#XmlElement(name = "teacher")
public StringSet getTeachers() {
return getData().getTeacherss();
I am not sure how to remove the "minOccurs" attribute. Do I need to modify my code to ignore it?
First of all I just dont understand how you are able to generate classes, instead it should show you an error saying "'minOccurs' cannot appear in element 'element'" because you have declared minOccur constraint to your global/root element "teachers". You shouldn't be doing that please refer this. Try regenerating your JAXB classes by removing this constraint that should work

Cast JAXB2 generated object to JAXBElement?

I have 2 sets of XSD's, one that generates RPC based calls, and another that defines the product specific methods. The RpcType object (generated by JAXB2) has a 'setRpcOperation' method defined by:
RpcType.setRpcOperation(JAXBElement<? extends RpcOperationType>)
That 'RpcOperation' object should be the 'specific product method' described above. One example is (also generated by JAXB2):
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "get-user-stats", propOrder = {
"reset"
})
public class GetUserStats {
protected Boolean reset;
/**
* Gets the value of the reset property.
*
* #return
* possible object is
* {#link Boolean }
*
*/
public Boolean isReset() {
return reset;
}
/**
* Sets the value of the reset property.
*
* #param value
* allowed object is
* {#link Boolean }
*
*/
public void setReset(Boolean value) {
this.reset = value;
}
}
Now, is it possible to create an instance of 'GetUserStatus' and add it to the RpcType object via setRpcOperation?
This type of scenario is common:
One schema to represent the message
Multiple schemas to represent the payload.
Below is one way this could be done:
Message Schema - message.xsd
Have one XML schema to represent your message envelope. Introduce one type to represent the body of the message. This type will be extended by the different payloads.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/message"
xmlns="http://www.example.org/message"
elementFormDefault="qualified">
<xsd:element name="message">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="body" type="body"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="body">
</xsd:complexType>
</xsd:schema>
Payload Schema - customer.xsd
This schema corresponds to a specific type of message payload. Notice how the customer type extends the body type from the message schema.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
targetNamespace="http://www.example.org/customer"
xmlns="http://www.example.org/customer"
xmlns:m="http://www.example.org/message"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:import schemaLocation="message.xsd" namespace="http://www.example.org/message"/>
<xsd:complexType name="customer">
<xsd:complexContent>
<xsd:extension base="m:body">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
org.example.message.package-info
This class was generated from message.xsd.
#javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.org/message", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.example.message;
org.example.message.Message
This class was generated from message.xsd.
package org.example.message;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"body"
})
#XmlRootElement(name = "message")
public class Message {
#XmlElement(required = true)
protected Body body;
public Body getBody() {
return body;
}
public void setBody(Body value) {
this.body = value;
}
}
org.example.message.Body
This class was generated from message.xsd.
package org.example.message;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "body")
public class Body {
}
org.example.customer.package-info
This class was generated from customer.xsd.
#javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.org/customer", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.example.customer;
org.example.customer.Customer
This class was generated from customer.xsd.
package org.example.customer;
import javax.xml.bind.annotation.*;
import org.example.message.Body;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "customer", propOrder = {
"name"
})
public class Customer extends Body {
#XmlElement(required = true)
protected String name;
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
}
Demo Class
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import org.example.customer.*;
import org.example.message.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Message.class, Customer.class);
Message message = new Message();
Customer customer = new Customer();
customer.setName("Jane Doe");
message.setBody(customer);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(message, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<message xmlns="http://www.example.org/message" xmlns:ns2="http://www.example.org/customer">
<body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:customer">
<ns2:name>Jane Doe</ns2:name>
</body>
</message>
EDIT #1
In response to your second question (Cast JAXB2 generated object to JAXBElement?)
I don't see where the JAXBElement comes into play with this example. I am able to run the following code:
import generated.GetFailedLoginCount;
import ietf.params.xml.ns.netconf.base._1.RpcType;
public class Demo {
public static void main(String[] args) {
RpcType rpc = new RpcType();
rpc.setMessageId("123");
GetFailedLoginCount rpcOperation = new GetFailedLoginCount();
rpc.setRpcOperation(rpcOperation);
}
}
EDIT #2
After changing the import to import to http://www.iana.org/assignments/xml-registry/schema/netconf.xsd I'm seeing the same behaviour as you.
To set the property correctly you will need to do something like:
RpcType rpc = new RpcType();
GetFailedLoginCount rpcOperation = new GetFailedLoginCount();
rpcOperation.setReset(true);
JAXBElement<GetFailedLoginCount> rpcOperationJE = new JAXBElement(new QName("foo"), GetFailedLoginCount.class, rpcOperation);
rpc.setRpcOperation(rpcOperationJE);
JAXBElement supplies the element name for the GetFailedLoginCount value. This is required because the element corresponding to the rpcOperation property is substitutable:
<xs:element name="get-config" type="getConfigType" substitutionGroup="rpcOperation" />
In your schema that imports netconf.xsd you should have an element of type "get-failed-login-count" that can be substituted for "rpcOperation". This will be supplied as a QName to the JAXBElement. Since we used element name "foo" above the schema update would look like:
<xs:element name="foo" type="get-failed-login-count" substitutionGroup="rpcOperation" />
Ok, so here is a subset of what I am trying to do. The above example was extremely helpful, but I still am not able to create a JAXBElement:
Base envelope can be found: http://www.iana.org/assignments/xml-registry/schema/netconf.xsd
Payload for rpcOperationType (I added the ** lines):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:dmi="http://xml.juniper.net/dmi"
** xmlns:netconf="urn:ietf:params:xml:ns:netconf:base:1.0"
>
**<xs:import schemaLocation="netconf.xsd" namespace="urn:ietf:params:xml:ns:netconf:base:1.0"/>
<!-- get-failed-login-count -->
<xs:complexType name="get-failed-login-count">
**<xs:complexContent>
** <xs:extension base="netconf:rpcOperationType">
<xs:annotation>
<xs:appinfo>
<dmi:rpc-info>
<name>Get failed login count for Authentication failure and Exceeded user</name>
<description>
This command returns the Number of Logins refused due to exceeding allowed limits and Auth failure (24 hour moving window)
</description>
<rpc-reply-tag>failed-login-count</rpc-reply-tag>
</dmi:rpc-info>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
<xs:element name="reset" type="xs:boolean" minOccurs="0">
<xs:annotation>
<xs:appinfo>
<dmi:param-info>
<name>Reset Stats</name>
<description>
This will govern the reseting of this statistics data. By default, the data is not reset.
</description>
</dmi:param-info>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:sequence>
** </xs:extension>
**</xs:complexContent>
</xs:complexType>
Now, the generated GetFailedLogin class extends RpcOperationType, but I am not sure how to set it in the RpcType object:
RpcType rpc = new RpcType();
rpc.setMessageId("123");
GetFailedLoginCount rpcOperation = new GetFailedLoginCount();
rpc.setRpcOperation(); // Expects JAXBElement<? Extends RpcOperationType>

Any way to override how <choice> element is binded by xsd.exe

I have the following elements in my schema:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="optimizeModelBase">
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
<xs:complexType name="riskModel">
<xs:complexContent>
<xs:extension base="optimizeModelBase">
<xs:attribute name="type" type="xs:string" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="fullCovariance">
<xs:complexContent>
<xs:extension base="optimizeModelBase">
<xs:attribute name="fromDate" type="xs:date" use="required"/>
<xs:attribute name="toDate" type="xs:date" use="required"/>
<xs:attribute name="windowSize" type="xs:int" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
In my main schema body, I use a element to specify a 1-of situation:
<xs:choice id="RiskModelParameter">
<xs:element name="RiskModel" type="riskModel"/>
<xs:element name="FullCovariance" type="fullCovariance"/>
</xs:choice>
When I run xsd.exe, the resulting code is:
[System.Xml.Serialization.XmlElementAttribute("FullCovariance",
typeof(fullCovariance))]
[System.Xml.Serialization.XmlElementAttribute("RiskModel",
typeof(riskModel))]
public optimizeModelBase Item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
The issue is that the element's ID tag is being ignored, and xsd.exe is arbitrarily naming the property "Item". I have to admit, it's not a big issue, but it's starting to annoy me. What makes this extra annoying is that if I have additional elements at the same level, xsd.exe binds them as "Item1", "Item2", etc.
Does anyone know if it's possible to not have xsd.exe name my choice elements as "Item", and instead be able to put in my own property names?
I've searched high and low, but it seems like there is no solution for my problem. According to the link:
http://msdn.microsoft.com/en-us/library/sa6z5baz(VS.80).aspx
It seems like the arbitrary naming of the choice element is not overrideable. Hopefully this information is helpful to others out there...!
Just had this exact problem today.
I do have a workaround so you can circumvent this problem using a group instead of choice.
using the above xsd as the basis:
Rewrite:
<xs:choice id="RiskModelParameter">
<xs:element name="RiskModel" type="riskModel"/>
<xs:element name="FullCovariance" type="fullCovariance"/>
</xs:choice>
To:
<xs:group name="RiskModelGroup">
<xs:sequence>
<xs:element name="RiskModel" type="riskModel"/>
<xs:element name="FullCovariance" type="fullCovariance"/>
</xs:sequence>
</xs:group>
Reference the group in your element:
<xs:element name="Foo">
<xs:complexType>
<xs:sequence>
<xs:element name="SomeFieldId" type="xs:int" />
<xs:group ref="RiskModelGroup" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Run xsd.exe and the result is as follows
public partial class Foo {
private int someFieldIdField;
private riskModel riskModelField;
private fullCovariance fullCovarianceField;
/// <remarks/>
public int SomeFieldId {
get {
return this.someFieldIdField;
}
set {
this.someFieldIdField = value;
}
}
/// <remarks/>
public riskModel RiskModel {
get {
return this.riskModelField;
}
set {
this.riskModelField = value;
}
}
/// <remarks/>
public fullCovariance FullCovariance {
get {
return this.fullCovarianceField;
}
set {
this.fullCovarianceField = value;
}
}
}
Now you have property names RiskModel and FullCovariance
Foo f = new Foo()
f.RiskModel.name
or
f.FullCovariance.fromDate
If you require multiple Items of RiskModels and FullCovariance objects you could add a new element having the RiskModelGroup within a sequence.
Good luck!
For those who still want to know : Just use XSDObjectGenerator (made by Microsoft). It manage XsdChoice by adding one object for each choice to your class. That way, you don't have to look for the right element to use for the Item property.
For example:
<xs:complexType name="AccountSchemeName1Choice">
<xs:sequence>
<xs:choice>
<xs:element name="Cd" type="ExternalAccountIdentification1Code"/>
<xs:element name="Prtry" type="Max35Text"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
became
[XmlType(TypeName = "AccountSchemeName1Choice", Namespace = Declarations.SchemaVersion), Serializable]
public class AccountSchemeName1Choice : INotifyPropertyChanged
{
[XmlElement(ElementName = "Cd", IsNullable = false, Form = XmlSchemaForm.Qualified, DataType = "string", Namespace = Declarations.SchemaVersion)]
public string __Cd;
[XmlIgnore]
public string Cd
{
get { return __Cd; }
set { __Cd = value; RaisePropertyChanged("Cd"); }
}
[XmlElement(ElementName = "Prtry", IsNullable = false, Form = XmlSchemaForm.Qualified, DataType = "string", Namespace = Declarations.SchemaVersion)]
public string __Prtry;
[XmlIgnore]
public string Prtry
{
get { return __Prtry; }
set { __Prtry = value; RaisePropertyChanged("Prtry"); }
}
public AccountSchemeName1Choice()
{
}
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
I once actually parsed an autogenerated xsd.exe file and changed it using NRefactory.
I myself just encountered this limitation in my dealings with XSD.exe. It seems that this is a fairly uniform practice with respect to how XSD.exe interprets the ID attribute for all element types. I'd love to hear a rationalization from someone on the MS development team for why XSD.exe works in this manner.
What's interesting is that I have been working on a SchemaImporterExtension that would, among other things, leverage the ID attribute of choice elements to achieve precisely what you're describing, a means of customizing the field/property names of choice mapped object members.
Unfortunately, not only does it seem that XSD.exe doesn't support ID attribute binding, but it doesn't even appear that ID is included in the XmlSchemaChoice object that reflects the choice element from the parsed schema document.
Perhaps I'm missing something, but if this is indeed the intended behavior and not an error on my part, then it's a pretty ridiculous omission in my estimation, and it speaks to just how much of a neutered XSD representation is reflected in the MS schema auto-generation tools.
XSD.exe adheres to what I'll term as a "lean and mean" interpretation of the XML schema standard. Apparently now WCF obviates XSD.exe, and guess what? WCF's svcutil tool recognizes an even smaller footprint of XML schema; choice element binding is even't supported in svcutil IIRC.
At some point I'm not even sure what value the MS auto-generation tools are going to bring to the table, because you're going to be reduced to using trivial XSD structures (I mean, no choice element support? Really?) to encapsulate your business object modeling.

Resources