[英]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。 我知道這是因為ServiceResponse
與ServiceResult
不同,但我不知道如何指定我希望反序列化發生在子元素上,而不是整個 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>
我剛剛在您的示例中添加了xml
和desc
。
然后為了跳過頂層實體,我們需要半解析 xml。 一種方法:
FileStream
Load
到XDocument
//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
實例,希望DataContractSerializer
的ReadObject
有一個接受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.