VB.Net Xml反序列化为Class
VB.Net Xml Deserialization into a Class
我在尝试将一些 XML 反序列化为我创建的 class 时遇到了一些问题。
我得到的错误是:
There is an error in XML document (1, 2).
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
at CommonLayer.InvuManager.FindDocuments(String policy, String year) in C:\GIT\novus\CommonLayer\InvuManager.vb:line 194
at Novus.NavigationControlRisk.UpdateInvuDocumentsFolderTitle(TreeListNode& documentsFolderNode, String policy, String year) in C:\GIT\novus\Dashboard\src\Dashboard\NavigationControls\NavigationControlRisk.vb:line 3125
at Novus.NavigationControlRisk.PopulateFolders(TreeListNode parentNode, Boolean isAttachingPolicy, Boolean refreshData) in C:\GIT\novus\Dashboard\src\Dashboard\NavigationControls\NavigationControlRisk.vb:line 1280
at Novus.NavigationControlRisk.PopulateNode(Boolean refreshData) in C:\GIT\novus\Dashboard\src\Dashboard\NavigationControls\NavigationControlRisk.vb:line 1158
at Novus.NavigationControlRisk.mainTreeList_MouseClick(Object sender, MouseEventArgs e, Boolean refreshData) in C:\GIT\novus\Dashboard\src\Dashboard\NavigationControls\NavigationControlRisk.vb:line 2340
at Novus.NavigationControlRisk._Lambda$__R25-1(Object a0, MouseEventArgs a1)
at System.Windows.Forms.Control.OnMouseClick(MouseEventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at DevExpress.XtraEditors.Container.EditorContainer.WndProc(Message& m)
at DevExpress.XtraTreeList.TreeList.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at Novus.My.MyApplication.Main(String[] Args) in :line 81
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
这是我创建的 class,此时它没什么特别的,我只是想让它工作:
Imports System.Xml.Serialization
<Serializable, XmlRoot("Document")> _
Public Class Document
<XmlElement("Type")> _
Public Property Type As String
<XmlElement("FileName")> _
Public Property FileName As String
End Class
这是我正在使用的文件中的 XML:
<ArrayOfDocuments>
<Document>
<Type>Debit/Credit note</Type>
<FileName>dbE12901_acc1.doc</FileName>
</Document>
<Document>
<Type>Generic</Type>
<FileName>a3_lmbc_categories.xls</FileName>
</Document>
</ArrayOfDocuments>
最后,这是我使用的代码:
Dim foundDocuments As New List(Of Document)
Dim xmldoc As New XmlDocument
xmldoc.Load(InterfaceFilePath)
Dim allText As String = xmldoc.InnerXml
Using currentStringReader As New StringReader(allText)
Dim xml as New XmlSerializer(GetType(List(Of Document)))
foundDocuments = TryCast(xml.Deserialize(currentStringReader), List(Of Document))
End Using
我这辈子都弄不明白为什么它不能反序列化。我的应用程序中有其他不同 classes 的实例,我已经检查过它们的结构方式相同,所以我不明白为什么它不起作用。
我需要另一双眼睛来检查我做了什么,有人有什么建议吗?
正如 Chris 在评论中提到的,用于 List(Of Document)
的根元素名称需要是 ArrayOfDocument
(单数),因此如果 XML 它不会自动工作包含 ArrayOfDocuments
(复数)作为根元素。
如果您需要反序列化,一个简单的解决方案是创建一个 ArrayOfDocuments
class 并反序列化为它,而不是反序列化为 List(Of Document)
:
Public Class Document
Public Property Type As String
Public Property FileName As String
End Class
Public Class ArrayOfDocuments
<XmlElement>
Public Property Document As Document()
End Class
然后:
Dim xml As New XmlSerializer(GetType(ArrayOfDocuments))
foundDocuments = TryCast(xml.Deserialize(currentStringReader), ArrayOfDocuments)
您可以通过复制 xml 文本然后在 visual studio:
中自动从 xml 生成 class
Edit >> Paste Special >> Paste XML As Classes
我这样做了,它产生了 classes
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", IsNullable:=False)> _
Partial Public Class ArrayOfDocuments
Private documentField() As ArrayOfDocumentsDocument
<System.Xml.Serialization.XmlElementAttribute("Document")> _
Public Property Document() As ArrayOfDocumentsDocument()
Get
Return Me.documentField
End Get
Set(value As ArrayOfDocumentsDocument())
Me.documentField = value
End Set
End Property
End Class
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
Partial Public Class ArrayOfDocumentsDocument
Private typeField As String
Private fileNameField As String
Public Property Type() As String
Get
Return Me.typeField
End Get
Set(value As String)
Me.typeField = value
End Set
End Property
Public Property FileName() As String
Get
Return Me.fileNameField
End Get
Set(value As String)
Me.fileNameField = value
End Set
End Property
End Class
(手动将自动名称 ArrayOfDocumentDocument
更改为 Document
)
这很容易反序列化
Imports System.Xml.Serialization
Imports System.IO
Dim s As New XmlSerializer(GetType(ArrayOfDocuments))
Dim m As ArrayOfDocuments
Using sr As New StreamReader("XMLFile1.xml")
m = s.Deserialize(sr)
End Using
Dim foundDocuments = m.Document.ToList()
感谢 Chris Dunaway,他在上面的一条评论中为我解决了这个问题。
是更改 ArrayOfDocuments => ArrayOfDocument
的简单案例
之后就完美运行了
我在尝试将一些 XML 反序列化为我创建的 class 时遇到了一些问题。
我得到的错误是:
There is an error in XML document (1, 2).
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
at CommonLayer.InvuManager.FindDocuments(String policy, String year) in C:\GIT\novus\CommonLayer\InvuManager.vb:line 194
at Novus.NavigationControlRisk.UpdateInvuDocumentsFolderTitle(TreeListNode& documentsFolderNode, String policy, String year) in C:\GIT\novus\Dashboard\src\Dashboard\NavigationControls\NavigationControlRisk.vb:line 3125
at Novus.NavigationControlRisk.PopulateFolders(TreeListNode parentNode, Boolean isAttachingPolicy, Boolean refreshData) in C:\GIT\novus\Dashboard\src\Dashboard\NavigationControls\NavigationControlRisk.vb:line 1280
at Novus.NavigationControlRisk.PopulateNode(Boolean refreshData) in C:\GIT\novus\Dashboard\src\Dashboard\NavigationControls\NavigationControlRisk.vb:line 1158
at Novus.NavigationControlRisk.mainTreeList_MouseClick(Object sender, MouseEventArgs e, Boolean refreshData) in C:\GIT\novus\Dashboard\src\Dashboard\NavigationControls\NavigationControlRisk.vb:line 2340
at Novus.NavigationControlRisk._Lambda$__R25-1(Object a0, MouseEventArgs a1)
at System.Windows.Forms.Control.OnMouseClick(MouseEventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at DevExpress.XtraEditors.Container.EditorContainer.WndProc(Message& m)
at DevExpress.XtraTreeList.TreeList.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at Novus.My.MyApplication.Main(String[] Args) in :line 81
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
这是我创建的 class,此时它没什么特别的,我只是想让它工作:
Imports System.Xml.Serialization
<Serializable, XmlRoot("Document")> _
Public Class Document
<XmlElement("Type")> _
Public Property Type As String
<XmlElement("FileName")> _
Public Property FileName As String
End Class
这是我正在使用的文件中的 XML:
<ArrayOfDocuments>
<Document>
<Type>Debit/Credit note</Type>
<FileName>dbE12901_acc1.doc</FileName>
</Document>
<Document>
<Type>Generic</Type>
<FileName>a3_lmbc_categories.xls</FileName>
</Document>
</ArrayOfDocuments>
最后,这是我使用的代码:
Dim foundDocuments As New List(Of Document)
Dim xmldoc As New XmlDocument
xmldoc.Load(InterfaceFilePath)
Dim allText As String = xmldoc.InnerXml
Using currentStringReader As New StringReader(allText)
Dim xml as New XmlSerializer(GetType(List(Of Document)))
foundDocuments = TryCast(xml.Deserialize(currentStringReader), List(Of Document))
End Using
我这辈子都弄不明白为什么它不能反序列化。我的应用程序中有其他不同 classes 的实例,我已经检查过它们的结构方式相同,所以我不明白为什么它不起作用。
我需要另一双眼睛来检查我做了什么,有人有什么建议吗?
正如 Chris 在评论中提到的,用于 List(Of Document)
的根元素名称需要是 ArrayOfDocument
(单数),因此如果 XML 它不会自动工作包含 ArrayOfDocuments
(复数)作为根元素。
如果您需要反序列化,一个简单的解决方案是创建一个 ArrayOfDocuments
class 并反序列化为它,而不是反序列化为 List(Of Document)
:
Public Class Document
Public Property Type As String
Public Property FileName As String
End Class
Public Class ArrayOfDocuments
<XmlElement>
Public Property Document As Document()
End Class
然后:
Dim xml As New XmlSerializer(GetType(ArrayOfDocuments))
foundDocuments = TryCast(xml.Deserialize(currentStringReader), ArrayOfDocuments)
您可以通过复制 xml 文本然后在 visual studio:
中自动从 xml 生成 classEdit >> Paste Special >> Paste XML As Classes
我这样做了,它产生了 classes
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", IsNullable:=False)> _
Partial Public Class ArrayOfDocuments
Private documentField() As ArrayOfDocumentsDocument
<System.Xml.Serialization.XmlElementAttribute("Document")> _
Public Property Document() As ArrayOfDocumentsDocument()
Get
Return Me.documentField
End Get
Set(value As ArrayOfDocumentsDocument())
Me.documentField = value
End Set
End Property
End Class
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
Partial Public Class ArrayOfDocumentsDocument
Private typeField As String
Private fileNameField As String
Public Property Type() As String
Get
Return Me.typeField
End Get
Set(value As String)
Me.typeField = value
End Set
End Property
Public Property FileName() As String
Get
Return Me.fileNameField
End Get
Set(value As String)
Me.fileNameField = value
End Set
End Property
End Class
(手动将自动名称 ArrayOfDocumentDocument
更改为 Document
)
这很容易反序列化
Imports System.Xml.Serialization
Imports System.IO
Dim s As New XmlSerializer(GetType(ArrayOfDocuments))
Dim m As ArrayOfDocuments
Using sr As New StreamReader("XMLFile1.xml")
m = s.Deserialize(sr)
End Using
Dim foundDocuments = m.Document.ToList()
感谢 Chris Dunaway,他在上面的一条评论中为我解决了这个问题。
是更改 ArrayOfDocuments => ArrayOfDocument
的简单案例之后就完美运行了