【问题标题】:How to parse a XSD file如何解析 XSD 文件
【发布时间】:2010-07-16 16:15:47
【问题描述】:

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

关于如何读取 XSD 文件的教程有什么建议吗?还有关于如何拉出代表一列的每个xs:element 并从每个元素中读取其msprop:Generator_UserColumnNametypemsprop:Generator_ColumnPropNameInTable 属性的任何建议。

【问题讨论】:

    标签: c# parsing xsd


    【解决方案1】:

    您需要创建一个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...
                        }
                    }
                }
            }
        }
    }
    

    显然,您希望将所有子处理内容放在一个单独的方法中并递归调用它,但这应该向您展示一般流程。

    【讨论】:

      【解决方案2】:

      正如 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 的讨论。

      【讨论】:

        【解决方案3】:

        您可以将其加载到 XmlDocument 中。 Xsd 是有效的 Xml,所以如果您熟悉这种类型,它非常简单。或者 XmlTextReader。

        编辑:

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

        【讨论】:

        • 很遗憾我对 xml 也不熟悉。
        • @Scott:掌握如何解析 XML 的基本知识(尤其是基本的 XPath 使用)是值得学习的,至少在有参考资料的情况下可以使基本查询工作的程度在你面前引导。它不是特别复杂。应用程序使用 XML 作为至少一种输出类型是相对常见的(尽管像 SOAP 这样的东西有 VS 包装器,所以您通常可以忽略 XML 部分)。
        【解决方案4】:

        您也知道,Visual Studio 包含一个名为 XSD 的工具,它已经获取 XSD 文件并为 C# 或 VB.NET 生成类:http://msdn.microsoft.com/en-us/library/x6c1kb0s.aspx

        【讨论】:

        • 不幸的是,我不能用它来做我正在做的事情。我不只是试图将 XSD 转换为模仿 XSD 文件的代码容器。这是一个非常专业的类,看起来与 XSD 或 MSDataSetGenerator 通常生成的完全不同。
        【解决方案5】:

        这是一个示例,说明如何从生成的 XSD 文件中获取 tableadapter 的排序列表。 XML 会有所不同,具体取决于数据集是 Web 应用程序还是网站的一部分。您将需要通读 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
        

        【讨论】:

        • 注意这个例子是VB.Net。尽管 C# 版本可能几乎完全相同。就个人而言,我更喜欢通过 XPath 查询 XML 文件,而不是使用像 GetElementsByTagName 这样的调用,但对于 OP,后者可能会花费更少的精力来学习使用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多