【问题标题】:Deserialize XML to object array with different name to XML element将 XML 反序列化为与 XML 元素具有不同名称的对象数组
【发布时间】:2014-10-25 11:51:51
【问题描述】:

我有一个这样的 XML 结构:

<QueryResult>
    <Submission>
        <Sections>
            <Section>
                <!--Section Data-->
            </Section>
        </Sections>
    </Submission>
</QueryResult>

我正在尝试反序列化 - 我永远不必序列化 - 这是一个 Submission 对象,例如:

public partial class Submission : CanvasModel
{
    private DateTime _date;
    private DateTime _deviceDate;
    private List<Section> _sections = new List<Section>();

    [XmlIgnore]
    public ICollection<Section> Sections
    {
        get
        {
            return _sections;
        }
        set
        {
            _sections = value.ToList();
        }
    }

    //[XmlArrayItem("Section", IsNullable = false)]
    [XmlArrayItem(typeof(Section), ElementName = "Sections", IsNullable = false)]
    public Section[] SectionsArray
    {
        get
        {
            return _sections.ToArray();
        }
        set
        {
            _sections = new List<Section>(value);
        }
    }
}

然而 XML 元素 Sections 没有反序列化。仅当Section[] 属性与XML 元素Sections 同名时才有效。我正在与XmlArrayItem 属性搏斗,但我输了。在其他地方,当名称不同时,我使用XmlElement 属性来指定元素名称,一切正常。但是,我不允许在同一属性上使用 XmlElementXmlArrayItem

我使用XmlArrayItem 属性将Sections XML 元素反序列化为SectionsArray 属性的正确方法是什么?

顺便说一句,我希望我的 EF 数据模型需要的广泛使用的属性 public ICollection&lt;Section&gt; Sections 具有文档名称 Sections,原因有几个,所以交换这两个名称确实是我最后的手段.我想保留当前的 ​​SectionsArray 属性纯粹用于反序列化。

【问题讨论】:

    标签: c# xml serialization xml-serialization deserialization


    【解决方案1】:

    两种 方法可以通过使用xml 序列化属性来解决这个问题。

    首先是AncientSyntax 的回答,我同意,唯一的修改是您必须为数组明确指定节点名称。

        [XmlRootAttribute( "Submission", Namespace = "", IsNullable = false)]
        public class Submission : CanvasModel { 
            private List<Section> _sections = new List<Section>();
    
        [XmlIgnore]
        public virtual ICollection<Section> Sections
        {
            get { return _sections; }
            set { _sections = value.ToList(); }
        }
    
        [XmlArray(ElementName="Sections")]
        [XmlArrayItem("Section", IsNullable = false)]
        public Section[] SectionsArray
        {
            get { return _sections.ToArray(); }
            set { _sections = value.ToList(); }
        }
        }
    

    不太直接的方法是将数组包装成中间类型 喜欢:

    [SerializableAttribute()]
    [XmlRootAttribute("Sections", Namespace = "", IsNullable = false)]
    public partial class Sections {
        private Section[] sectionField;
        [XmlElementAttribute("Section")]
        public Section[] Section
        {
          get { return this.sectionField; }
          set { this.sectionField = value; }
        }
      }
    

    并使用它代替sections数组:

    private Sections _sectionsArrayWrapper;
    [XmlElement(typeof(Sections), ElementName = "Sections", IsNullable = false)]    
    public Sections SectionsArrayWrapper
    {
          // your job to go from array wrapper to collection
    }
    

    这两种定义都适用:

    [SerializableAttribute()]
    [XmlRootAttribute("Section", Namespace = "", IsNullable = false)]
    public class Section { }
    

    public class CanvasModel { }

    这是使用您提供的 xml 测试的。

    【讨论】:

    • 我们有一个赢家!添加数组元素名称就可以了。
    【解决方案2】:

    ElementName 应该是包含的 xml 元素的名称,在本例中为 Section。

    此外,您似乎应该使用 XmlArrayAttribute 以及 XmlArrayItemAttribute。

    [XmlArray]
    [XmlArrayItem(typeof(Section), ElementName = "Section", IsNullable = false)]
    

    有关示例,请参阅 http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlarrayattribute%28v=vs.110%29.aspx

    【讨论】:

    • 添加XmlArrayAttribute 似乎没有什么区别。如果类名与元素名不同,在所有情况下我仍然得到零个部分。
    猜你喜欢
    • 2015-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-07
    相关资源
    最近更新 更多