2010-09-09 82 views
12

我试图以编程方式从任何.net类型生成xs:schema。我知道我可以使用反射并通过遍历公共属性来生成它,但是是否有内置方式?如何以编程方式从类型生成xml模式?

实施例:

[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; } 
} 

所需的输出:

<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> 
+0

我:

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(); 

代码摘自怀疑在一般情况下有办法做到这一点。此外,XML序列化程序不使用'[Serializable]'。 – 2010-09-09 20:38:56

+0

@John不知道,谢谢! – 2010-09-09 21:04:57

回答

9

所以这个作品,我想这是不丑,因为它似乎是:

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); 

我仍然希望有一个2线的解决方案在那里,好像有是应该的,感谢小费@dtb


编辑 只是为了KIC KS,这里的2行版本(自我贬低的幽默)

var typeMapping = new SoapReflectionImporter().ImportTypeMapping(typeof(Person)); 
new XmlSchemaExporter(new XmlSchemas { new XmlSchema() }).ExportTypeMapping(typeMapping); 
+0

我刚刚发现自己遇到类似于你的问题。我尝试过使用你的代码,用已经存在的'XmlSchema'变量替换'新的Schema()',但它不起作用。你能否进一步解释你的解决方案如何工 – pyon 2011-03-08 14:55:01

+0

在现有的XmlSchema中是否有任何东西?我相信,肥皂反射导入器是.Net Framework用于Web服务的内部类。这里有一些msdn文档。 – 2011-03-14 15:25:40

+0

嗨,我刚刚拒绝[编辑](http://stackoverflow.com/suggested-edits/266125),因为它修改你的代码。你可能想检查它(和相关的注释掉),看看它们是否有效。 – Benjol 2012-05-17 20:18:11

6

可以编程方式调用xsd.exe

  1. 添加XSD.EXE作为组件参考。
  2. using XsdTool;
  3. Xsd.Main(new[] { "myassembly.dll", "/type:MyNamespace.MyClass" });

您还可以使用反射来看看XsdTool.Xsd.ExportSchemas方法。它使用公共的XmlReflectionImporter,XmlSchemas,XmlSchemaXmlSchemaExporterXmlTypeMapping类从.NET类型创建一个模式。

本质上它做到这一点:

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(...); 
}     ↑ 

您应该能够通过传递合适的作家到XmlSchema.Write方法来定制输出。

+0

这很有趣,我不知道你能做到这一点。不是我正在寻找的东西。编程的原因是控制输出。 – 2010-09-09 20:56:40

+0

我其实已经做到了。这是一个集群,我希望有人知道更好的方法。 – 2010-09-09 20:58:45

1

我相信这是你要找的内容:从上面Writing your own XSD.exe

借款代码:

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); 
       } 
      } 
     } 
    } 
} 
+1

现在你知道比发布仅链接回答更好吗? – 2014-01-22 03:49:41

+1

@JohnSaunders:在发布之前我辩论了几分钟,但是我找不出一个有用的总结(除了发布整个程序外)。唯一的风险就是这篇文章与任何更新不同步。你有什么建议? – Mrchief 2014-01-22 14:54:46

+0

删除它之前它会被删除你会是我的建议,除非你能拿出一个总结。 – 2014-01-22 15:28:18