簡體   English   中英

Web 對子元素類型的服務調用的反序列化結果

[英]Deserializing result from Web Service call to a child element type

我已連接到 web 服務並下載我正在嘗試反序列化的 XML。 但是,XML 的頂級元素與我嘗試序列化的子元素類型不同。

<ServiceResponse xmlns="namespace1">
  <ServiceResult xmlns:i="namespace2">
   ...lots of elements
  </ServiceResult>
</ServiceResponse>

我編寫了以下代碼:

public MyData ConvertXmlToMyData(string filepath)
{
     XmlRootAttribute xRoot = new XmlRootAttribute();
     xRoot.ElementName = "ServiceResponse";
     xRoot.Namespace = @"namespace1";
     xRoot.IsNullable = true;

     XmlSerializer reader = new XmlSerializer(typeof(MyData), xRoot);
     StreamReader file = new StreamReader(filepath);

     MyData result = (MyData)reader.Deserialize(file);
     file.Close();
     return result;
}

代碼毫無例外地執行,但所有底層元素都是 null。 我知道這是因為ServiceResponseServiceResult不同,但我不知道如何指定我希望反序列化發生在子元素上,而不是整個 object (沒有其他元素,只有一個子元素類型ServiceResult )。

我見過 state 的唯一解決方案是我應該編輯類型的聲明,但在我的情況下,我是從 web 服務中獲取它們的,所以我不能這樣做。

有誰知道我應該做什么?

編輯:從服務參考中添加了 MyData 注釋的詳細信息

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="MyData", Namespace="namespace2")]
[System.SerializableAttribute()]
public partial class MyData: object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {

編輯2:

將代碼更改為:

public MyData ConvertXmlToMyData(string filepath)
{
    DataContractSerializer reader = new DataContractSerializer(typeof(MyData));

    StreamReader file = new StreamReader(filepath);

    file.BaseStream.Position = 0;

    MyData result = (MyData)reader.ReadObject(file.BaseStream); <- error thrown here

    file.Close();

    return result;
}

現在看到錯誤:

第 1 行錯誤 position 73。從命名空間 'namespace1' 期待元素 'MyData'。遇到名稱為 'ServiceResponse'、命名空間 'namespace1' 的 'Element'。

假設您的 xml 文件如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<ServiceResponse xmlns="namespace1">
  <ServiceResult xmlns:i="namespace2">
    <desc>1</desc>
  </ServiceResult>
</ServiceResponse>

我剛剛在您的示例中添加了xmldesc

然后為了跳過頂層實體,我們需要半解析 xml。 一種方法:

  1. FileStream LoadXDocument
  2. 查找頂級實體
  3. 查找二級實體
//Step #1
var xml = File.OpenRead("sample.xml");
var semiParsedData = XDocument.Load(xml);

//Step #2
const string topNamespace = "namespace1", firstNode = "ServiceResponse";
const StringComparison comparison = StringComparison.InvariantCultureIgnoreCase;

var topLevelEntity = semiParsedData.Descendants().FirstOrDefault(element => 
        string.Equals(element.Name.Namespace.NamespaceName, topNamespace, comparison)
        && string.Equals(element.Name.LocalName, firstNode, comparison));

//Step #3
const string secondNode = "ServiceResult";
var secondLevelEntity = topLevelEntity?.Descendants().FirstOrDefault(element =>
    string.Equals(element.Name.Namespace.NamespaceName, topNamespace, comparison)
    && string.Equals(element.Name.LocalName, secondNode, comparison));

if (secondLevelEntity == null)
    return;

希望有一個名為CreateReader的方法,它在XNode class 上定義。

  • secondLevelEntity是一個XElement實例。
  • XElement繼承自XContainer
  • XContainer繼承自XNode

因此,我們可以在secondLevelEntity上調用CreateReader

using var resultReader = secondLevelEntity.CreateReader();

resultReader是一個XmlReader實例,希望DataContractSerializerReadObject有一個接受XmlReader的重載:

var deserializer = new DataContractSerializer(typeof(MyData));
var myData = (MyData)deserializer.ReadObject(resultReader);
Console.WriteLine(myData.Description);

最后數據 model 應如下所示:

[DataContract(Name = "ServiceResult", Namespace = "namespace1")]
public class MyData
{
    [DataMember(Name = "desc")]
    public string Description { get; set; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM