I am using xsd.exe to generate some c# classes from a .xsd file. I ran into the same issue that is covered here and on other sites where xsd.exe generates Type[] arrays instead
Yes, svcutil.exe
can be used as a replacement for xsd.exe
but it sounds like you are having trouble getting generic collections to be generated. svcutil.exe
has a collectionType
switch that allows you to specify the type to be used for a collection:
svcutil /o:Svc.cs /ct:System.Collections.Generic.List`1 http://example.com
Clarification
Andrew Hare's answer above will work, but the example command that jameswelle pasted just above his last section of code:svcutil.exe /target:code /dataContractOnly /serializer:XmlSerializer /importXmlTypes /collectionType:System.Collections.Generic.List`1 Example.xsd
does not work because, as stated on MSDN, '. . .the /r and /ct switches for referencing types are for generating data contracts. These switches do not work when using XmlSerializer.'
HTH.
I have found Xsd2Code to be much better than xsd.exe does does exactly what you need. See here: http://xsd2code.codeplex.com/
I would just create your own xsd.exe. Sorry having trouble pasting but if you copy this code into your main:
XmlSchemas xsds = new XmlSchemas();
xsds.Add(xsd);
xsds.Compile(null, true);
XmlSchemaImporter schemaImporter = new XmlSchemaImporter(xsds);
// create the codedom
CodeNamespace codeNamespace = new CodeNamespace(strNamespace);
XmlCodeExporter codeExporter = new XmlCodeExporter(codeNamespace);
List<XmlTypeMapping> maps = new List<XmlTypeMapping>();
foreach (XmlSchemaType schemaType in xsd.SchemaTypes.Values)
{
maps.Add(schemaImporter.ImportSchemaType(schemaType.QualifiedName));
}
foreach (XmlSchemaElement schemaElement in xsd.Elements.Values)
{
maps.Add(schemaImporter.ImportTypeMapping(schemaElement.QualifiedName));
}
foreach (XmlTypeMapping map in maps)
{
codeExporter.ExportTypeMapping(map);
}
ReplaceArrayWithList(codeNamespace);
// Check for invalid characters in identifiers
CodeGenerator.ValidateIdentifiers(codeNamespace);
// output the C# code
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
using (StreamWriter writer = new StreamWriter(strCsPath, false))
{
codeProvider.GenerateCodeFromNamespace(codeNamespace, writer, new CodeGeneratorOptions());
}
}
private static void ReplaceArrayWithList(CodeNamespace codeNamespace)
{
codeNamespace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
foreach (CodeTypeDeclaration codeType in codeNamespace.Types)
{
foreach (CodeTypeMember member in codeType.Members)
{
if (member is CodeMemberField)
{
CodeMemberField field = (CodeMemberField)member;
if (field.Type.ArrayRank > 0)
{
CodeTypeReference type = new CodeTypeReference();
type.BaseType = "List<" + field.Type.BaseType + ">";
field.Type = type;
}
}
if (member is CodeMemberProperty)
{
CodeMemberProperty property = (CodeMemberProperty)member;
if (property.Type.ArrayRank > 0)
{
CodeTypeReference type = new CodeTypeReference();
type.BaseType = "List<" + property.Type.BaseType + ">";
property.Type = type;
}
}
}
}
}
}
}
I have tested the same commands on another schema, ang received similar "junk" results from svcutil. So, the might be a way to make it work like xsd.exe, but so far all Ive seen are far less useful ones.
Updated answer: I found that many of these generic arrays of xml nodes were replaced by strong types when all the referenced XSD's are forcibly included. In my case, i have many xsd files all referenced by each other, but svcutil doesnt seem to include them. i had to instead tell it to use *.xsd to get them all.