我的格式为
<?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
}
答案 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);