XML反序列化难题

时间:2015-06-17 10:37:28

标签: c# xml-deserialization

我有一个使用直接代码反序列化XML的难题,它似乎非常忠实地遵循msdn文档,但它没有产生预期的对象成员值:

给出以下类结构

[DataContract(Namespace = "")]
public class AddResult
{
    [DataMember()]
    public string ErrorMessage;
    [DataMember()]
    public bool ResultStatus;
    [DataMember()]
    public string Result;
}

[DataContract(Namespace = "")]
public class AddOrderResult : AddResult
{

    [DataMember()]
    public Order Order;
}

以及以下XML:

<AddOrderResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <ErrorMessage i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService" />
  <Result i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService" />
  <ResultStatus xmlns="http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService">true</ResultStatus>
  <Order>
    <Kto>10025</Kto>
    <LIMSIdentifier>12345</LIMSIdentifier>
    <Matchcode>test order 1</Matchcode>
    <OfficeLineHandle>547864</OfficeLineHandle>
    <OverruleCreditCheck>true</OverruleCreditCheck>
  </Order>
</AddOrderResult

以下代码(其中xmlResponse是一个包含上述XML的XDocument对象)生成一个AddOrderResult对象,当XML中的值明确为&#39;时,ResultStatus属性设置为FALSE:

     AddOrderResult res;
     using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(xmlResponse.ToString())))
    {
        stream.Position = 0;
        XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
        DataContractSerializer ser = new DataContractSerializer(typeof(AddOrderResult),new Type[] {typeof(AddResult)});
        res = (AddOrderResult)ser.ReadObject(reader,true);
        resultStatus = res.ResultStatus; //<-this should be true, but is actually false
    }

这种略有不同的方法具有相同的结果:

            AddOrderResult res;
            using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(xmlResponse.ToString())))
            {
                stream.Position = 0;
                XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
                XmlSerializer ser = new XmlSerializer(typeof(AddOrderResult),new Type[] {typeof(AddResult)});
                res = (AddOrderResult)ser.Deserialize(reader);
                resultStatus = res.ResultStatus; //<-this should be true, but is actually false
            }

在生成的反序列化的AddOrderResult对象中,Order属性(对象本身)具有所有正确的值;它只是xml中未正确反序列化的ErrorMessage,Result和ResultStatus值。

我犯了一个明显的错误,或者这是一个已知的问题?问题是反序列化代码,类定义还是XML?

1 个答案:

答案 0 :(得分:1)

您遇到的问题是命名空间。在XML中,ResultStatus行使用xmlns属性标记了命名空间。因此,您需要在DataContract中使用此命名空间。如果您将AddResult类更改为:

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService")]
public class AddResult
{
    [DataMember()]
    public string ErrorMessage;
    [DataMember()]
    public bool ResultStatus;
    [DataMember()]
    public string Result;
}

你会发现ResultStatus被正确读取。

编辑:

这是一个自包含的示例,显示正在读入系统的值以及所有填充正确的值。这包括对您在问题中遗漏的课程的最佳猜测。

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;

namespace SO_AddOrder
{
    class Program
    {
        const string Xml = @"<AddOrderResult xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">
  <ErrorMessage i:nil=""true"" xmlns=""http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService"" />
  <Result i:nil=""true"" xmlns=""http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService"" />
  <ResultStatus xmlns=""http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService"">true</ResultStatus>
  <Order>
    <Kto>10025</Kto>
    <LIMSIdentifier>12345</LIMSIdentifier>
    <Matchcode>test order 1</Matchcode>
    <OfficeLineHandle>547864</OfficeLineHandle>
    <OverruleCreditCheck>true</OverruleCreditCheck>
  </Order>
</AddOrderResult>";

        static void Main(string[] args)
        {
            AddOrderResult res;
            using (MemoryStream stream = new MemoryStream(Encoding.Default.GetBytes(Xml)))
            {
                stream.Position = 0;
                XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
                DataContractSerializer ser = new DataContractSerializer(typeof(AddOrderResult), new Type[] { typeof(AddResult) });
                res = (AddOrderResult)ser.ReadObject(reader, true);
            }
            Console.WriteLine(res.ResultStatus);
        }
    }



    // Define other methods and classes here
[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService")]
public class AddResult
{
    [DataMember()]
    public string ErrorMessage;
    [DataMember()]
    public bool ResultStatus;
    [DataMember()]
    public string Result;
}

[DataContract(Namespace = "")]
public class AddOrderResult : AddResult
{

    [DataMember()]
    public Order Order;
}

[DataContract(Namespace = "")]
public class Order
{

    [DataMember()] 
    public int Kto;


    [DataMember()]
    public string LIMSIdentifier;

    [DataMember()]
    public string Matchcode;

    [DataMember()]
    public int OfficeLineHandle;

    [DataMember()]
    public bool OverruleCreditCheck;
}
}