Consider the following XSD:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ContainingClass" type="ContainingClass" />
<xs:complexType name="ContainingClass">
<xs:sequence>
<xs:element name="OuterArrayContainer" type="OuterArrayContainer" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="OuterArrayContainer">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="10" name="OuterArray" type="InnerArrayContainer" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="InnerArrayContainer">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="10" name="InnerArray" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Assuming that the above XSD is in a file called "test.xsd", I can run the following command to create a C# wrapper for it:
xsd test.xsd /c
The C# output looks like this (after removing XML attributes for brevity):
public partial class ContainingClass {
private int[][] outerArrayContainerField;
public int[][] OuterArrayContainer {
get { return this.outerArrayContainerField; }
set { this.outerArrayContainerField = value; }
}
}
As you can see, it has lost the inner types altogether and replaced them with a single jagged int array. I want to preserve the inner types.
If I add dummy elements to the XSD like so:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ContainingClass" type="ContainingClass" />
<xs:complexType name="ContainingClass">
<xs:sequence>
<xs:element name="OuterArrayContainer" type="OuterArrayContainer" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="OuterArrayContainer">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="10" name="OuterArray" type="InnerArrayContainer" />
<xs:element name="Dummy" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="InnerArrayContainer">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="10" name="InnerArray" type="xs:int" />
<xs:element name="Dummy" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Then the output is:
public partial class ContainingClass {
private OuterArrayContainer outerArrayContainerField;
public OuterArrayContainer OuterArrayContainer {
get { return this.outerArrayContainerField; }
set { this.outerArrayContainerField = value; }
}
}
public partial class OuterArrayContainer {
private InnerArrayContainer[] outerArrayField;
private int dummyField;
public InnerArrayContainer[] OuterArray {
get { return this.outerArrayField; }
set { this.outerArrayField = value; }
}
public int Dummy {
get { return this.dummyField; }
set { this.dummyField = value; }
}
}
public partial class InnerArrayContainer {
private int[] innerArrayField;
private int dummyField;
public int[] InnerArray {
get { return this.innerArrayField; }
set { this.innerArrayField = value; }
}
public int Dummy {
get { return this.dummyField; }
set { this.dummyField = value; }
}
}
This preserves the inner types, but at the expense of having an unused dummy property.
My question is: Is there a way to do this without introducing a dummy element (and without having to go and manually edit the output C# code)?
(It's entirely possibly that I'm going about this in completely the wrong way...)
Short answer is no. In this particular instance, this seems like a bug with XSD.exe, but even then, it has always had poor support for complex types in general, as its generated code is heavily serialization/deserialization-oriented, not schema-oriented, so it makes only the bare minimum effort to model schema semantics.
What I recommend using is another tool called 'dotnet-xscgen' from https://github.com/mganss/XmlSchemaClassGenerator (view instructions on how to install/use it here)
It generates code that is still very similar to XSD.exe (i.e.
XmlSerializercompatible) but is much improved. When running your original schema (without the dummy elements), it generates the following code (I've removed all attributes for brevity):Microsoft do not appear to be interested in improving XML tooling so others have taken up the slack.