【问题标题】:Use XmlReader and Ignore Order of Nodes使用 XmlReader 并忽略节点顺序
【发布时间】:2014-03-09 12:57:07
【问题描述】:

我正在尝试实现“IXmlSerializable”接口并与“ReadXml”实现作斗争。这是我的序列化 xml:

<?xml version="1.0" encoding="utf-16"?>
<MyClass>
  <IntProperty>100</IntProperty>
  <BoolProperty>True</BoolProperty>
  <ArrayProperty>
    <ArrayEntry MyAttr="Bob" />
    <ArrayEntry MyAttr="Alice" />
  </ArrayProperty>
  <StringProperty>Hello World!</StringProperty>
</MyClass>

有一个“小”特殊要求,反序列化必须向后兼容旧的序列化版本可能有不同的元素顺序,缺少元素或有额外的(现在未使用的)元素。我该怎么做?

Public Class MyClass
  Implements IXmlSerializable

    Public Property IntProperty As Integer
    Public Property BoolProperty As Boolean
    Public Property ArrayProperty As ArrayEntry()
    Public Property StringProperty As String

    Public Sub ReadXml(reader As System.Xml.XmlReader) Implements IXmlSerializable.ReadXml
        ' to be done ...
    End Sub

    ' ...

End Class

Public Class ArrayEntry
    Public Property MyAttr As String
End Class

【问题讨论】:

    标签: vb.net serialization xml-serialization xmlreader backwards-compatibility


    【解决方案1】:

    这对我有用。它在节点顺序方面完全灵活。

    Public Sub ReadXml(reader As System.Xml.XmlReader) Implements IXmlSerializable.ReadXml
    
        reader.MoveToContent()
    
        While True
            Select Case reader.Name
                Case "IntProperty"
                    IntProperty = CInt(reader.ReadString())
                Case "BoolProperty"
                    BoolProperty = CBool(reader.ReadString())
                Case "StringProperty"
                    StringProperty = reader.ReadString()
                Case "ArrayProperty"
                    Dim arrayEntries As New List(Of ArrayEntry)
                    If Not reader.IsEmptyElement Then
                        While reader.Read()
                            If reader.Name <> "ArrayEntry" Then Exit While
                            Dim ar As New ArrayEntry
                            ar.MyAttr = reader.GetAttribute("MyAttr")
                            arrayEntries.Add(ar)
                        End While
                    End If
                    ArrayProperty = arrayEntries.ToArray()
            End Select
            If Not reader.Read() Then Exit While
        End While
    
    End Sub
    

    【讨论】:

      【解决方案2】:

      这里有一些用于解析地理编码数据的代码,可以帮助您完成大部分工作。

      在您的案例“ArrayProperty”中,您需要将 Reader.Read 用于嵌套元素。

         URL = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.placefinder%20where%20text%3D%22{0}%22&diagnostics=true"
          URL = String.Format(URL, sLocation)
           Try
              reader = New XmlTextReader(URL)
              'reader.WhitespaceHandling = WhitespaceHandling.None 'Disable whitespace so that you don't have to read over whitespaces
              With Address
                  While (reader.Read())
                      Debug.Print(reader.Name.ToString())
                      Select Case reader.Name.ToString()
                          Case "Result"
                              If reader.HasAttributes Then
                                  For i = 0 To CShort(reader.AttributeCount - 1)
                                      reader.MoveToAttribute(i)
                                      Select Case reader.Name.ToString
                                          Case "precision"
                                              .precision = reader.GetAttribute(reader.Name.ToString)
                                          Case "warning"
                                              .warning = reader.GetAttribute(reader.Name.ToString)
                                              bOK = False
                                      End Select
                                      reader.MoveToElement() ' Move the reader back to the element node.
                                  Next
                              End If
                          Case "ErrorMessage"
                              .warning = reader.ReadString().ToString()
                          Case "quality"
                              .precision = reader.ReadString().ToString()
                          Case "line1"
                              .Street = reader.ReadString().ToString()
                          Case "city"
                              .City = reader.ReadString().ToString()
                          Case "statecode"
                              .State = reader.ReadString().ToString()
                          Case "postal"
                              .Zip = reader.ReadString().ToString()
                          Case "country"
                              .Country = reader.ReadString().ToString()
                          Case "offsetlat"
                              .Latitude = reader.ReadString().ToString()
                          Case "offsetlon"
                              .Longitude = reader.ReadString().ToString()
                      End Select
                  End While
              End With
          Catch ex As Exception
              bOK = False
              Address.warning = ex.Message
          End Try
      

      对于上面的代码,我只是将下面的代码用于“地址”类:

      Private Structure Address_struct
          Public Street As String
          Public City As String
          Public State As String
          Public Zip As String
          Public Country As String
          Public Latitude As String
          Public Longitude As String
          Public precision As String
          Public warning As String
      End Structure
      Dim Address As Address_struct
      

      【讨论】:

      • 谢谢!您能否提供一个如何解析“ArrayProperty”节点的示例,记住它可能出现在“MyClass”节点下的任何位置?
      • 鉴于您正在处理的 XML 结构,我们可能很难使用上面的代码。您可以调用 reader.read 以获取 CASE 中间的下一个元素。我不确定您是否必须按照处理属性的示例中所示退出。
      • 这就是我问的原因:-)
      猜你喜欢
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      • 2020-01-19
      • 1970-01-01
      • 1970-01-01
      • 2015-06-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多