如何将XML反序列化为对象?

时间:2013-12-26 13:15:55

标签: c# .net vb.net

我正在尝试将XML doc(invoiceList)转换为对象。理想情况下,我想将其转换为对象集合(“发票”)。

下面是XML的一个片段。我还在INVOICE对象中包含了一个片段。最后我尝试反序列化。我得到的错误消息是如此无用,以至于我不知道从哪里开始。

<?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>

发票对象代码的片段

[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;

我的代码:

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)

错误是:

  

类型'System.InvalidOperationException'的未处理异常   发生在System.Xml.dll

中      

其他信息:XML文档中存在错误(1,74)。

1 个答案:

答案 0 :(得分:1)

最简单的方法是创建一个与其根级别的整个 XML文档相匹配的类。它不需要为每个节点包含一个属性,但它至少需要包含路径中每个元素的属性,以便从根元素到达您关注的元素。例如,以下类将在您的示例中加载文档:

[XmlRoot("invoiceListResponse")]
public class InvoiceListResponse
{

    [XmlArray("invoiceList")]
    [XmlArrayItem("invoiceListItem")]
    public InvoiceDto[] InvoiceList;
}

然后,您可以像这样反序列化:

XmlSerializer s = new XmlSerializer(typeof(InvoiceListResponse));
using (FileStream f = new FileStream("Test.xml", System.IO.FileMode.Open))
{
    InvoiceListResponse response = (InvoiceListResponse)s.Deserialize(f);
}

修改

根据您在下面的评论,您需要做的是反序列化到确切的DTO类,而不对其进行任何修改。如果是这种情况,并且你不想像我在第一个例子中演示的那样创建一个包装类,你总是可以这样做:

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