简体   繁体   English

XML反序列化:所有属性为null /不应使用EndElement

[英]XML deserialization: All properties null / EndElement not expected

Any help is appreciated with this, I've been struggling. 一直以来,我一直在努力提供任何帮助。

From a HTTP request I receive an XML response. 从HTTP请求中,我收到XML响应。 I have no control over its structure, so I must match that structure with my data contracts. 我无法控制它的结构,因此我必须将该结构与我的数据合同相匹配。 However, no matter what i do, all the properties in the Result object are either null or the default value. 但是,无论我做什么,Result对象中的所有属性都是null或默认值。

XML Structure: XML结构:

<Customnamedroot xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Results="2" Skip="0">
<Object>
    <Something xsi:nil="true" />
    <Anything>2012-06-08T11:21:27</Anything>
    <Booleanthing>true</Booleanthing>
</Object>
<Object>
    <Something>1463387</Something>
    <Anything>2012-06-07T09:16:11.41</Anything>
    <Booleanthing>true</Booleanthing>
</Object>
</Customnamedroot>

The call: 电话:

SearchResults objects = response.Content.ReadAsAsync<SearchResults>().Result;

Corresponding Data Contract classes: 相应的数据合同类别:

[CollectionDataContract(Name = "Customnamedroot", ItemName = "Object", Namespace = "")]
public class SearchResults : List<Result>
{
}

//[DataContract(Name = "Object")]
public class Result
{
    [DataMember(Order = 1, Name = "Something", IsRequired = false)]
    public decimal? Something{ get; set; }

    [DataMember(Order = 2, Name = "Anything", IsRequired = true, EmitDefaultValue = false)]
    public DateTime Anything{ get; set; }

    [DataMember(Order = 3, Name = "Booleanthing", IsRequired = true, EmitDefaultValue = false)]
    public bool Booleanthing{ get; set; }
}

Edit: This problem occurs if the DataContract(Name = "Object") is omitted. 编辑:如果省略DataContract(Name =“ Object”),则会出现此问题。 If that DataContractAttribute is added, I get the following error: 如果添加了该DataContractAttribute,则会出现以下错误:

System.Runtime.Serialization.SerializationException: Error in line 1 position 157. 
'EndElement' 'Object' from namespace '' is not expected. 
Expecting element 'Something| Anything'.

What am I doing wrong? 我究竟做错了什么?

Remove ItemName from the CollectionDataContract . CollectionDataContract中删除ItemName Re-add the DataContract for the Result class and add the Namespace property to it with an empty string. 重新为Result类添加DataContract ,并使用空字符串向其添加Namespace属性。 If there is no namespace defined explicitly in the xml structure .Net will assume an empty string as the namespace and you must tie yourself to that. 如果在xml结构中没有显式定义名称空间,则.Net将假定一个空字符串作为名称空间,您必须将自己绑定到该名称空间。

[CollectionDataContract(Name = "Customnamedroot", Namespace = "")]
public class SearchResults : List<Result>
{
}

[DataContract(Name = "Object", Namespace = "")]
public class Result
{
    [DataMember(Order = 1, Name = "Something", IsRequired = false)]
    public decimal? Something{ get; set; }

    [DataMember(Order = 2, Name = "Anything", IsRequired = true, EmitDefaultValue = false)]
    public DateTime Anything{ get; set; }

    [DataMember(Order = 3, Name = "Booleanthing", IsRequired = true, EmitDefaultValue = false)]
    public bool Booleanthing{ get; set; }
}

As a side note; 作为旁注; even though you don't control the generation of the XML you can certainly modify it's structure using Linq to Xml before deserializing it into a concrete class. 即使您不控制XML的生成,也可以肯定地使用Linq to Xml修改XML的结构,然后反序列化为具体的类。 Here's just a sample of a transformation I'm working on at the moment. 这只是我目前正在进行的转换的一个示例。 By transforming the XML you prevent the XML structure from dictating how your concrete classes look and fit together and are free to do OOP the way you like as it should be. 通过转换XML,可以防止XML结构决定具体类的外观和组合方式,并可以按自己喜欢的方式自由进行OOP。

protected string OnTransformXml(string xml)
{
    var doc = XDocument.Parse(xml);
    var root = doc.Descendants("root").FirstOrDefault();
    var allResults = doc.Descendants("Result").ToList();
    foreach (var node in allResults)
    {
        // remove all Result elements from their current location
        node.Remove();
        // rename the Result element to RawResult
        node.Name = "RawResult";
        // create a container for the Result elements to live in
        var rawMembersElement = new XElement("Result");
        // add each Result element to the new container
        rawMembersElement.Add(node);
        // add the new container
        root.Add(rawMembersElement);
    }
    return doc.ToString();
}

Transforms this: 转换此:

<root>
  <Result>
      <a>1</a>
      <b></b>
  </Result>
</root>

to this: 对此:

<root>
  <Result>
    <RawResult>
      <a>1</a>
      <b></b>
    </RawResult>
  </Result>
</root>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM