XML 反序列化器对嵌套标签的深入程度不够
XML Deserializer not going deep enough into nested tags
我正在尝试将相当嵌套的 xml 结构反序列化为一个对象。
<engineLimits>
<engineName>BLAH</engineName>
<engineType>BLAH</engineType>
<engineSubtype>BLAH</engineSubtype>
<engineDirectory>blahh</engineDirectory>
<version>1.0</version>
<creationDate>blah</creationDate>
<testBed>blah</testBed>
<limit>
<!-- The title of the graph -->
<title>title</title>
<!-- Axis settings -->
<xAxis label="label" units="units" equation="equation" min="min" max="max" resolution="res"></xAxis>
<yAxis label="label" units="units" equation="equation" min="min" max="max" resolution="res"></yAxis>
<definition name="test">10</definition>
<averageLimit degree="3">
<average color="grey">
<points>
<point x="11" y="21"/>
<point x="12" y="22"/>
<point x="13" y="23"/>
<point x="14" y="24"/>
<point x="15" y="25"/>
</points>
</average>
<upperLimit color="red">
<points>
<point y="12"/>
<point y="13"/>
<point y="14"/>
<point y="15"/>
<point y="16"/>
</points>
</upperLimit>
<lowerLimit color="red">
<points>
<point y="12"/>
<point y="13"/>
<point y="14"/>
<point y="15"/>
<point y="16"/>
</points>
</lowerLimit>
</averageLimit>
</limit>
</engineLimit>
下面是我如何构建基本对象的片段:
<Serializable()> _
<XmlRoot("engineLimits")> _
Public Class EngineLimits
Dim myLimits As List(Of Limits.Limit)
Public Sub New()
myLimits = New List(Of Limits.Limit)
End Sub
<XmlElement("limit")> _
Public Property limits As List(Of Limits.Limit)
Get
Return myLimits
End Get
Set(value As List(Of Limits.Limit))
myLimits = value
End Set
End Property
End Class
极限class:
<XmlRoot("limit")> _
Public Class Limit
Dim myAverageLimit As Components.AverageLimit
Dim myLineLimits As List(Of Components.LineLimit)
Dim myLines As List(Of Components.Line)
Public Sub New()
myLineLimits = New List(Of Components.LineLimit)
myLines = New List(Of Components.Line)
End Sub
<XmlElement("averageLimit")> _
Public Property averageLimit() As Components.AverageLimit
Get
Return myAverageLimit
End Get
Set(value As Components.AverageLimit)
myAverageLimit = value
End Set
End Property
End Class
平均限额class:
<XmlRoot("averageLimit")> _
Public Class AverageLimit
Dim myDegree As Integer
Dim myAverage As Average
Dim myUpperLimit As DerivedLimit
Dim myLowerLimit As DerivedLimit
Public Sub New()
End Sub
<XmlAttribute("degree")> _
Public Property degree() As Integer
Get
Return myDegree
End Get
Set(value As Integer)
myDegree = value
End Set
End Property
<XmlElement("average")> _
Public Property average() As Average
Get
Return myAverage
End Get
Set(value As Average)
myAverage = value
End Set
End Property
最后是平均值 class:
<XmlRoot("average")> _
Public Class Average
Dim myPoints As List(Of LinePoint)
Public Sub New()
myPoints = New List(Of LinePoint)
End Sub
<XmlArray("points")> _
<XmlArrayItem("point")> _
Public WriteOnly Property setPoints() As List(Of LinePoint)
Set(value As List(Of LinePoint))
myPoints = value
End Set
End Property
End Class
我的问题是反序列化在嵌套标签中的作用不够大。当我 运行 程序时,除了点之外,所有内容都正确填写。对于我的生活,在 average
class 中,我无法解析 list(Of linePoints)
!
这里是线点 class:
<XmlRoot("point")> _
Public Class LinePoint
Dim myX As Double
Dim myY As Double
Public Sub New()
End Sub
<XmlAttribute("x")> _
Public Property x() As Double
Get
Return myX
End Get
Set(value As Double)
myX = value
End Set
End Property
<XmlAttribute("y")> _
Public Property y() As Double
Get
Return myY
End Get
Set(value As Double)
myY = value
End Set
End Property
End Class
仅供参考,degree
已正确解析。可以在实际上不是 array
而是 list
的 属性 上定义 <XmlArray>
吗?
编辑
这是我的反序列化代码:
Try
' Create a new file stream for reading the XML file
Using fs = New StreamReader("C:\Users\u3201656\Desktop\test.xml")
' Construct a XmlSerializer and use it
' to serialize the data from the stream.
Dim SerializerObj = New XmlSerializer(GetType(EngineLimits))
Try
' Deserialize the hashtable from the file
engineLimits = DirectCast(SerializerObj.Deserialize(fs), EngineLimits)
Catch ex As Exception
Console.WriteLine(String.Format("Failed to serialize. Reason: {0}", ex.Message))
End Try
End Using ' put a break point here and mouse-over engineLimits….
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
一个可序列化的 属性 应该总是有一个 public getter 和 setter。您的积分 属性 缺少 getter:
<XmlArray("points")> _
<XmlArrayItem("point")> _
Public Property setPoints() As List(Of LinePoint)
Set(value As List(Of LinePoint))
myPoints = value
End Set
Get
Return myPoints
End Get
End Property
使用您上面的代码进行测试并获得列表中 xml 中的所有点数。
另外,如果你有 vs 2015,你可以大大简化你的 类。见下文。 (命名空间已被删除,因为我没有声明)
<Serializable()> _
<XmlRoot("engineLimits")>
Public Class EngineLimits
<XmlElement("limit")>
Public Property Limits As List(Of Limit) = New List(Of Limit)()
End Class
<XmlRoot("limit")>
Public Class Limit
<XmlElement("averageLimit")>
Public Property AverageLimit As AverageLimit
End Class
<XmlRoot("averageLimit")>
Public Class AverageLimit
<XmlAttribute("degree")>
Public Property Degree As Integer
<XmlElement("average")>
Public Property Average As Average
End Class
<XmlRoot("average")>
Public Class Average
<XmlArray("points")> _
<XmlArrayItem("point")>
Public Property SetPoints As List(Of LinePoint) = New List(Of LinePoint)
End Class
<XmlRoot("point")>
Public Class LinePoint
<XmlAttribute("x")>
Public Property X As Double
<XmlAttribute("y")>
Public Property Y As Double
End Class
我正在尝试将相当嵌套的 xml 结构反序列化为一个对象。
<engineLimits>
<engineName>BLAH</engineName>
<engineType>BLAH</engineType>
<engineSubtype>BLAH</engineSubtype>
<engineDirectory>blahh</engineDirectory>
<version>1.0</version>
<creationDate>blah</creationDate>
<testBed>blah</testBed>
<limit>
<!-- The title of the graph -->
<title>title</title>
<!-- Axis settings -->
<xAxis label="label" units="units" equation="equation" min="min" max="max" resolution="res"></xAxis>
<yAxis label="label" units="units" equation="equation" min="min" max="max" resolution="res"></yAxis>
<definition name="test">10</definition>
<averageLimit degree="3">
<average color="grey">
<points>
<point x="11" y="21"/>
<point x="12" y="22"/>
<point x="13" y="23"/>
<point x="14" y="24"/>
<point x="15" y="25"/>
</points>
</average>
<upperLimit color="red">
<points>
<point y="12"/>
<point y="13"/>
<point y="14"/>
<point y="15"/>
<point y="16"/>
</points>
</upperLimit>
<lowerLimit color="red">
<points>
<point y="12"/>
<point y="13"/>
<point y="14"/>
<point y="15"/>
<point y="16"/>
</points>
</lowerLimit>
</averageLimit>
</limit>
</engineLimit>
下面是我如何构建基本对象的片段:
<Serializable()> _
<XmlRoot("engineLimits")> _
Public Class EngineLimits
Dim myLimits As List(Of Limits.Limit)
Public Sub New()
myLimits = New List(Of Limits.Limit)
End Sub
<XmlElement("limit")> _
Public Property limits As List(Of Limits.Limit)
Get
Return myLimits
End Get
Set(value As List(Of Limits.Limit))
myLimits = value
End Set
End Property
End Class
极限class:
<XmlRoot("limit")> _
Public Class Limit
Dim myAverageLimit As Components.AverageLimit
Dim myLineLimits As List(Of Components.LineLimit)
Dim myLines As List(Of Components.Line)
Public Sub New()
myLineLimits = New List(Of Components.LineLimit)
myLines = New List(Of Components.Line)
End Sub
<XmlElement("averageLimit")> _
Public Property averageLimit() As Components.AverageLimit
Get
Return myAverageLimit
End Get
Set(value As Components.AverageLimit)
myAverageLimit = value
End Set
End Property
End Class
平均限额class:
<XmlRoot("averageLimit")> _
Public Class AverageLimit
Dim myDegree As Integer
Dim myAverage As Average
Dim myUpperLimit As DerivedLimit
Dim myLowerLimit As DerivedLimit
Public Sub New()
End Sub
<XmlAttribute("degree")> _
Public Property degree() As Integer
Get
Return myDegree
End Get
Set(value As Integer)
myDegree = value
End Set
End Property
<XmlElement("average")> _
Public Property average() As Average
Get
Return myAverage
End Get
Set(value As Average)
myAverage = value
End Set
End Property
最后是平均值 class:
<XmlRoot("average")> _
Public Class Average
Dim myPoints As List(Of LinePoint)
Public Sub New()
myPoints = New List(Of LinePoint)
End Sub
<XmlArray("points")> _
<XmlArrayItem("point")> _
Public WriteOnly Property setPoints() As List(Of LinePoint)
Set(value As List(Of LinePoint))
myPoints = value
End Set
End Property
End Class
我的问题是反序列化在嵌套标签中的作用不够大。当我 运行 程序时,除了点之外,所有内容都正确填写。对于我的生活,在 average
class 中,我无法解析 list(Of linePoints)
!
这里是线点 class:
<XmlRoot("point")> _
Public Class LinePoint
Dim myX As Double
Dim myY As Double
Public Sub New()
End Sub
<XmlAttribute("x")> _
Public Property x() As Double
Get
Return myX
End Get
Set(value As Double)
myX = value
End Set
End Property
<XmlAttribute("y")> _
Public Property y() As Double
Get
Return myY
End Get
Set(value As Double)
myY = value
End Set
End Property
End Class
仅供参考,degree
已正确解析。可以在实际上不是 array
而是 list
的 属性 上定义 <XmlArray>
吗?
编辑
这是我的反序列化代码:
Try
' Create a new file stream for reading the XML file
Using fs = New StreamReader("C:\Users\u3201656\Desktop\test.xml")
' Construct a XmlSerializer and use it
' to serialize the data from the stream.
Dim SerializerObj = New XmlSerializer(GetType(EngineLimits))
Try
' Deserialize the hashtable from the file
engineLimits = DirectCast(SerializerObj.Deserialize(fs), EngineLimits)
Catch ex As Exception
Console.WriteLine(String.Format("Failed to serialize. Reason: {0}", ex.Message))
End Try
End Using ' put a break point here and mouse-over engineLimits….
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
一个可序列化的 属性 应该总是有一个 public getter 和 setter。您的积分 属性 缺少 getter:
<XmlArray("points")> _
<XmlArrayItem("point")> _
Public Property setPoints() As List(Of LinePoint)
Set(value As List(Of LinePoint))
myPoints = value
End Set
Get
Return myPoints
End Get
End Property
使用您上面的代码进行测试并获得列表中 xml 中的所有点数。
另外,如果你有 vs 2015,你可以大大简化你的 类。见下文。 (命名空间已被删除,因为我没有声明)
<Serializable()> _
<XmlRoot("engineLimits")>
Public Class EngineLimits
<XmlElement("limit")>
Public Property Limits As List(Of Limit) = New List(Of Limit)()
End Class
<XmlRoot("limit")>
Public Class Limit
<XmlElement("averageLimit")>
Public Property AverageLimit As AverageLimit
End Class
<XmlRoot("averageLimit")>
Public Class AverageLimit
<XmlAttribute("degree")>
Public Property Degree As Integer
<XmlElement("average")>
Public Property Average As Average
End Class
<XmlRoot("average")>
Public Class Average
<XmlArray("points")> _
<XmlArrayItem("point")>
Public Property SetPoints As List(Of LinePoint) = New List(Of LinePoint)
End Class
<XmlRoot("point")>
Public Class LinePoint
<XmlAttribute("x")>
Public Property X As Double
<XmlAttribute("y")>
Public Property Y As Double
End Class