Reputation: 5617
I'm trying to convert an XML doc (invoiceList) into an object. Ideally I'd like to convert it into a collection of objects ("Invoices").
Below is a fragment of the XML. I've also included a fragment off my INVOICE object. And finally my attempt at deserialization. The error message I get is so useless that I don't know where to start.
<?xml version="1.0" encoding="utf-8"?>
<invoiceListResponse>
<invoiceList>
<invoiceListItem>
<invoiceUid>39165890</invoiceUid>
<lastUpdatedUid>AAAAADrKwis=</lastUpdatedUid>
<ccy>JPY</ccy>
<autoPopulateFXRate>false</autoPopulateFXRate>
<fcToBcFxRate>1.0000000000</fcToBcFxRate>
<transactionType>S</transactionType>
<invoiceDate>2013-12-26</invoiceDate>
<utcFirstCreated>2013-12-26T08:12:22</utcFirstCreated>
<utcLastModified>2013-12-26T08:12:22</utcLastModified>
<summary />
<invoiceNumber>W101010101</invoiceNumber>
fragment of Invoice object code
[XmlRoot(ElementName = "invoice")]
public class InvoiceDto : TransactionDto
{
public InvoiceDto()
{
TradingTerms = new TradingTermsDto();
QuickPayment = new QuickPaymentDto();
}
public InvoiceDto(string transactionType, string layout)
{
Layout = layout;
TransactionType = transactionType;
TradingTerms = new TradingTermsDto();
QuickPayment = new QuickPaymentDto();
}
[XmlElement(ElementName = "transactionType")]
public string TransactionType;
[XmlElement(ElementName = "invoiceType")]
public string InvoiceType;
[XmlElement(ElementName = "contactUid")]
public int ContactUid;
[XmlElement(ElementName = "shipToContactUid")]
public int ShipToContactUid;
[XmlElement(ElementName = "externalNotes")]
public string ExternalNotes;
My code:
Dim list As XmlDocument = proxy.Find(queries)
'Deserialize text file to a new object.
Using reader As XmlReader = XmlReader.Create(New StringReader(list.InnerXml))
reader.MoveToContent()
reader.Read()
reader.Read()
theinv = DirectCast(New XmlSerializer(GetType(Dto.InvoiceDto)).Deserialize(reader), Dto.InvoiceDto)
Debug.Write(theinv.InvoiceNumber)
Error is:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Xml.dll
Additional information: There is an error in XML document (1, 74).
Upvotes: 1
Views: 2192
Reputation: 43743
The easiest thing to do is to create a class that matches the entire XML document from its root level down. It doesn't need to contain a property for every node, but it needs to at least contain a property for each element in the path to get from the root element down to the ones that you care about. For instance, the following class will work to load the document in your example:
[XmlRoot("invoiceListResponse")]
public class InvoiceListResponse
{
[XmlArray("invoiceList")]
[XmlArrayItem("invoiceListItem")]
public InvoiceDto[] InvoiceList;
}
Then, you can deserialize into it like this:
XmlSerializer s = new XmlSerializer(typeof(InvoiceListResponse));
using (FileStream f = new FileStream("Test.xml", System.IO.FileMode.Open))
{
InvoiceListResponse response = (InvoiceListResponse)s.Deserialize(f);
}
Edit
Based on your comments, below, it appears that what you need to do is to deserialize into that exact DTO class, without making any modifications to it. If that is the case, and you don't want to create a wrapper class as I demonstrated in my first example, you could always do something like this:
Dim invoices As New List(Of InvoiceDto)()
Dim serializer As New XmlSerializer(GetType(InvoiceDto))
For Each i As XmlNode In doc.SelectNodes("/invoiceListResponse/invoiceList/invoiceListItem")
Using reader As New StringReader("<invoice>" & i.InnerXml & "</invoice>")
invoices.Add(DirectCast(serializer.Deserialize(reader), InvoiceDto))
End Using
Next
Upvotes: 1