Создать схему из XML-файла, аналогичную Create Schema в VS2010, и преобразовать XSD в класс, аналогичный xsd.exe, в коде

Есть ли способ с помощью командной строки с помощью xsd.exe эмулировать то, что происходит, когда вы нажимаете опцию «Создать схему» на вкладке XML в Visual Studio?

Я пытаюсь автоматизировать процесс создания схем из XML, чтобы создавать классы с помощью XSD.

когда я использую команду xsd file.xml, я получаю сообщение об ошибке: Невозможно добавить столбец с именем «MyXMLElement»: вложенная таблица с таким же именем уже принадлежит этому DataTable. Однако он отлично работает, когда я использую параметр «Создать схему» в VS2010.

<Person xmlns="http://someNamespace/1.0" xmlns:j="http://www.google.com/2.0" xmlns:nc="http://yahoo.com/3.0">   
    <MainElement>
        <j:FirstElement>
            <nc:SecondElement>
                <nc:Value>something.com</nc:Value>
            </nc:SecondElement>
        </j:FirstElement>
        <nc:FirstElement>
            <ThirdElement>          
                <nc:PersonName>
                    <nc:Value>SomeName</nc:Value>
                </nc:PersonName>
            </ThirdElement>
        </nc:FirstElement>
    </MainElement>
</Person>

person Popo    schedule 17.12.2013    source источник


Ответы (2)


Вы можете запустить xsd.exe file.xml, и он должен сгенерировать file.xsd, схему для экземпляра документа.

Я попробовал ваш отредактированный образец и столкнулся с той же ошибкой. Я думал, что этот подход сработал, но, похоже, я ошибался. В качестве альтернативы .NET имеет класс System.Xml.Schema.XmlSchemaInference, который я протестировал, чтобы не выдавать ошибки:

        XmlSchemaInference xs = new XmlSchemaInference();
        XmlSchemaSet schemaSet;

        using (XmlReader xr = XmlReader.Create("file.xml"))
        {
            schemaSet = xs.InferSchema(xr);
        }

        foreach (XmlSchema schema in schemaSet.Schemas())
        {
            Console.WriteLine(schema.TargetNamespace);
            schema.Write(Console.Out);
            Console.WriteLine();
        }

Конечно, вместо того, чтобы писать схемы для тестирования на консоль, вы можете сохранить их в файлы. Есть одна проблема, в моем тесте с вашими файлами в наборе схем создаются три схемы, по одной для каждого целевого пространства имен, а основная делает, например. <xs:import namespace="http://www.google.com/2.0" /> для импорта других, но поскольку файлов нет, schema.Write не выводит местоположение.

Это все, что я могу сейчас предложить. Я понимаю, что это не полное решение, но, возможно, оно поможет вам решить проблему.

person Martin Honnen    schedule 17.12.2013
comment
Когда я использую эту команду, я получаю сообщение об ошибке: не могу добавить столбец с именем «MyXMLElement»: вложенная таблица с таким же именем уже принадлежит этому DataTable. Однако он отлично работает, когда я использую параметр «Создать схему» в VS2010. - person Popo; 18.12.2013
comment
Вы используете команду для .xml файла? Ошибка звучит так, как будто вы запускаете xsd.exe для создания набора данных. - person Martin Honnen; 18.12.2013
comment
@Sanpopo, можете ли вы опубликовать минимальный, но полный .xml документ с этой ошибкой при выполнении xsd.exe file.xml? Я не уверен, в чем проблема, поэтому мне нужно увидеть пример, позволяющий воспроизвести проблему. - person Martin Honnen; 18.12.2013
comment
ошибка возникает из-за наличия двух узлов xml с тем же именем, но с разными пространствами имен. Так что у меня будет <nc:MyXMLElement> и <j:MyXMLElement>. Я добавляю пример к основному вопросу. - person Popo; 18.12.2013
comment
@Sanpopo, я отредактировал ответ, возможно, используя XmlSchemaInference, как это предусмотрено библиотекой классов .NET framework. - person Martin Honnen; 18.12.2013
comment
Спасибо, что некоторым помогает, это позволяет мне получать схемы, у меня все еще есть другие проблемы, когда я пытаюсь скомпилировать в файл класса, но это проблемы с различиями. - person Popo; 19.12.2013

Именно это я и сделал, чтобы создать XSD из файла .xml, а затем преобразовать XSD в класс или классы и сохранить файл класса.

Imports System
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Xml
Imports System.Xml.Schema
Imports System.Xml.Serialization
Imports System.CodeDom
Imports System.CodeDom.Compiler

Public Class XMLToClass
    Implements IXMLToClass

    Public Sub New()
    End Sub

    Public Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType Implements IXMLToClass.GetDataUsingDataContract

        Return composite
    End Function



    Public Sub GenerateClassFromXML(ByVal XMLfileName As String, ByVal OutPutFilePath As String, ByVal CodeNameSpace As String)
        Dim xs As New XmlSchemaInference()
        Dim schemaSet As XmlSchemaSet
        Dim schemas As New XmlSchemas()
        Using xr As XmlReader = XmlReader.Create(XMLfileName)
            xs.TypeInference = XmlSchemaInference.InferenceOption.Relaxed
            xs.Occurrence = XmlSchemaInference.InferenceOption.Relaxed
            schemaSet = xs.InferSchema(xr)
        End Using

        For Each Schema As XmlSchema In schemaSet.Schemas
            schemas.Add(Schema)
        Next
        PersistClass(schemas, OutPutFilePath, CodeNameSpace)

    End Sub

    Public Sub PersistClass(ByVal schemas As XmlSchemas, ByVal OutPutFileName As String, ByVal namesp As String)

        ' Get the namespace for the schema.
        Dim ns As CodeNamespace = XsdGenerator.Processor.Process(schemas, namesp)
        ' Create the appropriate generator for the language.
        Dim provider As CodeDomProvider
        provider = New Microsoft.VisualBasic.VBCodeProvider()
        ' Write the code to the output file.
        Using sw As New StreamWriter(OutPutFileName, False)
            provider.GenerateCodeFromNamespace(ns, sw, New CodeGeneratorOptions())
        End Using

    End Sub
End Class

Namespace XsdGenerator
    Public NotInheritable Class Processor
        Public Shared Function Process(ByVal schemas As XmlSchemas, targetNamespace As String) As CodeNamespace

            ' Create the importer for these schemas.
            Dim importer As New XmlSchemaImporter(schemas)
            ' System.CodeDom namespace for the XmlCodeExporter to put classes in.
            Dim ns As New CodeNamespace(targetNamespace)
            Dim exporter As New XmlCodeExporter(ns)
            ' Iterate schema top-level elements and export code for each.
            For Each xsd As XmlSchema In schemas
                For Each element As XmlSchemaElement In xsd.Elements.Values
                    ' Import the mapping first.
                    Dim mapping As XmlTypeMapping = importer.ImportTypeMapping(element.QualifiedName)
                    ' Export the code finally.
                    exporter.ExportTypeMapping(mapping)
                Next
            Next

            Return ns
        End Function
    End Class
End Namespace
person Popo    schedule 30.01.2014