简体   繁体   English

在vb.net中解析xml

[英]parse xml in vb.net

I am given an XML file. 我得到一个XML文件。 It is formed like this: 它是这样形成的:

      <?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>

I am having trouble parsing this. 我在解析此文件时遇到了麻烦。 There are hundreds of articles online - but all of them have a different format than the data handed to me. 在线上有数百篇文章-但是所有文章的格式都不同于提交给我的数据。 Can anyone point me in the right direction for VB.NET on Framework 3.5? 谁能为我指出Framework 3.5上VB.NET的正确方向? I am used to seeing data more like this: 我习惯于看到更多这样的数据:

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

EDIT: So, I have tried this: 编辑:所以,我试过了:

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

What I need is the Row items to be able to populate a combobox - this just gives me the same thing as the XML file: 我需要的是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>

I believe the answer below should be to your liking. 我相信下面的答案应该是您的喜好。 Most of my comments/editorials should explain the whole process. 我的大部分评论/社论都应解释整个过程。 Turns out you're not the only person on stackoverflow having cognos dataset woes, lol. 事实证明,您不是唯一有cognos数据集问题的堆栈溢出问题的人,大声笑。 The example below was tested in LinqPad and returned desirable results. 下面的示例在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

To extract data from XML in VB.Net, you could simply use VB.Net's XML literals (if you don't want to bother with XML transformation ). 要从VB.Net中的XML提取数据,您可以简单地使用VB.Net的XML文字(如果您不想打扰XML转换 )。

Given your xml: 给定您的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>

you can import its namespace with 您可以使用导入其名称空间

Imports <xmlns="http://developer.cognos.com/schemas/xmldata/1/">

and then simply query your data like in the following examples: 然后像下面的示例一样简单地查询您的数据:

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    

Output: 输出:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM