tags:

views:

83

answers:

5

I am writing a code generation tool that will take in a XSD file generated from Visual Studio's Data Set Generator and create a custom class for each column in each table. I already understand how to implement a IVsSingleFileGenerator to do the code generation and how to turn that single file generator in to a multi-file generator. However it seems the step I am having the most trouble with is the one that should be the most simple. I have never really worked with XML or XML-Schema before and I have no clue what is the correct way to iterate through a XSD file and read out the column names and types so I can build my code.

Any recommendation on a tutorial on how to read a XSD file? Also any recommendations on how to pull each xs:element that represents a column out and read its msprop:Generator_UserColumnName, type, and msprop:Generator_ColumnPropNameInTable properties from each element.

+2  A: 

You could just load it into and XmlDocument. Xsd is valid Xml, so if you are familiar with this type it is pretty simple. Alteratively XmlTextReader.

EDIT:

Having a quick search there is a System.Xml.Schema.XmlSchema object that represents a schema, which is most likely more applicable. http://msdn.microsoft.com/en-us/library/system.xml.schema.xmlschema.aspx has a good example of using this class.

btlog
Unfortunately I am not familiar at all with xml either.
Scott Chamberlain
@Scott: Having a basic knowledge of how to parse XML (particularly basic XPath use) is something worth learning, at least to the point where you are able to get basic queries working if you have a reference guide in front of you. It's not particularly complicated. It is relatively common for applications to use XML as at least one of their output types (though stuff like SOAP has VS wrappers, so you can often ignore the XML part).
Brian
A: 

Here is an example of how to get a sorted list of the tableadapters from a generated XSD file. The XML is different depending on if the dataset is part of a web application or a web site. You will need to read through the XSD file to determine exactly what you want to read. Hopefully this will get you started.

Dim XMLDoc As New System.Xml.XmlDocument

XMLDoc.Load("MyDataset.xsd")
Dim oSortedTableAdapters As New Collections.Generic.SortedDictionary(Of String, Xml.XmlElement)

Const WebApplication As Boolean = False

Dim TableAdapters = XMLDoc.GetElementsByTagName("TableAdapter")
For Each TableAdapter As Xml.XmlElement In TableAdapters
    If WebApplication Then
        'pre-compiled way'
        oSortedTableAdapters.Add(TableAdapter.Attributes("GeneratorDataComponentClassName").Value, TableAdapter)
    Else
        'dynamic compiled way'
        oSortedTableAdapters.Add(TableAdapter.Attributes("Name").Value, TableAdapter)
    End If
Next
Carter
Note that this example is VB.Net. Though a C# version wouuld probably be almost exactly the same. Personally, I prefer querying XML files via XPath rather than using calls like `GetElementsByTagName`, but for the OP the latter may take less effort to learn to use.
Brian
+2  A: 

As btlog says, XSDs should be parsed as XML files. C# does provide functionality for this.

XPath Tutorial: http://www.w3schools.com/xpath/default.asp
XQuery Tutorial: http://www.w3schools.com/xquery/default.asp
Random C# XmlDocument tutorial: http://www.codeproject.com/KB/cpp/myXPath.aspx

In C#, XPath/XQuery are used via XmlDocument . In particular, through calls like SelectSingleNode and SelectNodes.

I recommend XmlDocument over XmlTextReader if your goal is to pull out specific chunks of data. If you prefer to read it line by line, XmlTextReader is more appropriate.

Brian
A: 

Just so you know too, Visual Studio includes a tool called XSD that will already take an XSD file and generate classes for either C# or VB.NET: http://msdn.microsoft.com/en-us/library/x6c1kb0s.aspx

icemanind
Unfortunately I can not use that for what I am doing. I am not just trying to translate the XSD to a code container that mimics the XSD file. This is going to a very specialized class that looks nothing like what XSD or MSDataSetGenerator usually generates.
Scott Chamberlain
A: 

You'll want to create an XmlSchemaSet, read in your schema and then compile it to create an infoset. Once you've done that, you can start iterating through the document

XmlSchemaElement root = _schema.Items[0] as XmlSchemaElement;
XmlSchemaSequence children = ((XmlSchemaComplexType)root.ElementSchemaType).ContentTypeParticle as XmlSchemaSequence;
foreach(XmlSchemaObject child in children.Items.OfType<XmlSchemaElement>()) {
    XmlSchemaComplexType type = child.ElementSchemaType as XmlSchemaComplexType;
    if(type == null) {
        // It's a simple type, no sub-elements.
    } else {
        if(type.Attributes.Count > 0) {
            // Handle declared attributes -- use type.AttributeUsers for inherited ones
        }
        XmlSchemaSequence grandchildren = type.ContentTypeParticle as XmlSchemaSequence;
        if(grandchildren != null) {
            foreach(XmlSchemaObject xso in grandchildren.Items) {
                if(xso.GetType().Equals(typeof(XmlSchemaElement))) {
                    // Do something with an element.
                } else if(xso.GetType().Equals(typeof(XmlSchemaSequence))) {
                    // Iterate across the sequence.
                } else if(xso.GetType().Equals(typeof(XmlSchemaAny))) {
                    // Good luck with this one!
                } else if(xso.GetType().Equals(typeof(XmlSchemaChoice))) {
                    foreach(XmlSchemaObject o in ((XmlSchemaChoice)xso).Items) {
                        // Rinse, repeat...
                    }
                }
            }
        }
    }
}

Obviously you'll want to put all the child handling stuff in a separate method and call it recursively, but this should show you the general flow.

TMN