从InnerText和Value属性反序列化XML元素
本文关键字:反序列化 XML 元素 属性 Value InnerText | 更新日期: 2023-09-27 18:17:45
我有一个XML Serializable类,属性名
[Serializable]
public class Item
{
[XmlElement("name")]
public string Name { get; set; }
}
我希望它能够以两种方式反序列化XML文件
<item>
<name>Name</name>
</item>
和
<item>
<name value="Name" />
</item>
第一个工作得很好,但我应该怎么做才能用相同的类反序列化第二个呢?
我找到了另一种方法来解决我的问题,只使用一个类,也许有人会觉得这很有用
[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; }
}
}
也许它不是非常优雅,但它在两种情况下都可以工作,并且使用相同的类
XML序列化属性可用于序列化和反序列化。如果我们假设可以使用属性来反序列化来自两个不同xml结构的Item
实例,那么序列化应该如何工作—应该将实例名称序列化为元素值,还是序列化为属性?还是两者都要?这就是为什么不能将两个不同的xml结构反序列化为单个类的原因。使用两个不同的类或手动反序列化,而不使用XML序列化属性。
既然您已经提到XML数据来自外部源,那么显然您无法控制它。
因此,您可以遵循以下任何选项:
- 为每个XML数据结构创建单独的类,因为据我所知,在使用
XmlSerializer
时没有办法控制XML反序列化 您可以使用
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
的引用。
参考: