2016-04-12 89 views
0

我有這個類代表了我的XML節點的TestCase:C#,XML如何通過獲取與XMLNode.SelectSingleNode XML節點週期

public class TestCase 
{ 
    [XmlAttribute("name")] 
    public string name { get; set; } 
    public string version { get; set; } 
    public string verdict { get; set; } 
    public string objective { get; set; } 
    public string criteria { get; set; } 
    public string issue { get; set; } 
    public string clientcomments { get; set; } 
    public string authoritycomments { get; set; } 
    public string sdk { get; set; } 

} 

我用XmlNode.SelectSingleNode中獲取特定的節點我XML。有關信息,如果重要,則沒有重複的節點(沒有具有相同名稱屬性的節點)。

到目前爲止,我有這樣的代碼:

public static TestCase FetchNode(string NodeName, string Path) 
    { 
     TestCase testcase = new TestCase(); 
     string[] attr = { "name", "version", "verdict", "objective", "criteria" 
       , "issue", "clientcomments", "authoritycomments", "sdk" }; 
     string[] attrval = { null, null,null,null,null,null,null,null,null}; 

     XmlDocument doc = new XmlDocument(); 
     doc.Load(Path); 

     XmlNode node = doc.SelectSingleNode("/TestsList/TestCase[@name='" + NodeName + "']"); 

     for (var i = 0; i == attr.Length - 1;i++) 
     { 
      attrval[i] = node[attr[i]].InnerText; 
     } 

     testcase.name = attrval[0]; 
     testcase.version = attrval[1]; 
     testcase.verdict = attrval[2]; 
     testcase.objective = attrval[3]; 
     testcase.criteria = attrval[4]; 
     testcase.issue = attrval[5]; 
     testcase.clientcomments = attrval[6]; 
     testcase.authoritycomments = attrval[7]; 
     testcase.sdk = attrval[8]; 

     return testcase; 

    } 

但是,此代碼是不可擴展可言,如果我改變我的階級結構,我需要改變功能,因爲類的每個元素都硬編碼在其中。

這是一個廣泛的請求,但我怎麼寫這個函數,所以如果我添加或刪除TestCase的類定義中的字符串,我不必更改函數FetchNode。

謝謝你的時間。

回答

1

你可以使用XmlSerializer.Deserialize

例子:

using System; 
using System.IO; 
using System.Xml; 
using System.Xml.Serialization; 

public class TestCase 
{ 
    [XmlAttribute("name")] 
    public string name { get; set; } 
    public string version { get; set; } 
    public string verdict { get; set; } 
    public string objective { get; set; } 
    public string criteria { get; set; } 
    public string issue { get; set; } 
    public string clientcomments { get; set; } 
    public string authoritycomments { get; set; } 
    public string sdk { get; set; } 
} 

public class Program 
{ 
    public const string XML = @" 
<TestCase name='TicketName'> 
    <name>Jon Nameson</name> 
    <version>10.1</version> 
    <verdict>High</verdict> 
</TestCase> 
"; 

    public static void Main() 
    { 
     var doc = new XmlDocument(); 
     doc.LoadXml(XML); 

     var node = doc.SelectSingleNode("/TestCase"); 

     var serializer = new XmlSerializer(typeof(TestCase)); 

     var testcase = serializer.Deserialize(new StringReader(node.OuterXml)) as TestCase; 

     Console.WriteLine(testcase.name); 
     Console.WriteLine(testcase.version); 
     Console.WriteLine(testcase.verdict); 
    } 
} 

DotNetFiddle

+0

工作得很好,沒有太多變化。謝謝。 –

1

您可以直接從反序列化使用下面的擴展相結合的方法XmlSerializerXmlNodeReader選擇XmlNode

public static class XmlNodeExtensions 
{ 
    public static T Deserialize<T>(this XmlNode element, XmlSerializer serializer = null) 
    { 
     using (var reader = new ProperXmlNodeReader(element)) 
      return (T)(serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader); 
    } 

    class ProperXmlNodeReader : XmlNodeReader 
    { 
     // Bug fix from https://stackoverflow.com/questions/30102275/deserialize-object-property-with-stringreader-vs-xmlnodereader 
     public ProperXmlNodeReader(XmlNode node) 
      : base(node) 
     { 
     } 

     public override string LookupNamespace(string prefix) 
     { 
      return NameTable.Add(base.LookupNamespace(prefix)); 
     } 
    } 
} 

這增加了一個extension methodXmlNode它調用XmlSerializerdeserialize所選擇的節點到所述類型T的一個實例。

然後做:

var testcase = node.Deserialize<TestCase>(); 

這是相同的:

var testcase = XmlNodeExtensions.Deserialize<TestCase>(node); 

在你的情況你TestCase類,預期根元素名稱即<TestCase>,符合實際的節點名稱。如果節點名稱與預期的根元素名稱不匹配,您可以按照XmlSerializer Performance Issue when Specifying XmlRootAttribute中的說明指示XmlSerializer預期不同的根名稱。

+0

感謝您的詳細回覆。我對c#的理解並不那麼先進,所以我不確定你提供給我的代碼究竟是幹什麼的。你介意給我一個簡短的代碼解釋嗎?謝謝! –

+0

@JephGagnon - 我添加了一個簡短的解釋,但我不確定你需要知道什麼。 – dbc

+0

這更多的是對你完全做了什麼的一般理解。你提供的鏈接爲我提供了更多的信息。我將Negorath的回答標記爲答案,因爲我可以理解所做的事情,但我也一定會嘗試這種方法(更重要的是理解它)。謝謝。 –