在vb.net中解析xml

时间:2013-10-01 21:59:57

标签: xml vb.net linq

我获得了一个XML文件。它形成如下:

      <?xml version="1.0" encoding="utf-8"?>
<dataset  xmlns="http://developer.cognos.com/schemas/xmldata/1/"      xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
    <!--
<dataset
    xmlns="http://developer.cognos.com/schemas/xmldata/1/"
    xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
        xs:schemaLocation="http://developer.cognos.com/schemas/xmldata/1/ xmldata.xsd">
-->
<metadata>
    <item name="Level" type="xs:short" precision="1"/>
    <item name="ID" type="xs:string" length="14"/>
    <item name="Name" type="xs:string" length="52"/>
</metadata>

<data>
    <row>
        <value>2</value>
        <value>101   </value>
        <value>Location 1</value>
    </row>
    <row>
        <value>2</value>
        <value>103   </value>
        <value>Location 2</value>
    </row>
</data>

我无法解析此问题。网上有数百篇文章 - 但它们的格式与传递给我的数据不同。 有人能指出我在Framework 3.5上的VB.NET正确的方向吗? 我习惯于看到更像这样的数据:

    <item name="Future" collected="yes">

编辑: 所以,我试过这个:

Dim reader As XmlTextReader = New XmlTextReader(fileToSave)

Do While (reader.Read())

Select Case reader.NodeType
                    Case XmlNodeType.Element 'Display beginning of element.
                        Console.Write("<" + reader.Name)
                        Console.WriteLine(">")
                    Case XmlNodeType.Text 'Display the text in each element.
                        Console.WriteLine(reader.Value)
                    Case XmlNodeType.EndElement 'Display end of element.
                        Console.Write("</" + reader.Name)
                        Console.WriteLine(">")
                End Select
            Loop

我需要的是能够填充组合框的Row项 - 这只是给我与XML文件相同的东西:

    <dataset>
<metadata>
<item>
<item>
<item>
</metadata>
<data>
<row>
<value>
2
</value>
<value>
101   
</value>
<value>
Location 1
</value>
</row>
<row>
<value>
2
</value>
<value>
103   
</value>
<value>
Location 2
</value>
</row>
</data>
</dataset>

3 个答案:

答案 0 :(得分:1)

我相信下面的答案应该是你喜欢的。我的大多数评论/社论应该解释整个过程。原来你不是stackoverflow上唯一有认知数据集困境的人,哈哈。以下示例在LinqPad中进行了测试,并返回了理想的结果。

