提问人:jpi76 提问时间:6/19/2023 最后编辑:djvjpi76 更新时间:6/20/2023 访问量:44
从 XML 读取数据的顺序
Order of data read from XML
问:
我必须从 XML 文件中读取数据,顺序很重要
我有以下(简化的)XML数据需要阅读:
<xmltest>
<type1>
<tekst>ABC</tekst>
</type1>
<type2>
<tekst>DEF</tekst>
</type2>
<type1>
<tekst>GHI</tekst>
</type1>
<type2>
<tekst>JKL</tekst>
</type2>
<type3>
<tekst>MNO</tekst>
</type3>
</xmltest>
创建了以下类:
public class xmltest
public property type1 as list(of type1)
public property type2 as list(of type2)
public property type3 as list(of type3)
end class
public class type1
public property tekst as string
end class
public class type2
public property tekst as string
end class
public class type3
public property tekst as string
end class
我使用以下代码来读取 XML:
Public Sub Indlaes
Dim reader As New System.Xml.XmlTextReader("filename.txt")
Dim subreader As System.Xml.XmlReader
Dim xmlSer As System.Xml.Serialization.XmlSerializer
Dim result = New cmltest
Do While (reader.Read())
Select Case reader.NodeType
Case System.Xml.XmlNodeType.Element
subreader = reader.ReadSubtree()
xmlSer = New System.Xml.Serialization.XmlSerializer(result.GetType)
result = xmlSer.Deserialize(subreader)
subreader.Close()
End Select
Loop
reader.Close()
End Sub
在上面的示例中,我最终在 xmltest 中得到了 3 个列表,但无法重新创建我正在考虑使用字典的顺序
,该字典在 3 个列表/字典中使用了 ID,但是我如何设置该 ID?或者有没有其他解决方案?
我真的很想继续使用 Deserialize 函数,因为它也用于其余的 xml 数据
答:
您正在使用混合方法进行反序列化,并且您正在使用 txt 文件(?)基本的反序列化方法可能涉及以下内容
型:
<XmlRoot>
Public Class xmltest
<XmlElement>
Public Property type1 As List(Of type1)
<XmlElement>
Public Property type2 As List(Of type2)
<XmlElement>
Public Property type3 As List(Of type3)
End Class
Public Class type1
<XmlElement>
Public Property tekst As String
End Class
Public Class type2
<XmlElement>
Public Property tekst As String
End Class
Public Class type3
<XmlElement>
Public Property tekst As String
End Class
反序列化代码:
Dim s As New XmlSerializer(GetType(xmltest))
Dim xmlTest As xmltest
Using fs As New FileStream("filename.xml", FileMode.Open)
xmlTest = CType(s.Deserialize(fs), xmltest)
End Using
如您所指出的,这会导致列表乱序
您可以对模型进行修改,以使用相同的类将所有节点反序列化为同一数组type
<XmlRoot>
Public Class xmltest
<XmlElement(ElementName:="type1", Type:=GetType(type1))>
<XmlElement(ElementName:="type2", Type:=GetType(type1))>
<XmlElement(ElementName:="type3", Type:=GetType(type1))>
<XmlChoiceIdentifier("typesElementName")>
Public Property types As type1()
<XmlIgnore>
Public Property typesElementName As types()
End Class
Public Class type1
<XmlElement>
Public Property tekst As String
End Class
<XmlType(IncludeInSchema:=False)>
Public Enum types
type1
type2
type3
End Enum
使用相同的反序列化代码,您现在按顺序获得此数组
元素序列的架构看起来是每个可能的元素名称的选择元素序列。如选择元素绑定支持中所述,实现此目的的一种方法是通过多态类型列表,前提是您在编译时知道所有可能的元素名称,并将属性 <XmlElementAttribute(String, Type)>
应用于每个可能类型的列表。<typeN>
<typeN>
<typeN>
以下类实现此方法:
' The root object with the polymorphic list corresponding to the possible types
<XmlRoot("xmltest")>
Public Class XmlTest
<XmlElement("type1", GetType(Type1)), XmlElement("type2", GetType(Type2)), XmlElement("type3", GetType(Type3))>
Public Property TypeList As List(Of TypeBase) = New List(Of TypeBase) ()
End Class
' The <TypeN> polymorphic type hierarchy
Public Class TypeBase
<XmlElement("tekst")>
Public Property Tekst As String
End Class
<XmlType("type1")>
Public Class Type1
Inherits TypeBase
End Class
<XmlType("type2")>
Public Class Type2
Inherits TypeBase
End Class
<XmlType("type3")>
Public Class Type3
Inherits TypeBase
End Class
对于这些类,可以使用 XmlSerializer
自动反序列化,如下所示,而无需使用以下泛型函数手动读取 :XmlReader
Public Function DeserializeFromFile(Of T)(filename As String) As T
Using stream = File.OpenRead(filename)
Return DirectCast(New XmlSerializer(GetType(T)).Deserialize(stream), T)
End Using
End Function
将所有这些放在一起,要反序列化 XML 文件,按其原始顺序遍历项目,并确定每个项目的类型,可以执行以下操作:<typeN>
Dim test = DeserializeFromFile(Of XmlTest)(filename)
For Each item in test.TypeList
Select Case item.GetType()
Case GetType(Type1)
Console.WriteLine("Type is type 1, value is {0}.", item.Tekst)
Case GetType(Type2)
Console.WriteLine("Type is type 3, value is {0}.", item.Tekst)
Case GetType(Type3)
Console.WriteLine("Type is type 3, value is {0}.", item.Tekst)
Case Else
Throw New Exception(String.Format("Unknown type {0}", item.GetType()))
End Select
Next
笔记:
我重命名了您的类和属性,以遵循 MSFT 建议的 Visual Basic 命名约定,并应用了 XML 序列化程序特性来指定 XML 文件中使用的名称。
有关 C# 中的类似问题,请参阅使用 XmlSerializer 反序列化和序列化 XML 时保持排序和 Xml 反序列化 - 将两个元素合并到单个 List<T> 对象中。
在这里演示小提琴。
上一个:为什么SOAP请求中缺少参数?
下一个:在属性存在时删除节点
评论