Как программно сгенерировать XML-схему из типа? - PullRequest
12 голосов
/ 10 сентября 2010

Я пытаюсь сгенерировать схему xs: из любого типа .net программным способом.Я знаю, что мог бы использовать отражение и генерировать его, перебирая открытые свойства, но есть ли встроенный способ?

Пример:

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

Ответы [ 5 ]

13 голосов
/ 12 июня 2014

Я нашел принятый ответ сгенерировал неверную схему, учитывая некоторые из моих атрибутов.Например, он игнорировал пользовательские имена для значений перечисления, помеченных [XmlEnum(Name="Foo")]

Я считаю, что это правильный путь (учитывая ваше использование 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();

Кодизвлечено из: http://blogs.msdn.com/b/youssefm/archive/2010/05/13/using-xml-schema-import-and-export-for-xmlserializer.aspx

9 голосов
/ 10 сентября 2010

Так что это работает, я думаю, что это было не так ужасно, как казалось:

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

Я все еще надеялся, что есть решение с двумя строками, похоже, что должно быть, спасибо заподсказка @ dtb


РЕДАКТИРОВАТЬ Только для ударов, вот двухстрочная версия (самоуничижительный юмор)

var typeMapping = new SoapReflectionImporter().ImportTypeMapping(typeof(Person));
new XmlSchemaExporter(new XmlSchemas { new XmlSchema() }).ExportTypeMapping(typeMapping);
6 голосов
/ 10 сентября 2010

Вы можете программно вызвать xsd.exe :

  1. Добавить xsd.exe в качестве ссылки на сборку.
  2. using XsdTool;
  3. Xsd.Main(new[] { "myassembly.dll", "/type:MyNamespace.MyClass" });

Вы также можете использовать Reflector для просмотра метода XsdTool.Xsd.ExportSchemas . Он использует публичные XmlReflectionImporter , XmlSchemas , XmlSchema XmlSchemaExporter и XmlTypeMapping для создания схемы из .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 .

1 голос
/ 22 января 2014

Я думаю, это то, что вы ищете: Написание собственного 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);
              }
          }
      }
  }
}
0 голосов
/ 10 сентября 2010

Инструмент определения схемы XML генерирует схемы XML или классы среды выполнения на общем языке из файлов XDR, XML и XSD или из классов в сборке времени выполнения.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...