从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>

第一个工作得很好,但我应该怎么做才能用相同的类反序列化第二个呢?

从InnerText和Value属性反序列化XML元素

我找到了另一种方法来解决我的问题,只使用一个类,也许有人会觉得这很有用

[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数据来自外部源,那么显然您无法控制它。

因此,您可以遵循以下任何选项:

  1. 为每个XML数据结构创建单独的类,因为据我所知,在使用XmlSerializer时没有办法控制XML反序列化
  2. 您可以使用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的引用。

参考:

相关文章: