【问题标题】:XML Deserialize to List of Custom objectsXML 反序列化为自定义对象列表
【发布时间】:2018-05-09 09:56:47
【问题描述】:

我正在尝试反序列化来自 webrequest 的 XML 字符串,但我无法将其添加到可以迭代的自定义对象列表中,我刚刚花了 2 个小时来解决这个问题,但我不能弄清楚我做错了什么,这是我第一次尝试类似的事情,所以在这一点上我有点无能为力。

这是我要反序列化的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<school_search>
  <summary>
    <total_schools>5</total_schools>
    <category>private</category>
  </summary>
  <schools>
    <school>
      <school_id>12</school_id>
      <school_name>School of Literature</school_name>
    </school>
    <school>
      <school_id>31</school_id>
      <school_name>School of Sports</school_name>
    </school>
    <school>
      <school_id>38</school_id>
      <school_name>School of Arts</school_name>
    </school> 
    <school>
      <school_id>40</school_id>
      <school_name>School of Science</school_name>
    </school>
    <school>
      <school_id>43</school_id>
      <school_name>School of Business</school_name>
    </school>
  </schools>
</school_search>

这是我创建的用于处理特定 XML 的类:

<XmlRoot(ElementName:="school_search")>
    Public Class xmlSchool_search
        <XmlElement(ElementName:="summary")>
        Public Property Summary() As xmlSummary
            Get
                Return m_Summary
            End Get
            Set
                m_Summary = Value
            End Set
        End Property
        Private m_Summary As xmlSummary
        <XmlElement(ElementName:="schools")>
        Public Property Schools() As xmlSchools
            Get
                Return m_Schools
            End Get
            Set
                m_Schools = Value
            End Set
        End Property
        Private m_Schools As xmlSchools
    End Class

    <XmlRoot(ElementName:="schools")>
    Public Class xmlSchools
        <XmlElement(ElementName:="school")>
        Public Property School() As List(Of xmlSchool)
            Get
                Return m_School
            End Get
            Set
                m_School = Value
            End Set
        End Property
        Private m_School As List(Of xmlSchool)
    End Class

    <XmlRoot(ElementName:="summary")>
    Public Class xmlSummary
        <XmlElement(ElementName:="total_Schools")>
        Public Property Total_schools() As String
            Get
                Return m_Total_schools
            End Get
            Set
                m_Total_schools = Value
            End Set
        End Property
        Private m_Total_schools As String

        <XmlElement(ElementName:="category")>
        Public Property Category() As String
            Get
                Return m_Category
            End Get
            Set
                m_Category = Value
            End Set
        End Property
        Private m_Category As String

    End Class

    <XmlRoot(ElementName:="school")>
    Public Class xmlSchool
        <XmlElement(ElementName:="school_id")>
        Public Property School_id() As String
            Get
                Return m_School_id
            End Get
            Set
                m_School_id = Value
            End Set
        End Property
        Private m_School_id As String

        <XmlElement(ElementName:="school_name")>
        Public Property School_name() As String
            Get
                Return m_School_name
            End Get
            Set
                m_School_name = Value
            End Set
        End Property
        Private m_School_name As String

    End Class

这是将 xml 反序列化为我的自定义类的相关代码:

   request = DirectCast(WebRequest.Create(address), HttpWebRequest)
   response = DirectCast(request.GetResponse(), HttpWebResponse)

   Dim schoolsList As List(Of xmlSchool)
   Using reader As New StreamReader(response.GetResponseStream())
         Dim deserializer As New XmlSerializer(GetType(List(Of xmlSchool)), New XmlRootAttribute("schools"))
         schoolsList = DirectCast(deserializer.Deserialize(reader), List(Of xmlSchool))
   End Using

最后这是我用来迭代它的:

 For Each school As xmlSchool In schoolsList
    HttpContext.Current.Response.Write(school.School_id)
    HttpContext.Current.Response.Write("<br/>")
 Next

问题: 我总是遇到以下异常:

System.InvalidOperationException: There is an error in XML document (2, 2). ---> System.InvalidOperationException: <school_search xmlns=''> was not expected.

