0

我的 xml 格式为

<?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 传递给子对象序列化器。“列表”序列化然后依次循环所有“特征”条目。下面是我的代码的精简版。

我尝试了几种循环方法,但总是以无限循环结束,由于尝试以错误类型序列化错误的 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
}
4

1 回答 1

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);
于 2013-07-18T17:41:45.137 回答