列表的XML序列化

时间:2013-07-18 17:09:46

标签: c# xml xml-serialization xmlserializer ixmlserializable

我的格式为

<?xml version="1.0" ?>
<manifest attr="TEXT" attr="TEXT" attr="TEXT">
<list name="TRIM">
    <feature id="TEXT"/>
    <feature id="TEXT"/>
    <feature id="TEXT"/>
    <feature id="TEXT"/>
    <feature id="TEXT"/>
</list>
<list attr="TEXT">
    <feature id="TEXT"/>
    <feature id="TEXT"/>
</list>
<list attr="TEXT"/>
<list attr="TEXT">
    <feature id="TEXT" attr="TEXT"/>
    <feature id="TEXT" attr="TEXT"/>
</list>
</manifest>

我正在尝试使用C#和IXmlSerializable接口来序列化它。我有三个类,所有类都继承了接口IXmlSerializable,我的意图是XML将由最顶层的类读入,并且它将循环通过将类型“list”的xml传递到子对象序列化器。然后,“list”序列化循环所有“特征”条目。下面是我的代码的缩减版本。

我已经尝试了几种循环方法,但总是以无限循环结束,由于尝试在错误类型中序列化错误的xml位而导致错误,或者在跳过整个列表后到达终点。

我是Xml序列化的新手,这种方法很天真,我愿意接受任何建议。

此XML很可能在将来发生变化(更多属性,元素类型等),因此必须可维护,我不能保证空元素也不会出现。

using UnityEngine;
using System.Collections;
using System.Xml.Serialization;

[XmlRoot("partManifest")]
public class ModelManifest : IEnumerator, IEnumerable, IXmlSerializable {

    [XmlRoot("feature")]
    public class Feature : IXmlSerializable
    {
        string m_id;
        string m_description;

        #region IXmlSerializable implementation
        System.Xml.Schema.XmlSchema System.Xml.Serialization.IXmlSerializable.GetSchema ()    
        {
            throw new System.NotImplementedException ();
        }

        void System.Xml.Serialization.IXmlSerializable.ReadXml (System.Xml.XmlReader reader)
        {       
        m_id = reader.GetAttribute("id");
        }

        void System.Xml.Serialization.IXmlSerializable.WriteXml (System.Xml.XmlWriter writer)
        {
        throw new System.NotImplementedException ();
        }
        #endregion
    }

    [XmlRoot("feature-list")]
    public class FeatureList : IXmlSerializable
    {
        string m_name;

        System.Collections.Generic.List<Feature> m_features = new System.Collections.Generic.List<Feature>();

        #region IXmlSerializable implementation
        public System.Xml.Schema.XmlSchema GetSchema ()
        {
            throw new System.NotImplementedException ();
        }

        public void ReadXml (System.Xml.XmlReader reader)
        {               
            XmlSerializer valueSerializer = new XmlSerializer(typeof(Feature));

            // Will return if no features present
            if(reader.IsEmptyElement)
                return;

            reader.ReadStartElement("feature-list");
            while(true)
            {
                m_features.Add ( (Feature)valueSerializer.Deserialize(reader) );
                i++;
                bool l_isAnotherSibling = reader.ReadToNextSibling("feature");

                if(!l_isAnotherSibling)
                    break;
            }
            Debug.Log (i.ToString() + " Features");
        }

        public void WriteXml (System.Xml.XmlWriter writer)
        {
            throw new System.NotImplementedException ();
        }
        #endregion
    }

    System.Collections.Generic.List<FeatureList> m_featureLists = new System.Collections.Generic.List<FeatureList>();

    #region IXmlSerializable implementation
    public System.Xml.Schema.XmlSchema GetSchema ()
    {
        throw new System.NotImplementedException ();
    }

    public void ReadXml (System.Xml.XmlReader reader)
    {       
        XmlSerializer valueSerializer = new XmlSerializer(typeof(FeatureList));

        if(reader.IsEmptyElement)
            return;

        reader.ReadStartElement("partManifest");

        while (true)
        {               
            m_featureLists.Add ( (FeatureList)valueSerializer.Deserialize(reader) );

            //bool l_isAnotherSibling = reader.ReadToNextSibling("feature-list");

            //if(!l_isAnotherSibling)
            //  break;
            if(reader.NodeType == System.Xml.XmlNodeType.EndElement)
                break;

            if(Input.GetKeyUp(KeyCode.A))
                break;
        }

        reader.ReadEndElement();
    }

    public void WriteXml (System.Xml.XmlWriter writer)
    {
        throw new System.NotImplementedException ();
    }
    #endregion
}

1 个答案:

答案 0 :(得分:2)

除非你有充分的理由需要实现IXmlSerializable,否则我只会在类上使用XmlSerializer和相应的属性。

基于给定的XML示例,这应该这样做。请注意,我必须重命名清单上的两个attr属性,因为具有相同名称的多个属性是无效的。

using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

[Serializable]
[XmlRoot("manifest")]
public class Manifest
{
    [XmlElement("list")]
    public List<FeatureList> FeatureLists { get; set; }

    [XmlAttribute("attr")]
    public string Attr { get; set; }

    [XmlAttribute("attr2")]
    public string Attr2 { get; set; }

    [XmlAttribute("attr3")]
    public string Attr3 { get; set; }
}

[Serializable]
public class FeatureList
{
    [XmlElement("feature")]
    public List<Feature> Features { get; set; }

    [XmlAttribute("name")]
    public string Name { get; set; }

    [XmlAttribute("attr")]
    public string Attr { get; set; }
}

[Serializable]
public class Feature
{
    [XmlAttribute("id")]
    public string Id { get; set; }

    [XmlAttribute("attr")]
    public string Attr { get; set; }
}

使用如下代码:

var stream = ... // open the XML
var serializer = new XmlSerializer(typeof (Manifest));
var manifest = (Manifest) serializer.Deserialize(stream);