2010-07-16 88 views
3

我正在编写一个代码生成工具,它将接收从Visual Studio的数据集生成器生成的XSD文件,并为每个表中的每列创建一个自定义类。我已经了解如何实现IVsSingleFileGenerator来执行代码生成以及如何将单个文件生成器转换为multi-file generator。然而,似乎我遇到的最麻烦的一步应该是最简单的一步。我从来没有真正使用XML或XML模式,我不知道什么是正确的方式来遍历XSD文件,并读出列名和类型,所以我可以建立我的代码。如何解析XSD文件

关于如何读取XSD文件的教程的任何建议?此外还有关于如何将每列代表一列的每个xs:element以及从每个元素读取其msprop:Generator_UserColumnName,typemsprop:Generator_ColumnPropNameInTable属性的任何建议。

回答

5

正如btlog所说,XSD应该被解析为XML文件。 C#确实为此提供了功能。

的XPath教程:http://www.w3schools.com/xpath/default.asp
XQuery教程:http://www.w3schools.com/xquery/default.asp 随机
C#XmlDocument教程:http://www.codeproject.com/KB/cpp/myXPath.aspx

在C#,的XPath/XQuery的经由XmlDocument使用。特别是通过像SelectSingleNodeSelectNodes这样的呼叫。

如果您的目标是提取特定的数据块,我建议您使用XmlDocument而不是XmlTextReader。如果你喜欢逐行阅读,XmlTextReader更合适。

更新:对于那些对使用Linq查询XML感兴趣的人,.Net 4.0引入了XDocument作为XmlDocument的替代方案。请参阅XDocument or XmlDocument的讨论。

2

你可以加载它和XmlDocument。 Xsd是有效的Xml,所以如果你熟悉这种类型,它非常简单。改变XmlTextReader。

编辑:

有一个快速搜索有一个System.Xml.Schema.XmlSchema对象,它表示一个模式,这是最有可能更为适用。 http://msdn.microsoft.com/en-us/library/system.xml.schema.xmlschema.aspx有很好的使用这个类的例子。

+0

不幸的是,我对xml不熟悉。 – 2010-07-16 16:22:15

+2

@Scott:掌握如何解析XML(尤其是基本的XPath使用)的基本知识是值得学习的,至少在您能够获得基本查询工作的地方,如果您在前面有参考指南。这不是特别复杂。对于至少将其中一种输出类型使用XML的应用程序来说,相对比较常见(尽管像SOAP这样的东西有VS封装器,所以通常可以忽略XML部分)。 – Brian 2010-07-16 16:40:00

0

下面是如何从生成的XSD文件中获取tableadapters的排序列表的示例。根据数据集是Web应用程序还是Web站点的一部分,XML有所不同。您将需要通读XSD文件以确定您想要阅读的内容。希望这会让你开始。

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 
+0

请注意,这个例子是VB.Net。虽然C#版本可能几乎完全一样。就个人而言,我更喜欢通过XPath查询XML文件,而不是使用诸如“GetElementsByTagName”之类的调用,但对于OP,后者可能花费较少的努力来学习使用。 – Brian 2010-07-16 16:35:17

0

只是让你知道的太多,Visual Studio中包含了一个名为XSD的工具,将已经采取XSD文件并生成类C#或VB.NET:http://msdn.microsoft.com/en-us/library/x6c1kb0s.aspx

+0

不幸的是我不能用它来做我正在做的事情。我不只是试图将XSD转换为模仿XSD文件的代码容器。这是一个非常特殊的类,它看起来不像XSD或MSDataSetGenerator通常生成的那样。 – 2010-07-16 16:40:03

9

你要创建一个XmlSchemaSet,阅读在你的模式中,然后编译它来创建一个信息集。一旦你做到了这一点,你就可以开始通过文件迭代

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... 
        } 
       } 
      } 
     } 
    } 
} 

显然,你会想要把所有的孩子处理的东西,在一个单独的方法和递归调用它,但是这应该告诉你的一般流程。