2010-09-09 61 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