【问题标题】:Deserializing XML in C# where a property could be either an attribute or an element在 C# 中反序列化 XML,其中属性可以是属性或元素
【发布时间】:2016-12-14 10:32:13
【问题描述】:

我正在编写一个 C# 库,作为其功能之一,它需要能够从 Web 服务接受以下形式的 XML 并对其进行反序列化。

表格一:

<results>
  <sample>
    <status>status message</status>
    <name>sample name</name>
    <igsn>unique identifier for this sample</igsn>
  </sample>
</results>

表格2:

<results>
  <sample name="sample name">
    <valid code="InvalidSample">no</valid>
    <status>Not Saved</status>
    <error>error message</error> 
  </sample>
</results>

这是我要反序列化到的类:

namespace MyNamespace
{
    [XmlRoot(ElementName = "results")]
    public class SampleSubmissionResponse
    {

        [XmlElement("sample")]
        public List<SampleSubmissionSampleResultRecord> SampleList { get; set; }

       ...
    }


    public class SampleSubmissionSampleResultRecord
    {
     ...

        /* RELEVANT PROPERTY RIGHT HERE */
        [XmlAttribute(Attribute = "name")]
        [XmlElement(ElementName = "name")]
        public string Name { get; set; }

      ...
    }

    public class SampleSubmissionValidRecord
    {
       ...
    }
}

问题在于,在一个 XML 示例中,Sample 元素的 name 属性是一个元素,而在另一个 XML 示例中,它是一个属性。如果我同时使用 XmlAttribute 和 XmlElement 装饰类的属性,则在创建 XmlSerializer 实例时会引发异常。

我已经在谷歌上搜索了很长时间,但找不到任何处理这种情况的文档。我假设但不确定,这是因为在创建 XML 模式时,您不应该为同一元素的属性和子元素使用相同的名称。

那么,我在这里做什么?

一种解决方案可能是为不同类型设置两个完全独立的模型。这可能行得通,但看起来不是很优雅。

另一种选择可能是实现 IXmlSerializable 并编写一些复杂的代码来在反序列化方法中处理这个问题。对于一个简单的问题,这将是一个非常冗长的解决方案。

我希望的第三个选项:以某种方式将 XmlAttribute 和 XmlElement 应用于同一属性,或等效的“非此即彼”属性。

第四个选项:更改 XML 来自的 Web 服务以始终使用一种形式。不幸的是,拥有它的人可能不愿意这样做。

【问题讨论】:

  • 您是否尝试过使用 xmlattribute 和 xmlelement 的 diffrun 属性

标签: c# xml xml-deserialization


【解决方案1】:

只为Name 属性指定一个属性。这将正确解析出第一个 xml 表单。

public class SampleSubmissionSampleResultRecord
{
    [XmlElement(ElementName = "name")]
    public string Name { get; set; }
}

要解析第二个 xml 表单,请将 XmlSerializer 订阅到 UnknownAttribute 事件。

var xs = new XmlSerializer(typeof(SampleSubmissionResponse));
xs.UnknownAttribute += Xs_UnknownAttribute;

在事件处理程序中,我们得到所需的值。

private void Xs_UnknownAttribute(object sender, XmlAttributeEventArgs e)
{
    var record = (SampleSubmissionSampleResultRecord)e.ObjectBeingDeserialized;
    record.Name = e.Attr.Value;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 2016-06-23
    • 1970-01-01
    • 2012-12-24
    • 1970-01-01
    相关资源
    最近更新 更多