Imports System.Data.Common
Imports System.Runtime.Serialization
Imports System.Xml.Xsl
Public Class Test

    'Note: If you don't put the <?xml...?> doctype the XML literals VB.NET gives you will not create an XDocument, but an XElement

    ' This the sample XML document from your question
    Private _xml As XDocument = <?xml version="1.0" encoding="utf-8"?>
    <dataset  xmlns="http://developer.cognos.com/schemas/xmldata/1/"      xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
    <!--
        <dataset
            xmlns="http://developer.cognos.com/schemas/xmldata/1/"
            xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
            xs:schemaLocation="http://developer.cognos.com/schemas/xmldata/1/ xmldata.xsd">
    -->
    <metadata>
        <item name="Level" type="xs:short" precision="1"/>
        <item name="ID" type="xs:string" length="14"/>
        <item name="Name" type="xs:string" length="52"/>
    </metadata>
    <data>
        <row>
            <value>2</value>
            <value>101   </value>
            <value>Location 1</value>
        </row>
        <row>
            <value>2</value>
            <value>103   </value>
            <value>Location 2</value>
        </row>
    </data>
    </dataset>

    ' This is a transform I found http://stackoverflow.com/questions/9465674/converting-a-cognos-xml-schema-file-to-xml-using-javascript-code, you're not the only one having trouble with this
    Private _xmlTransform As XDocument = <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns="http://tempuri.org/" xmlns:cog="http://developer.cognos.com/schemas/xmldata/1/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" indent="yes" />

        <xsl:template match="//comment()" />

        <xsl:template match="/">
            <xsl:apply-templates />
        </xsl:template>

        <xsl:template match="cog:dataset">
            <rows>
                <xsl:apply-templates />
            </rows>
        </xsl:template>

        <xsl:template match="cog:metadata">
            <xsl:apply-templates />
        </xsl:template>

        <xsl:template match="cog:item">
            <xsl:apply-templates />
        </xsl:template>

        <xsl:template match="@name | @type | @length | @precision" />

        <xsl:template match="cog:data">
            <xsl:apply-templates />
        </xsl:template>

        <xsl:template match="cog:row">
            <row>
                <xsl:apply-templates />
            </row>
        </xsl:template>

        <xsl:template match="cog:value">
            <xsl:variable name="currentposition" select="count(./preceding-sibling::cog:value)+1" />
            <xsl:variable name="currentname" select="//cog:metadata/cog:item[$currentposition]/@name" />
            <xsl:element name="{$currentname}">
                <xsl:apply-templates />
            </xsl:element>
        </xsl:template>

        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>

    ' This is the XSLT .NET object that will allow us to translate your dataset into something usable
    private _tranform As XslCompiledTransform = new XslCompiledTransform()

    ' Meat & Potatoes, where the dataset will be set to
    public Property MainDataSet As DataSet

    Sub Main
        ' using XDocument, we can create a reader and then prepare the tranform...
        _tranform.Load(_xmlTransform.CreateReader(), new XsltSettings(true,true), Nothing)

        ' I am using "Using" here because, but you're more than welcome to use .Dispose, I'm a C# dev at heart, I'm just forced to code VB.NET for my day job
        Using _ds = new DataSet()   
            ' The XmlTextWrite constructor allows a StringBuilder; which will keep everything in-memory, per your comments
            Dim _sb As StringBuilder = new StringBuilder()

            ' Create an XmlTextWriter with the StringBuilder as the output-buffer
            Using _xmlWriter = XmlTextWriter.Create(_sb)                    
                ' Commit tranformation of the original dataset xml
                _tranform.Transform(_xml.CreateReader(), _xmlWriter)

                ' Have the interim DataSet read-in the new xml 
                _ds.ReadXml(new StringReader(_sb.ToString()), XmlReadMode.Auto)

                ' ... keeping it clean here... lol
                _xmlWriter.Close()

                ' Set the class property to the rendered dataset. 
                MainDataSet = _ds
            End Using       
        End Using

    End Sub
End Class

答案 1 :(得分:1)

要从VB.Net中的XML中提取数据,您可以简单地使用VB.Net的XML文字(如果您不想打扰XML transformation)。

给出你的xml:

Dim xml As XDocument =  
                <?xml version="1.0" encoding="utf-8"?>
                <dataset  xmlns="http://developer.cognos.com/schemas/xmldata/1/"      xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
                    <metadata>
                        <item name="Level" type="xs:short" precision="1"/>
                        <item name="ID" type="xs:string" length="14"/>
                        <item name="Name" type="xs:string" length="52"/>
                    </metadata>
                    <data>
                        <row>
                            <value>2</value>
                            <value>101   </value>
                            <value>Location 1</value>
                        </row>
                        <row>
                            <value>2</value>
                            <value>103   </value>
                            <value>Location 2</value>
                        </row>
                    </data>
                </dataset>

您可以使用

导入其命名空间
Imports <xmlns="http://developer.cognos.com/schemas/xmldata/1/">

然后只需查询您的数据,如以下示例所示:

For Each element In xml...<value>
    Console.WriteLine(element.Value)
Next

Console.WriteLine("----------")

For Each element In xml...<row>
    For Each v in element.<value>
        Console.WriteLine(v.Value)
    Next
Next

Console.WriteLine("----------")

For Each element In xml...<row>
    Dim s = element.<value>.Select(Function(e) e.Value.Trim())
    Console.WriteLine(String.Join(" - ", s))
Next    

输出:

2
101   
Location 1
2
103   
Location 2
----------
2
101   
Location 1
2
103   
Location 2
----------
2 - 101 - Location 1
2 - 103 - Location 2

答案 2 :(得分:-1)

您可以使用System.IO.File.WriteAllLinesSystem.IO.File.WriteAllText方法,并将扩展名设置为XML