2014-10-02 46 views
1

我有這樣的類反序列化我的課:如何反序列化類的特定項目的子集

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」的撤回清單,我的問題是我想從中取得只有一個KPI設置基於條件"when Name = something"然後我想使用和進一步通過,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> 
+0

能否請您包括一些示例XML? – xDaevax 2014-10-02 12:45:15

+0

您可以手動解析'xml'(壞),或者您可以反序列化所有內容(整個'KPIPATHS')並稍後執行條件過濾。 – Sinatr 2014-10-02 13:23:02

+0

不,我想避免xml reader或類似的東西。序列化的方式是我選擇的。 – Bob 2014-10-02 13:25:25

回答

0

使用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類來查詢你的類型實例中的數據增加一個功能,一旦它已經完全deseriailzed(因爲函數和方法不序列化)與此類似:

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的(XPath)語法從文檔中特定項目的路徑。

下面是解決這個問題的一些相關主題:

+0

嗨xDaevax,我把你的方法放在KpiPath類中,我試圖從其他類中調用它,如下所示:List ff = kpiPath.KPIFromName(kpiname.ToString());但它不工作,因爲無法找到類型或名稱空間KPI? – Bob 2014-10-02 15:43:39

+0

@Bob這可能是因爲你已經在'KpiPath'類中聲明瞭你的'KPI'類(你不必這樣做,並且可能因爲你聲明這個類是公共的而不需要)。嘗試移動「KpiPath」類之外的「KPI」類。 – xDaevax 2014-10-02 15:45:25

+0

@Bob讓我知道這是否適合你。 – xDaevax 2014-10-02 15:54:04

相關問題