2010-09-09 30 views
12

Tôi đang cố gắng tạo lược đồ xs: từ bất kỳ loại .net nào theo cách lập trình. Tôi biết tôi có thể sử dụng sự phản chiếu và tạo ra nó bằng cách lặp lại các đặc tính công cộng, nhưng có cách nào được xây dựng không?Làm cách nào để tạo một lược đồ xml theo chương trình từ một loại?

Ví dụ:

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

mong muốn 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> 
+0

tôi nghi ngờ có một cách để làm điều này trong trường hợp chung. Ngoài ra, '[Serializable]' không được sử dụng bởi XML Serializer. –

+0

@ John không biết điều đó, cảm ơn! –

Trả lời

9

Vì vậy, các công trình này, tôi đoán đó là không phải là xấu xí như nó có vẻ:

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

tôi vẫn hy vọng có được một giải pháp 2 dòng trên mạng, nó có vẻ như có nên được, thanks for the tip @dtb


EDIT Just for KIC ks, đây là phiên bản 2 dòng (tự ti hài hước)

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

Tôi chỉ thấy mình trong một vấn đề tương tự như của bạn. Tôi đã thử sử dụng mã của bạn, thay thế 'new Schema()' bằng một biến 'XmlSchema' đã tồn tại, nhưng nó không hoạt động. Bạn có thể giải thích thêm về cách giải pháp của bạn hoạt động không? – pyon

+0

Có bất kỳ điều gì trong XmlSchema đã tồn tại không? Soap reflection importer là một lớp bên trong được sử dụng bởi .Net Framework cho các dịch vụ web, tôi tin tưởng. Có một số tài liệu msdn trên đó. –

+0

Xin chào, tôi sắp từ chối một [sửa] (http://stackoverflow.com/suggested-edits/266125) vì nó sửa đổi mã của bạn. Bạn có thể muốn kiểm tra nó (và nhận xét liên quan) để xem chúng có hợp lệ không. – Benjol

6

Bạn có thể lập trình gọi xsd.exe:

  1. Thêm xsd.exe như tài liệu tham khảo lắp ráp.
  2. using XsdTool;
  3. Xsd.Main(new[] { "myassembly.dll", "/type:MyNamespace.MyClass" });

Bạn cũng có thể sử dụng Reflector để nhìn vào XsdTool.Xsd.ExportSchemas phương pháp. Nó sử dụng các lớp công khai XmlReflectionImporter, XmlSchemas, XmlSchemaXmlSchemaExporterXmlTypeMapping để tạo lược đồ từ các loại .NET.

Về cơ bản nó thực hiện điều này:

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

Bạn sẽ có thể tùy chỉnh đầu ra bằng cách thông qua một nhà văn phù hợp với phương pháp XmlSchema.Write.

+0

Thật thú vị, tôi không biết bạn có thể làm điều đó. Không thực sự những gì tôi đang tìm kiếm. Lý do để làm điều đó theo lập trình sẽ là để kiểm soát đầu ra. –

+0

Tôi đã thực sự đã làm điều đó. Đó là một cụm, tôi hy vọng ai đó biết cách tốt hơn. –

0

Công cụ Định nghĩa lược đồ XML tạo ra các lược đồ XML hoặc các lớp thời gian chạy ngôn ngữ chung từ các tệp XDR, XML và XSD hoặc từ các lớp trong một assembly thời gian chạy.

http://msdn.microsoft.com/en-us/library/x6c1kb0s(VS.71).aspx

+1

Chạy một .exe không được tính là có lập trình. –

+0

Bạn luôn có thể chạy .exe từ mã của bạn. ;) – JBeurer

1

Tôi tin rằng đây là những gì bạn đang tìm kiếm: Writing your own XSD.exe

đang vay với phần trên:

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

Chắc chắn bây giờ bạn biết rõ hơn là để đăng câu trả lời chỉ có liên kết? –

+1

@JohnSaunders: Tôi đã tranh luận rằng trong vài phút trước khi đăng nó, nhưng tôi không thể tìm ra một bản tóm tắt hữu ích (ngoài việc đăng toàn bộ chương trình ra cho blog). Chỉ có nguy cơ với điều đó là bài đăng này không đồng bộ với bất kỳ cập nhật nào từ đó. Bạn đề xuất món gì? – Mrchief

+0

Xóa nó trước khi nó bị xóa cho bạn sẽ là đề nghị của tôi, trừ khi bạn có thể đưa ra một bản tóm tắt. –

13

Tôi tìm thấy accepted answer đã tạo một lược đồ không chính xác cho một số thuộc tính của tôi. ví dụ.Nó bỏ qua tên tùy chỉnh cho các giá trị enum được đánh dấu bằng [XmlEnum(Name="Foo")]

Tôi tin rằng đây là cách chính xác (cho bạn sử dụng XmlSerializer) và khá đơn giản quá:

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

Mã chiết xuất từ: http://blogs.msdn.com/b/youssefm/archive/2010/05/13/using-xml-schema-import-and-export-for-xmlserializer.aspx

+0

Chúc mừng, cảm ơn bạn đã cập nhật. –

Các vấn đề liên quan