我尝试将 XmlRootAttribute 更改为 school_search 并且它不会引发异常,但是 schoolList 是空的,我相信问题出在自定义类中,但我看不出问题出在哪里。

提前感谢大家花时间研究这个问题。

【问题讨论】:

  • 发布任何包含 XML 的内容时,请小心并确保所有 XML 都是代码格式(反引号或缩进 4 个空格的块)。如果您不这样做,您的标签将被静默丢弃并且不会出现在呈现的问题中。我修复了异常消息。
  • 我很抱歉 Jim,感谢您的编辑!
  • 学习过程的所有部分,不幸的是,SO markdown 在文本中对&lt; 的作用并不是很明显。作为一项规则,如果您使用 XML 发布任何内容,请务必查看预览以确保它符合您的预期。顺便说一句,写得很好的问题。我会投票,但我今天没有票了。

标签: xml vb.net serialization deserialization


【解决方案1】:

我喜欢用 xml linq 解析简单的 xml

Imports System.Xml
Imports System.Xml.Linq
Module Module1
    Const FILENAME As String = "c:\temp\test.xml"
    Sub Main()

        Dim doc As XDocument = XDocument.Load(FILENAME)

        Dim search As Search = doc.Descendants("school_search").Select(Function(x) New Search() With { _
                                                                           .total_schools = x.Descendants("total_schools").FirstOrDefault(), _
                                                                           .category = x.Descendants("category").FirstOrDefault(), _
                                                                           .schools = x.Descendants("school").Select(Function(y) New School With { _
                                                                                                                         .name = y.Element("school_name"), _
                                                                                                                         .id = y.Element("school_id") _
                                                                                                                                         }).ToList()
                                                                       }).FirstOrDefault()
    End Sub

End Module
Public Class Search
    Public total_schools As Integer
    Public category As String
    Public schools As List(Of School)
End Class
Public Class School
    Public name As String
    Public id As Integer
End Class

【讨论】:

  • 感谢您的回答,在我看来这是一个非常干净的解决方案。我接受上一个答案作为正确答案而不是您的解决方案的原因是因为我不习惯 LINQ 但下次我必须通过 .NET 时我一定会仔细研究它,所以谢谢你,我真的很感激。
  • 通常 xml 文件具有不需要的额外级别。序列化你必须让类匹配 xml 文件。通过手动解析,您通常可以像我消除摘要一样消除层。
【解决方案2】:

你不需要xmlSchools类,你可以在xmlSchool_search类中引入学校集合作为List&lt;of xmlSchool&gt;类型的属性。
然后使用XmlArray 属性告诉序列化器当前属性代表一个集合。

<XmlRoot(ElementName:="school_search")>
Public Class xmlSchool_search
    <XmlElement(ElementName:="summary")>
    Public Property Summary As xmlSummary

    <XmlArray(ElementName:="schools")>
    Public Property Schools As List(Of xmlSchool)
End Class

<XmlType(ElementName:="summary")>
Public Class xmlSummary
    <XmlElement(ElementName:="total_schools")>
    Public Property Total_schools As String

    <XmlElement(ElementName:="category")>
    Public Property Category As String
End Class

<XmlType(ElementName:="school")>
Public Class xmlSchool
    <XmlElement(ElementName:="school_id")>
    Public Property School_id As String

    <XmlElement(ElementName:="school_name")>
    Public Property School_name As String
End Class

反序列化

Dim deserializer As New XmlSerializer(GetType(xmlSchool_search))
Dim search As xmlSchool_search = Nothing

Using reader As New StreamReader(response.GetResponseStream())
     search = DirectCast(deserializer.Deserialize(reader), xmlSchool_search )
End Using

Dim schools As List(Of xmlSchool) = search.Schools

因为您在属性设置器和获取器中没有自定义逻辑,所以您可以使用属性简写

Public Property Name As String

【讨论】:

  • 谢谢,那是正确的!现在一切都说得通了:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-16
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
相关资源
最近更新 更多