1

我得到了一个 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

我需要的是能够填充组合框的行项目 - 这只是给了我与 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>
4

3 回答 3

1

我相信下面的答案应该是你喜欢的。我的大部分评论/社论应该解释整个过程。事实证明,你不是 stackoverflow 上唯一一个遇到 cognos 数据集问题的人,哈哈。下面的示例在 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
于 2013-10-02T04:05:37.047 回答
1

要在 VB.Net 中从 XML 中提取数据,您可以简单地使用 VB.Net 的 XML 文字(如果您不想打扰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>

您可以使用

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
于 2013-10-02T09:24:39.397 回答
-1

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

于 2013-10-01T22:11:09.000 回答