Reputation: 2460
Is there a way to emulate using command line with the xsd.exe what happens when you click the 'Create Schema' option under the XML tab in Visual Studio?
I am trying to automate the process of creating schemas from XML in order to create classes using the XSD.
when I use the xsd file.xml command I get an error: Cannot add a column named 'MyXMLElement': a nested table with the same name already belongs to this DataTable. However, it works fine when I use the Create Schema option in 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>
Upvotes: 1
Views: 1295
Reputation: 2460
This is what I ended up doing to create an XSD from an .xml file and then convert the XSD into a class or classes and save the class file.
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
Upvotes: 0
Reputation: 167716
You can run xsd.exe file.xml
and it should generate file.xsd
, a schema for the instance document.
I tried your edited sample and ran into the same error. I thought that approach worked but it seems I was wrong. As an alternative, .NET has the System.Xml.Schema.XmlSchemaInference
class that I have tested not to throw an error:
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();
}
Of course instead of writing the schemas for testing to the console you could save them to files. There is one problem, in my test with your files three schemas are created in the schema set, one for each target namespace, and the main one does e.g. <xs:import namespace="http://www.google.com/2.0" />
to import the other ones but as there are no files, the schema.Write
does not output any location.
That is all I can currently suggest, I realize it is not a complete solution but perhaps it helps you solve the problem.
Upvotes: 2