问题
I have a bit of an issue trying to deserialize some XML into a class that I have created.
The error I get is:
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()
Here is the class I created, it's nothing fancy at this point, I'm simply trying to get it to work:
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
And here is the XML from the file I am using:
<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>
Finally, here is the code I am using:
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
I cannot, for the life of me, figure out why it will not deserialize. I have other instances of different classes in my app and I have checked and the way they are structured is the same, so I do not understand why it will not work.
I need another pair of eyes just to check what I have done, does anyone have any suggestions?
回答1:
You can automatically generate the class from xml by copying the xml text then in visual studio:
Edit >> Paste Special >> Paste XML As Classes
I did this and it yielded the 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
(Changed automatic name ArrayOfDocumentDocument
to Document
manually)
This is deserialized easily
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()
回答2:
Shout out to Chris Dunaway who solved it for me in one of the comments above.
Was a simple case of changing ArrayOfDocuments => ArrayOfDocument
After that it worked perfectly
回答3:
As mentioned by Chris in the comments, the root element name used for List(Of Document)
needs to be ArrayOfDocument
(singular), so it won't work automatically if the XML contains ArrayOfDocuments
(plural) as the root element.
If you needed to deserialize that, as is, one simple solution would be to create an ArrayOfDocuments
class and deserialize into that instead of deserializing into 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
And then:
Dim xml As New XmlSerializer(GetType(ArrayOfDocuments))
foundDocuments = TryCast(xml.Deserialize(currentStringReader), ArrayOfDocuments)
来源:https://stackoverflow.com/questions/45168499/vb-net-xml-deserialization-into-a-class