I'm trying to generate an xs:schema from any .net Type programmatically. I know I could use reflection and generate it by iterating over the public properties, but is there a built in way?
我正在尝试以编程方式从任何.net类型生成xs:schema。我知道我可以使用反射并通过迭代公共属性来生成它,但是有内置的方法吗?
Example:
例:
[Serializable]
public class Person
{
[XmlElement(IsNullable = false)] public string FirstName { get; set; }
[XmlElement(IsNullable = false)] public string LastName { get; set; }
[XmlElement(IsNullable = true)] public string PhoneNo { get; set; }
}
Desired Output:
期望的输出:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Person" type="Person" />
<xs:complexType name="Person">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" form="unqualified" name="FirstName" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" form="unqualified" name="LastName" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" form="unqualified" name="PhoneNo" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
5 个解决方案
#1
13
I found the accepted answer generated an incorrect schema given some of my attributes. e.g. It ignored custom names for enum values marked with [XmlEnum(Name="Foo")]
我发现接受的答案会产生一些错误的模式,给出了我的一些属性。例如它忽略了标有[XmlEnum(Name =“Foo”)]的枚举值的自定义名称
I believe this is the correct way (given your using XmlSerializer
) and is quite simple too:
我相信这是正确的方法(鉴于你使用XmlSerializer),也很简单:
var schemas = new XmlSchemas();
var exporter = new XmlSchemaExporter(schemas);
var mapping = new XmlReflectionImporter().ImportTypeMapping(typeof(Person));
exporter.ExportTypeMapping(mapping);
var schemaWriter = new StringWriter();
foreach (XmlSchema schema in schemas)
{
schema.Write(schemaWriter);
}
return schemaWriter.ToString();
Code extracted from: http://blogs.msdn.com/b/youssefm/archive/2010/05/13/using-xml-schema-import-and-export-for-xmlserializer.aspx
代码摘自:http://blogs.msdn.com/b/youssefm/archive/2010/05/13/using-xml-schema-import-and-export-for-xmlserializer.aspx
#2
9
So this works, I guess it wasn't as ugly as it seemed:
所以这是有效的,我想它并不像看起来那么难看:
var soapReflectionImporter = new SoapReflectionImporter();
var xmlTypeMapping = soapReflectionImporter.ImportTypeMapping(typeof(Person));
var xmlSchemas = new XmlSchemas();
var xmlSchema = new XmlSchema();
xmlSchemas.Add(xmlSchema);
var xmlSchemaExporter = new XmlSchemaExporter(xmlSchemas);
xmlSchemaExporter.ExportTypeMapping(xmlTypeMapping);
I was still hoping there was a 2 line solution out there, it seems like there should be, thanks for the tip @dtb
我仍然希望那里有一个2线解决方案,似乎应该有,感谢提示@dtb
EDIT Just for kicks, here's the 2 line version (self deprecating humor)
编辑只是为了踢,这里是2行版本(自我贬低幽默)
var typeMapping = new SoapReflectionImporter().ImportTypeMapping(typeof(Person));
new XmlSchemaExporter(new XmlSchemas { new XmlSchema() }).ExportTypeMapping(typeMapping);
#3
6
You can programmatically invoke xsd.exe:
您可以以编程方式调用xsd.exe:
- Add xsd.exe as assembly reference.
- 将xsd.exe添加为程序集引用。
using XsdTool;
- 使用XsdTool;
Xsd.Main(new[] { "myassembly.dll", "/type:MyNamespace.MyClass" });
- Xsd.Main(new [] {“myassembly.dll”,“/ type:MyNamespace.MyClass”});
You can also use Reflector to look at the XsdTool.Xsd.ExportSchemas method. It uses the public XmlReflectionImporter, XmlSchemas, XmlSchema XmlSchemaExporter and XmlTypeMapping classes to create a schema from .NET types.
您还可以使用Reflector查看XsdTool.Xsd.ExportSchemas方法。它使用公共XmlReflectionImporter,XmlSchemas,XmlSchema XmlSchemaExporter和XmlTypeMapping类从.NET类型创建模式。
Essentially it does this:
基本上它是这样做的:
var importer = new XmlReflectionImporter();
var schemas = new XmlSchemas();
var exporter = new XmlSchemaExporter(schemas);
var xmlTypeMapping = importer.ImportTypeMapping(typeof(Person));
exporter.ExportTypeMapping(xmlTypeMapping);
schemas.Compile(..., false);
for (var i = 0; i < schemas.Count; i++)
{
var schema = schemas[i];
schema.Write(...);
} ↑
You should be able to customize the output by passing a suitable writer to the XmlSchema.Write method.
您应该能够通过将合适的编写器传递给XmlSchema.Write方法来自定义输出。
#4
1
I believe this is what you're looking for: Writing your own XSD.exe
我相信这就是你要找的:编写自己的XSD.exe
Borrowing code from above:
借用上面的代码:
using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using NUnit.Framework;
namespace XmlSchemaImporterTest
{
[TestFixture]
public class XsdToClassTests
{
// Test for XmlSchemaImporter
[Test]
public void XsdToClassTest()
{
// identify the path to the xsd
string xsdFileName = "Account.xsd";
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string xsdPath = Path.Combine(path, xsdFileName);
// load the xsd
XmlSchema xsd;
using(FileStream stream = new FileStream(xsdPath, FileMode.Open, FileAccess.Read))
{
xsd = XmlSchema.Read(stream, null);
}
Console.WriteLine("xsd.IsCompiled {0}", xsd.IsCompiled);
XmlSchemas xsds = new XmlSchemas();
xsds.Add(xsd);
xsds.Compile(null, true);
XmlSchemaImporter schemaImporter = new XmlSchemaImporter(xsds);
// create the codedom
CodeNamespace codeNamespace = new CodeNamespace("Generated");
XmlCodeExporter codeExporter = new XmlCodeExporter(codeNamespace);
List maps = new List();
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);
}
RemoveAttributes(codeNamespace);
// Check for invalid characters in identifiers
CodeGenerator.ValidateIdentifiers(codeNamespace);
// output the C# code
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
using(StringWriter writer = new StringWriter())
{
codeProvider.GenerateCodeFromNamespace(codeNamespace, writer, new CodeGeneratorOptions());
Console.WriteLine(writer.GetStringBuilder().ToString());
}
Console.ReadLine();
}
// Remove all the attributes from each type in the CodeNamespace, except
// System.Xml.Serialization.XmlTypeAttribute
private void RemoveAttributes(CodeNamespace codeNamespace)
{
foreach(CodeTypeDeclaration codeType in codeNamespace.Types)
{
CodeAttributeDeclaration xmlTypeAttribute = null;
foreach(CodeAttributeDeclaration codeAttribute in codeType.CustomAttributes)
{
Console.WriteLine(codeAttribute.Name);
if(codeAttribute.Name == "System.Xml.Serialization.XmlTypeAttribute")
{
xmlTypeAttribute = codeAttribute;
}
}
codeType.CustomAttributes.Clear();
if(xmlTypeAttribute != null)
{
codeType.CustomAttributes.Add(xmlTypeAttribute);
}
}
}
}
}
#5
0
The XML Schema Definition tool generates XML schema or common language runtime classes from XDR, XML, and XSD files, or from classes in a runtime assembly.
XML Schema Definition工具从XDR,XML和XSD文件或运行时程序集中的类生成XML模式或公共语言运行时类。
http://msdn.microsoft.com/en-us/library/x6c1kb0s(VS.71).aspx
http://msdn.microsoft.com/en-us/library/x6c1kb0s(VS.71).aspx
#1
13
I found the accepted answer generated an incorrect schema given some of my attributes. e.g. It ignored custom names for enum values marked with [XmlEnum(Name="Foo")]
我发现接受的答案会产生一些错误的模式,给出了我的一些属性。例如它忽略了标有[XmlEnum(Name =“Foo”)]的枚举值的自定义名称
I believe this is the correct way (given your using XmlSerializer
) and is quite simple too:
我相信这是正确的方法(鉴于你使用XmlSerializer),也很简单:
var schemas = new XmlSchemas();
var exporter = new XmlSchemaExporter(schemas);
var mapping = new XmlReflectionImporter().ImportTypeMapping(typeof(Person));
exporter.ExportTypeMapping(mapping);
var schemaWriter = new StringWriter();
foreach (XmlSchema schema in schemas)
{
schema.Write(schemaWriter);
}
return schemaWriter.ToString();
Code extracted from: http://blogs.msdn.com/b/youssefm/archive/2010/05/13/using-xml-schema-import-and-export-for-xmlserializer.aspx
代码摘自:http://blogs.msdn.com/b/youssefm/archive/2010/05/13/using-xml-schema-import-and-export-for-xmlserializer.aspx
#2
9
So this works, I guess it wasn't as ugly as it seemed:
所以这是有效的,我想它并不像看起来那么难看:
var soapReflectionImporter = new SoapReflectionImporter();
var xmlTypeMapping = soapReflectionImporter.ImportTypeMapping(typeof(Person));
var xmlSchemas = new XmlSchemas();
var xmlSchema = new XmlSchema();
xmlSchemas.Add(xmlSchema);
var xmlSchemaExporter = new XmlSchemaExporter(xmlSchemas);
xmlSchemaExporter.ExportTypeMapping(xmlTypeMapping);
I was still hoping there was a 2 line solution out there, it seems like there should be, thanks for the tip @dtb
我仍然希望那里有一个2线解决方案,似乎应该有,感谢提示@dtb
EDIT Just for kicks, here's the 2 line version (self deprecating humor)
编辑只是为了踢,这里是2行版本(自我贬低幽默)
var typeMapping = new SoapReflectionImporter().ImportTypeMapping(typeof(Person));
new XmlSchemaExporter(new XmlSchemas { new XmlSchema() }).ExportTypeMapping(typeMapping);
#3
6
You can programmatically invoke xsd.exe:
您可以以编程方式调用xsd.exe:
- Add xsd.exe as assembly reference.
- 将xsd.exe添加为程序集引用。
using XsdTool;
- 使用XsdTool;
Xsd.Main(new[] { "myassembly.dll", "/type:MyNamespace.MyClass" });
- Xsd.Main(new [] {“myassembly.dll”,“/ type:MyNamespace.MyClass”});
You can also use Reflector to look at the XsdTool.Xsd.ExportSchemas method. It uses the public XmlReflectionImporter, XmlSchemas, XmlSchema XmlSchemaExporter and XmlTypeMapping classes to create a schema from .NET types.
您还可以使用Reflector查看XsdTool.Xsd.ExportSchemas方法。它使用公共XmlReflectionImporter,XmlSchemas,XmlSchema XmlSchemaExporter和XmlTypeMapping类从.NET类型创建模式。
Essentially it does this:
基本上它是这样做的:
var importer = new XmlReflectionImporter();
var schemas = new XmlSchemas();
var exporter = new XmlSchemaExporter(schemas);
var xmlTypeMapping = importer.ImportTypeMapping(typeof(Person));
exporter.ExportTypeMapping(xmlTypeMapping);
schemas.Compile(..., false);
for (var i = 0; i < schemas.Count; i++)
{
var schema = schemas[i];
schema.Write(...);
} ↑
You should be able to customize the output by passing a suitable writer to the XmlSchema.Write method.
您应该能够通过将合适的编写器传递给XmlSchema.Write方法来自定义输出。
#4
1
I believe this is what you're looking for: Writing your own XSD.exe
我相信这就是你要找的:编写自己的XSD.exe
Borrowing code from above:
借用上面的代码:
using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using NUnit.Framework;
namespace XmlSchemaImporterTest
{
[TestFixture]
public class XsdToClassTests
{
// Test for XmlSchemaImporter
[Test]
public void XsdToClassTest()
{
// identify the path to the xsd
string xsdFileName = "Account.xsd";
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string xsdPath = Path.Combine(path, xsdFileName);
// load the xsd
XmlSchema xsd;
using(FileStream stream = new FileStream(xsdPath, FileMode.Open, FileAccess.Read))
{
xsd = XmlSchema.Read(stream, null);
}
Console.WriteLine("xsd.IsCompiled {0}", xsd.IsCompiled);
XmlSchemas xsds = new XmlSchemas();
xsds.Add(xsd);
xsds.Compile(null, true);
XmlSchemaImporter schemaImporter = new XmlSchemaImporter(xsds);
// create the codedom
CodeNamespace codeNamespace = new CodeNamespace("Generated");
XmlCodeExporter codeExporter = new XmlCodeExporter(codeNamespace);
List maps = new List();
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);
}
RemoveAttributes(codeNamespace);
// Check for invalid characters in identifiers
CodeGenerator.ValidateIdentifiers(codeNamespace);
// output the C# code
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
using(StringWriter writer = new StringWriter())
{
codeProvider.GenerateCodeFromNamespace(codeNamespace, writer, new CodeGeneratorOptions());
Console.WriteLine(writer.GetStringBuilder().ToString());
}
Console.ReadLine();
}
// Remove all the attributes from each type in the CodeNamespace, except
// System.Xml.Serialization.XmlTypeAttribute
private void RemoveAttributes(CodeNamespace codeNamespace)
{
foreach(CodeTypeDeclaration codeType in codeNamespace.Types)
{
CodeAttributeDeclaration xmlTypeAttribute = null;
foreach(CodeAttributeDeclaration codeAttribute in codeType.CustomAttributes)
{
Console.WriteLine(codeAttribute.Name);
if(codeAttribute.Name == "System.Xml.Serialization.XmlTypeAttribute")
{
xmlTypeAttribute = codeAttribute;
}
}
codeType.CustomAttributes.Clear();
if(xmlTypeAttribute != null)
{
codeType.CustomAttributes.Add(xmlTypeAttribute);
}
}
}
}
}
#5
0
The XML Schema Definition tool generates XML schema or common language runtime classes from XDR, XML, and XSD files, or from classes in a runtime assembly.
XML Schema Definition工具从XDR,XML和XSD文件或运行时程序集中的类生成XML模式或公共语言运行时类。
http://msdn.microsoft.com/en-us/library/x6c1kb0s(VS.71).aspx
http://msdn.microsoft.com/en-us/library/x6c1kb0s(VS.71).aspx