如何反序列化类的特定项子集

本文关键字:子集 反序列化 | 更新日期: 2023-09-27 18:25:17

我有这个类来反序列化我的类:

public class Serializer <T> {
       public T SerializeAppPath(string xmlpath) {
           T apppath;
           using (TextReader txtReader = new StreamReader(xmlpath)) {
               XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
               apppath = (T)xmlSerializer.Deserialize(txtReader);
               return apppath;
           }
       }
} 

下面是我想将XML反序列化为的类:

   [XmlRoot("KPIPATHS")]
    public sealed class KpiPath
    {
        public sealed class KPI
        {
            [XmlElement("Name")]
            public string Name { get; set; }
            [XmlElement("RequestTemplateFullPath")]
            public string RequestTemplateFullPath { get; set; }
            [XmlElement("RequestFullPath")]
            public string RequestFullPath { get; set; }
            public KPI()
            {
            }
        }
        [XmlArray("KPIS")]
        public List<KPI> Kpis { get; set; }
        public KpiPath()
        {
        }
    }

下面是我如何执行它以从XML中获得结果。我正在检索"Kpis"的列表,我的问题是我只想从中提取一个基于条件"when Name = something"KPI集,然后我想进一步使用并传递那个KpiPath类。希望你明白我的意思。

Serializer<KpiPath> serializer2 = new Serializer<KpiPath>();
kpiPath = serializer2.SerializeAppPath(KpiPaths);

一些示例XML:

<?xml version="1.0" encoding="utf-8"?>
<KPIPATHS>
<KPIS>
    <KPI>
      <Name>AXD</Name>
      <RequestTemplateFullPath>D:'something</RequestTemplateFullPath>
      <RequestFullPath>D:'something</RequestFullPath>
      <ResultFullPath>D:'something</ResultFullPath>
    </KPI>
    <KPI>
      <Name>DRE</Name>
      <RequestTemplateFullPath>D:'something</RequestTemplateFullPath>
      <RequestFullPath>D:'something</RequestFullPath>
      <ResultFullPath>D:'something</ResultFullPath>
    </KPI>
</KPIS>

如何反序列化类的特定项子集

使用XmlSerializer将始终对给定类型上的所有内容进行反序列化/序列化。您正在尝试有条件地查询XML文档,这是一个不同的函数。XmlSerialization不应用作对XML的查询,而是应获取给定类型的全部内容,并将其完全序列化为XML,或者从XML反序列化给定类型的新实例。此外,在给定的序列化链中只能定义一个XmlRoot属性。

来自MSDN:

有两个属性可以应用于类(并且只有类):XmlRootAttribute和XmlTypeAttribute。这些属性是非常相似。XmlRootAttribute只能应用于一个类:序列化时表示XML文档打开的类和结束元素——换句话说,根元素。这个另一方面,XmlTypeAttribute可以应用于任何类,包括根类。

有关详细信息,请参阅此处:http://msdn.microsoft.com/en-us/library/2baksw0z(v=vs.110).aspx

简而言之,您希望在序列化期间有一个不同的节点作为XML根,这是不受支持的。


在您的情况下,我会在KpiPath类中添加一个函数,以便在类型实例中的数据完全取消序列化后(因为函数和方法不可序列化)查询数据,类似于以下内容:

void Main() {
    XmlSerializer ser = new XmlSerializer(typeof(KpiPath));
    KpiPath newPath = new KpiPath();
    newPath.Kpis.Add(new KPI() {Name = "test", RequestTemplateFullPath = @"C:'test", RequestFullPath = @"C:'test"});
    newPath.Kpis.Add(new KPI() {Name = "test", RequestTemplateFullPath = @"C:'newTest", RequestFullPath = @"C:'newTest"});
    newPath.Kpis.Add(new KPI() {Name = "anotherTest", RequestTemplateFullPath = @"C:'funTest", RequestFullPath = @"C:'funTest"});
    StringBuilder sb = new StringBuilder();
    using(StringWriter writer = new StringWriter(sb)) {
        ser.Serialize(writer, newPath);
    } // end using
    Debug.WriteLine(sb.ToString());
    List<KPI> matches = newPath.KPIFromName("test");
    //For debugging, make sure we get two results (matching the two named test above), print a failure message if not.
    Debug.Assert(matches.Count == 2, "Invalid Count");
}
[XmlRoot("KPIPATHS"), Serializable()]
public sealed class KpiPath {
    [XmlArray("KPIS")]
    public List<KPI> Kpis { get; set; }
    public KpiPath() {
        Kpis = new List<KPI>();
    } // end default constructor
    public List<KPI> KPIFromName(string kpiName) {
        if(String.IsNullOrWhiteSpace(kpiName)) {
            throw new ArgumentNullException("kpiName", "No name provided.");
        } // end if
        List<KPI> matches = new List<KPI>();
        if(this.Kpis.Any()) {
            for(int i = 0; i < this.Kpis.Count; i++) {
                if(this.Kpis[i].Name.ToUpperInvariant() == kpiName.ToUpperInvariant()) {
                    matches.Add(this.Kpis[i]);
                } // end if
            } // end for loop
        } // end if
        return matches;
    } // end function GetFromName
} // end class KpiPath
[Serializable()]
public sealed class KPI {
    [XmlElement("Name")]
    public string Name { get; set; }
    [XmlElement("RequestTemplateFullPath")]
    public string RequestTemplateFullPath { get; set; }
    [XmlElement("RequestFullPath")]
    public string RequestFullPath { get; set; }
    public KPI() {
    } // end default constructor
} // end class KPI

通过这种方式,您可以轻松地检索具有感兴趣名称的项,并且不必具有任何复杂/难以遵循的反序列化逻辑。

如果这对您来说不是一个好的解决方案,我建议您使用XmlReader/XmlDocument组合,根据XPath语法从文档中读取特定项目。

以下是解决此问题的一些相关主题:

  • 部分xml序列化/反序列化
  • 序列化/反序列化部分XML文件
  • http://msdn.microsoft.com/en-us/library/6exf3h2k(v=vs.110).aspx<--何时/如何使用序列化类型