解析随机XML字符串

时间:2016-01-24 15:32:39

标签: xml vb.net xml-parsing

在我们的SQL Server数据库中,我们在text字段记录中有哪些字符串,但是用随机节点写成xml,即

<Record id="5">  
    <account>
        <OldValue>125025</OldValue>
        <NewValue></NewValue>
    </account>  
    <Amount>
        <OldValue>001995</OldValue>
        <NewValue></NewValue>
    </Amount>  
</Record id>

<Stock>
    <Car>
        <OldValue>035</OldValue>
        <NewValue>038 </NewValue>
    </Car>
</Stock>

我需要在字符串中使这些记录可读,例如:

ID: 5, 
Account Old Value: 125025, 
Account New Value: -
Amount Old Value: 001995, 
Amount New Value: -

我不认为我可以serialize字符串,因为我没有预定义的类来序列化它。我正在创建一个函数来读取我的随机xml节点,但我不确定我是否采用了正确的方法。更重要的是,目前我收到了错误:XMLException: 'id' is an unexpected token.

Public Shared Function XmlCustom(sValue As String)
    Dim output As StringBuilder = New StringBuilder()

    If Not String.IsNullOrEmpty(sValue) Then
        Dim xmlString As String = sValue
        Try
            ' Create an XmlReader
            Using reader As XmlReader = XmlReader.Create(New StringReader(xmlString))
                Dim ws As XmlWriterSettings = New XmlWriterSettings()
                ws.Indent = True
                Using writer As XmlWriter = XmlWriter.Create(output, ws)

                    ' Parse the file and display each of the nodes.
                    While reader.Read()
                        Select Case reader.NodeType
                            Case XmlNodeType.Element
                                writer.WriteStartElement(reader.Name)
                            Case XmlNodeType.Text
                                writer.WriteString(reader.Value)
                            Case XmlNodeType.XmlDeclaration
                            Case XmlNodeType.ProcessingInstruction
                                writer.WriteProcessingInstruction(reader.Name, reader.Value)
                            Case XmlNodeType.Comment
                                 writer.WriteComment(reader.Value)
                            Case XmlNodeType.Attribute
                                 writer.WriteElementString("id", reader.Value)

                            Case XmlNodeType.EndElement
                                 writer.WriteFullEndElement()
                        End Select
                    End While
                End Using
            End Using

        Catch ex As Exception
            MsgBox(output.ToString())
            MessageBox.Show("XmlCustom - " & ex.ToString)
        End Try
    End If

End Function

有任何想法如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

如果没有架构,则无法使用序列化程序 由于大多数报告工具都支持DataTable作为DataSource的类型,因此您可以将数据从Xml字符串收集到DataTable

'Method which read elements and generate columns for DataTable and save values too
'Method recursively read every element and add elements names to Column name
Public Function ReadElement(el As XElement, columnName As StringBuilder) As IList(Of Tuple(Of DataColumn, String))
    Dim temp As New List(Of Tuple(Of DataColumn, String))()
    If el Is Nothing Then Return temp
    columnName.Append(el.Name)
    If el.HasElements = True Then
        For Each child As XElement In el.Elements
            temp.AddRange(ReadElement(child, columnName))
        Next
    Else
        Dim column As New DataColumn(columnName.ToString(), GetType(String))
        Dim value As String = el.Value
        Dim item As New Tuple(Of DataColumn, String)(column, value)
        temp.Add(item)
    End If
    Return temp
End Function

创建DataTable

Dim mainElement as XElement = XElement.Parse(yourXmlStringValue)

Dim data As New DataTable()
data.Columns.Add("Id", GetType(String))

'Generate schema for DataTable
Dim scheemaAndValues As New List(Of Tuple(Of DataColumn, String))()
For Each child As XElement In mainElement.Elements
    Dim columnName As New StringBuilder()
    scheemaAndValues.AddRange(ReadElement(child, columnName))
Next

'Add columns to DataTable
For Each arvo As Tuple(Of DataColumn, String) In scheemaAndValues
   data.Columns.Add(arvo.Item1)
Next

'Add values to the row
Dim dr As DataRow = data.NewRow()
dr.SetField(Of String)("Id", mainElement.Attribute("id").Value)
For Each arvo As Tuple(Of DataColumn, String) In scheemaAndValues
   dr.SetField(arvo.Item1.ColumnName, arvo.Item2)
Next
data.Rows.Add(dr)

答案 1 :(得分:0)

见下面的代码。我使用了XMLReader和XML Linq的组合。使用下面的代码,您可以获取每个元素名称,而无需担心对象的顺序。另一种选择是使用递归,如下面的C#项目:Recursion, parsing xml file with attributes into treeview c#。将C#代码转换为VB.Net非常简单。

Imports System.Xml
Imports System.Xml.Linq
Imports System.IO
Module Module1

    Sub Main()
        Dim xml As String = _
            "<?xml version=""1.0"" encoding=""utf-8""?>" & _
            "<Root>" & _
                "<Child>" & _
                    "<SubNode1></SubNode1>" & _
                    "<SubNode2></SubNode2>" & _
                    "<SubNode3></SubNode3>" & _
                "</Child>" & _
                "<Child>" & _
                    "<SubNode1></SubNode1>" & _
                    "<SubNode2></SubNode2>" & _
                    "<SubNode3></SubNode3>" & _
                "</Child>" & _
                "<Child>" & _
                    "<SubNode1></SubNode1>" & _
                    "<SubNode2></SubNode2>" & _
                    "<SubNode3></SubNode3>" & _
                "</Child>" & _
            "</Root>"

        Dim sReader As New StringReader(xml)
        Dim reader As New XmlTextReader(sReader)

        While Not reader.EOF
            If reader.Name <> "Child" Then
                reader.ReadToFollowing("Child")
            End If
            If Not reader.EOF Then
                Dim child As XElement = XElement.ReadFrom(reader)
                For Each element As XElement In child.Elements()
                    Dim name As String = element.Name.LocalName
                    Console.WriteLine(name)
                Next
            End If

        End While
        Console.ReadLine()
    End Sub

End Module

答案 2 :(得分:-1)

它不能的原因是因为你必须有一个模式来提供描述XML数据结构的解析器。您的SQL记录应该在某处具有模式定义,以便解析器可以在读取数据之前预先加载它。

下面您将找到有关规则XML模式描述符的大量信息。

https://msdn.microsoft.com/en-us/library/ms256129(v=vs.110).aspx