如何将 XML 反序列化为 list<class>
Posted
技术标签:
【中文标题】如何将 XML 反序列化为 list<class>【英文标题】:How do I deserialize XML into list<class> 【发布时间】:2021-11-12 11:52:57 【问题描述】:鉴于以下 HTTP POST 响应(请求有效):
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://tempuri.org/">
<schema xmlns="http://www.w3.org/2001/XMLSchema">schema</schema>xml</DataSet>
还有这个 XSD(XML Schema Definition,部分):
<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://tempuri.org/">
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="MTM">
<xs:complexType>
<xs:sequence>
<xs:element name="MTMDate" type="xs:dateTime" minOccurs="0" />
<xs:element name=......
....
MTMDate
元素后面有更多“列”元素。
我的代码尝试反序列化以 XML 形式返回的数据:
[XmlRoot("MTM")]
public class MTM
[XmlElement("MTM")]
public List<MTMItem> MTMData get; set;
public class MTMItem
[XmlElement("MTMDate")]
public DateTime MTMDate get; set;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MTM));
MTM mtmData = (MTM)xmlSerializer.Deserialize(response.GetResponseStream());
运行时,在MTM mtmData = ..
这一行出现以下错误:
There is an error in XML document (2,2)
IvalidOperationException: <DataSet xmlns='http://tempuri.org/'> was not expected
我想我弄错了[XmlRoot("MTM")]
部分并且没有正确遵循XSD Schema
以便反序列化为List<MTM>
?
编辑:
data
填充了byte[]
数据,这是我需要反序列化为数据集的 xml 数据吗?
using (var stream = request.GetRequestStream())
stream.Write(data, 0, data.Length);
【问题讨论】:
只是想确认您知道:您发布的“XML”看起来像 XSD(XML 模式定义),而不是实际的“内容”XML。也就是说,它是对 XML 格式的定义,而不是已经序列化为 XML 的实际数据。你真的想反序列化 that 吗?见:en.wikipedia.org/wiki/XML_Schema_(W3C) 嗨@Jonathan,我对 xml 和使用 Web 服务非常陌生。据我了解,我需要使用 XSD 反序列化 XSD 格式的 XML 吗?我只想将 XML 数据放入 List您提供的 XML 内容表示一个 .net 对象,该对象旨在表示称为 DataSet 的数据库响应。您可以编写自己的反序列化类来仅提取您想要的数据,但您最好使用 .net 框架中的内置行为according to the documentation
相关部分是标题为创建 XML Web 服务客户端的部分。因为该服务已经存在:
If you want to have Visual Studio generate the Web service proxy class for you, simply create the client project, and, in the Solution Explorer window, right-click the project, and then select Add > Service Reference. In the Add Service Reference dialog box, select Advanced, and then select Add Web Reference. Select the Web service from the list of available Web services (this may require supplying the address of the Web service endpoint if the Web service isn't available within the current solution or on the current computer). If you create the XML Web service proxy yourself (as described in the previous step), you can import it into your client code and consume the XML Web service methods
【讨论】:
您能否举个例子,使用问题中的信息来说明我将如何自己构建反序列化? 我对您的建议不太满意,VS 2019 在您上面概述的步骤中看起来也有所不同。最好手动进行(使用 xsd 类生成器)。 这是一个公平的观点,这个框架已经很老了——我没有在 VS2019 中尝试过。这是一个“框架挑战”,表示已经有一种方法可以处理这种与您提出的解决方案不同的场景。请参阅对原始问题的评论...【参考方案2】:另一个答案基于我们不想想要生成 Web 服务客户端的假设:
我怀疑您遇到的困难与描述数据集中对象的架构有关,其中为使用此 Web 服务而构建的客户端会知道它需要解压缩 DataSet 对象,然后解释结果。您从中生成类的架构没有说明 DataSet 类,因为它假定旧式 asp.net XML Web 服务客户端已经知道这一点。
所以我认为你需要能够根据它提供的架构来解释 DataSet 的“有效负载”是创建一个XmlReader 并导航到有效负载元素的开头,有效地剥离数据集包装。您希望将 XmlReader 推进到有效负载的根元素,跳过关联的架构,这只是描述而不是数据。所以你会想要这样的东西:
using (var reader = XmlReader.Create(stream))
reader.ReadToDescendant("MTM");
MTM mtmData = (MTM)serializer.Deserialize(reader);
【讨论】:
我正在尝试这种方法并使用TextReader.ReadToEnd()
来查看给出了哪些流数据,我显然得到了整个结果:如果我在using(var reader = XmlReader.Create(stream)
行之前这样做,那么我会得到整个结果:模式+有效负载。如果我检查该 using 语句中的结果,我只会得到有效负载,但前 4 行和一点被跳过......那是在我使用 reader.ReadToDescendant()
之前。知道为什么会发生这种情况,以及如何干净地获取有效载荷吗?尝试在 using 语句中反序列化时出现错误:XmlException: Root element is missing以上是关于如何将 XML 反序列化为 list<class>的主要内容,如果未能解决你的问题,请参考以下文章