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 of generic List collections for types in the .xsd file. Some people have suggested that svcutil.exe can be used as a replacement for xsd.exe if you pass the /dataContractOnly parameter to svcutil.exe. However, it seems like those people are mistaken because svcutil.exe actually generates System.Xml.XmlNode[] array properties instead of creating types based on the schema in the .xsd file.
我使用xsd。exe从.xsd文件中生成一些c#类。我遇到了同样的问题,在这里和其他一些xsd。exe生成类型[]数组,而不是.xsd文件中类型的泛型列表集合。有些人建议svcutil。exe可以作为xsd的替换。如果您将/dataContractOnly参数传递给svcutil.exe,则为exe。然而,这些人似乎错了,因为svcutil。exe实际上生成System.Xml。XmlNode[]数组属性,而不是基于.xsd文件中的模式创建类型。
For example, given this simple .xsd schema:
例如,给定这个简单的.xsd模式:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="Employee">
<xs:all>
<xs:element name="FirstName" type="xs:string"></xs:element>
<xs:element name="LastName" type="xs:string"></xs:element>
</xs:all>
</xs:complexType>
<xs:element name="Employees">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="Employee" type="Employee"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
'xsd.exe /classes Example.xsd' generates:
xsd。exe /类的例子。xsd的生成:
public partial class Employees {
private Employee[] employeeField;
public Employee[] Employee {
get { return this.employeeField; }
set { this.employeeField = value; }
}
}
public partial class Employee {
private string firstNameField;
private string lastNameField;
public string FirstName {
get { return this.firstNameField; }
set { this.firstNameField = value; }
}
public string LastName {
get { return this.lastNameField; }
set { this.lastNameField = value; }
}
}
'svcutil.exe /target:code /dataContractOnly /serializer:XmlSerializer /importXmlTypes /collectionType:System.Collections.Generic.List`1 Example.xsd' generates:
“svcutil。exe /target:code /dataContractOnly /serializer:XmlSerializer /importXmlTypes /collectionType:System.Collections.Generic. generic。清单1的例子。xsd的生成:
public partial class Employee : object, System.Runtime.Serialization.IExtensibleDataObject{
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
private string FirstNameField;
private string LastNameField;
public System.Runtime.Serialization.ExtensionDataObject ExtensionData{
get{ return this.extensionDataField; }
set{ this.extensionDataField = value; }
}
public string FirstName{
get{ return this.FirstNameField; }
set{ this.FirstNameField = value; }
}
public string LastName{
get{ return this.LastNameField; }
set{ this.LastNameField = value; }
}
}
public partial class Employees : object, System.Xml.Serialization.IXmlSerializable{
private System.Xml.XmlNode[] nodesField;
private static System.Xml.XmlQualifiedName typeName = new System.Xml.XmlQualifiedName("Employees", "http://tempuri.org/XMLSchema.xsd");
public System.Xml.XmlNode[] Nodes{
get{ return this.nodesField; }
set{ this.nodesField = value; }
}
public void ReadXml(System.Xml.XmlReader reader){
this.nodesField = System.Runtime.Serialization.XmlSerializableServices.ReadNodes(reader);
}
public void WriteXml(System.Xml.XmlWriter writer){
System.Runtime.Serialization.XmlSerializableServices.WriteNodes(writer, this.Nodes);
}
public System.Xml.Schema.XmlSchema GetSchema(){
return null;
}
public static System.Xml.XmlQualifiedName ExportSchema(System.Xml.Schema.XmlSchemaSet schemas){
System.Runtime.Serialization.XmlSerializableServices.AddDefaultSchema(schemas, typeName);
return typeName;
}
}
-
Is svcutil.exe really supposed to be a replacement for xsd.exe? The output generated seems to be quite different.
svcutil。exe真的应该是xsd。exe的替代品吗?所产生的输出似乎完全不同。
-
At this point, it looks like I will have to use xsd.exe to create classes from my .xsd file and then manually tweak the the code to get it in the form I want. I realize that using purely generated code would be ideal, but I was wondering if other people are using xsd.exe as a starting point and then working from there or if I need to consider another approach altogether?
此时,看起来我必须使用xsd。exe从我的.xsd文件中创建类,然后手动调整代码以获得我想要的表单。我意识到使用纯生成的代码是理想的,但是我想知道其他人是否在使用xsd。exe作为起点,然后从那里开始工作,或者如果我需要考虑另一种方法?
-
Are there any updates to xsd.exe in Visual Studio 2010?
xsd是否有任何更新。在Visual Studio 2010中?
5 个解决方案
#1
6
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。exe可以作为xsd的替换。但是听起来您在生成泛型集合时遇到了麻烦。svcutil。exe有一个集合类型开关,允许您指定用于集合的类型:
svcutil /o:Svc.cs /ct:System.Collections.Generic.List`1 http://example.com
#2
4
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.'
Andrew Hare上面的答案是可行的,但是jameswelle粘贴的示例命令刚好在他的最后一段代码之上:svcutil。exe /target:code /dataContractOnly /serializer:XmlSerializer /importXmlTypes /collectionType:System.Collections.Generic. generic。清单1的例子。xsd并不起作用,因为正如MSDN上所述,用于引用类型的/r和/ct交换机用于生成数据契约。在使用XmlSerializer时,这些开关不工作。
HTH.
HTH。
#3
2
I would just create your own xsd.exe. Sorry having trouble pasting but if you copy this code into your main:
我只需要创建你自己的xsd。exe。很抱歉粘贴有问题,但是如果您将此代码复制到您的主页:
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;
}
}
}
}
}
}
}
}
#4
1
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.
我在另一个模式上测试了相同的命令,ang从svcutil获得了类似的“垃圾”结果。因此,这可能是一种使它像xsd那样工作的方法。但是到目前为止,我所看到的都不是那么有用。
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.
更新的答案:我发现当所有引用的XSD都被强制包含时,许多xml节点的通用数组被强类型替换。在我的例子中,我有许多xsd文件都是相互引用的,但是svcutil似乎没有包含它们。我不得不告诉它使用*。将它们全部获取。
#5
1
I have found Xsd2Code to be much better than xsd.exe does does exactly what you need. See here: http://xsd2code.codeplex.com/
我发现Xsd2Code比xsd好多了。exe完成所需的工作。在这里看到的:http://xsd2code.codeplex.com/
#1
6
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。exe可以作为xsd的替换。但是听起来您在生成泛型集合时遇到了麻烦。svcutil。exe有一个集合类型开关,允许您指定用于集合的类型:
svcutil /o:Svc.cs /ct:System.Collections.Generic.List`1 http://example.com
#2
4
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.'
Andrew Hare上面的答案是可行的,但是jameswelle粘贴的示例命令刚好在他的最后一段代码之上:svcutil。exe /target:code /dataContractOnly /serializer:XmlSerializer /importXmlTypes /collectionType:System.Collections.Generic. generic。清单1的例子。xsd并不起作用,因为正如MSDN上所述,用于引用类型的/r和/ct交换机用于生成数据契约。在使用XmlSerializer时,这些开关不工作。
HTH.
HTH。
#3
2
I would just create your own xsd.exe. Sorry having trouble pasting but if you copy this code into your main:
我只需要创建你自己的xsd。exe。很抱歉粘贴有问题,但是如果您将此代码复制到您的主页:
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;
}
}
}
}
}
}
}
}
#4
1
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.
我在另一个模式上测试了相同的命令,ang从svcutil获得了类似的“垃圾”结果。因此,这可能是一种使它像xsd那样工作的方法。但是到目前为止,我所看到的都不是那么有用。
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.
更新的答案:我发现当所有引用的XSD都被强制包含时,许多xml节点的通用数组被强类型替换。在我的例子中,我有许多xsd文件都是相互引用的,但是svcutil似乎没有包含它们。我不得不告诉它使用*。将它们全部获取。
#5
1
I have found Xsd2Code to be much better than xsd.exe does does exactly what you need. See here: http://xsd2code.codeplex.com/
我发现Xsd2Code比xsd好多了。exe完成所需的工作。在这里看到的:http://xsd2code.codeplex.com/