我有XML Serializable类,其属性名称为
[Serializable]
public class Item
{
[XmlElement("name")]
public string Name { get; set; }
}
我希望它能够以两种方式反序列化我拥有的XML文件:
<item>
<name>Name</name>
</item>
和
<item>
<name value="Name" />
</item>
第一个工作正常,但我应该做些什么才能在同一个类中反序列化第二个?
答案 0 :(得分:2)
XML序列化属性适用于序列化和反序列化。如果我们假设可以使用属性从两个不同的xml结构反序列化Item
的实例,那么序列化应该如何工作 - 它应该将实例名称序列化为元素值,还是属性?或两者兼而有之?这就是为什么你不能将两个不同的xml结构反序列化为单个类。使用两个不同的类或手动反序列化它而不使用XML序列化属性。
答案 1 :(得分:0)
由于您已经提到XML数据来自外部来源,所以很明显您无法控制它。
因此,您可以按照以下任意选项进行操作:
XmlSerializer
XDocument
自行阅读XML,以克服此限制。如果按照第二个想法,我已经创建了一个小型控制台应用程序来演示。
主要代码如下:
MemoryStream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlData));
XDocument doc = XDocument.Load(xmlStream);
var records = from record in doc.Descendants("item").Descendants()
select new Item(!record.IsEmpty ? record.Value : record.Attribute("value").Value);
我在这里使用LinqToXml读取元素并检查元素是否为空,即Value
不为空,然后使用Value
,否则从元素中读取值Attribute
。
控制台应用程序(完整代码):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace Console.TestApp
{
class Program
{
static string xmltypeFirst = @"<item>
<name>John</name>
</item>";
static string xmltypeSecond = @"<item>
<name value='Smith' />
</item>";
static void Main(string[] args)
{
var data = xmltypeFirst;
var result = Deserialize(data).ToList();
Console.WriteLine("Name: " + result[0].Name);
data = xmltypeSecond;
result = Deserialize(data).ToList();
Console.WriteLine("Name: " + result[0].Name);
Console.WriteLine("Press any to key to exit..");
Console.ReadLine();
}
private static IEnumerable<Item> Deserialize(string xmlData)
{
MemoryStream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlData));
XDocument doc = XDocument.Load(xmlStream);
var records = from record in doc.Descendants("item").Descendants()
select new Item(!record.IsEmpty ? record.Value : record.Attribute("value").Value);
return records;
}
}
[Serializable]
public class Item
{
public Item(string name)
{
this.Name = name;
}
[XmlElement("name")]
public string Name { get; set; }
}
}
注意:要运行此功能,您需要在项目中添加对System.Xml.Linq.dll
的引用。
参考:here
答案 2 :(得分:0)
我找到另一种方法来解决我的问题,只使用一个类,也许有人会发现这个有用的
[Serializable]
public class Item
{
[XmlElement("name")]
public NameElement NameElement { get; set; }
}
public class NameElement
{
[XmlAttribute("value")]
public string Value { get; set; }
[XmlText]
public string Text { get; set; }
[XmlIgnore]
public string Name
{
get { return String.IsNullOrEmpty(this.Value) ? this.Text : this.Value; }
set { this.Value = value; }
}
}
也许它不是超级优雅但它适用于两种情况并且使用相同的类。