2010-10-21 76 views
2

下面的代碼片段簡單的GET屬性:的LINQ到XML從節點聲明

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml")); 
string result = ""; 
var childType = from t in themes.Descendants() 
    where t.Attribute("name").Value.Equals(theme) 
    select new { value = t.Attribute("type").Value }; 

foreach (var t in childType) { 
    result += t.value; 
} 
return result; 

和這裏的XML:

<?xml version="1.0" encoding="utf-8" ?> 
<themes> 
    <theme name="Agile"> 
    <root type="Project"> 
     <node type="Iteration" > 
     <node type="Story"> 
      <node type="Task"/> 
     </node> 
     </node> 
    </root> 
    </theme> 
    <theme name="Release" > 
    <root type="Project"> 
     <node type="Release"> 
     <node type="Task" /> 
     <node type="Defect" /> 
     </node> 
    </root> 
    </theme> 
</themes> 

我在做什麼錯?我不斷收到一個「未設置爲對象實例的對象」異常。

我試圖返回的是基於父節點類型的選定節點的類型,即如果主題是「敏捷」,父節點是「項目」,那麼返回值應該是「迭代」。這是最後的結果,但是我從來沒有那麼遠,因爲我陷入了上面所看到的情況。

+0

我編輯了我的答案以符合您添加的信息。編輯 – 2010-10-21 17:57:13

回答

5

我想你想要的東西更接近這個:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml")); 
string result = ""; 
var childType = from t in themes.Descendants("theme") 
       where t.Attribute("name").Value.Equals(theme) 
       select new { value = t.Descendants().Attribute("type").Value }; 

foreach (var t in childType) { 
    result += t.value; 
} 
return result; 

編輯: 根據您的其他信息,這也許是更近:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml")); 
string result = ""; 
var childType = from t in themes.Descendants("theme") 
       where t.Attribute("name").Value.Equals(theme) 
       where t.Element("node").Attribute("type").Value == parent 
       select new { value = t.Descendants().Attribute("type").Value }; 

foreach (var t in childType) { 
    result += t.value; 
} 
return result; 

編輯2:這是爲我工作:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml")); 
string result = ""; 
var theme = "Agile"; 
var parent = "Project"; 
var childType = from t in themes.Descendants("theme") 
      where t.Attribute("name").Value.Equals(theme) 
      where t.Element("root").Attribute("type").Value == parent 
      from children in t.Element("root").Descendants() 
      select new { value = children.Attribute("type").Value }; 
foreach (var t in childType) { 
    result += t.value; 
} 
return result; 

編輯3:這是完整的工作程序,只需將它放在控制檯應用程序的一個類中即可。

static void Main(string[] args) 
     { 
      var xml = "<themes><theme name='Agile'><root type='Project'><node type='Iteration' ><node type='Story'><node type='Task'/></node></node></root></theme><theme name='Release' ><root type='Project'><node type='Release'><node type='Task' /><node type='Defect' /></node></root></theme></themes>"; 
      XDocument themes = XDocument.Parse(xml); 
      string result = ""; 
      var theme = "Agile"; 
      var parent = "Project"; 
      var childType = from t in themes.Descendants("theme") 
          where t.Attribute("name").Value.Equals(theme) 
          where t.Element("root").Attribute("type").Value == parent 
          from children in t.Element("root").Descendants() 
          select new { value = children.Attribute("type").Value }; 

      foreach (var t in childType) 
      { 
       Console.WriteLine(t.value); 
      } 

      Console.Read(); 

     } 
+0

FirstNode沒有方法版本,它的屬性沒有屬性方法。 – Morgeh 2010-10-21 13:21:37

+0

我不得不在select語句中添加.First()到t.Descendants()以獲得它的編譯,但是我仍然沒有將對象設置爲對象的一個​​實例例外 – Morgeh 2010-10-21 13:34:24

+0

嘗試我的第二次編輯以查看它是否是你想要的。 – 2010-10-21 14:07:34

0

我沒有清除你的問題。這是我的解決方案(據我瞭解)

var childType = themes.Descendants("theme") 
          .Where(X => X.Attribute("name").Value == "Agile") 
          .Where(X => X.Descendants("root").Attributes("type").First().Value == "Project") 
          .Select(X => X.Descendants("node").Attributes("type").First().Value); 
0

您的查詢中有兩個錯誤。

第一個是:

from t in themes.Descendants() 

這會給你所有themes元素。
如果你想theme元素,則必須指定它,通過過濾,如:

from t in themes.Descendants("theme") 

第二個錯誤將因此

select new { value = t.Attribute("type").Value } 

因爲t將是一個theme元素,沒有屬性「類型」。
我不能幫忙,因爲不清楚最終的結果是什麼。

編輯:根據所添加的信息,這應該做的伎倆:

 var childType = 
      from t in doc.Descendants("theme") 
      where t.Attribute("name").Value.Equals(theme) 
      select t.Element("root") 
        .Element("node") 
        .Attribute("type").Value; 

然而,這是爲了獲取多種類型的節點具有相同theme名。
如果類型將始終相同,則應考慮致電.SingleOrDefault()

+0

以提供更多信息 – Morgeh 2010-10-21 12:22:24

1

好吧,這是我最後做的,它不是很漂亮,但它的工作原理。 它基於Pramodh的答案和幾個tweeks。

string result = ""; 
       var childType = themes.Descendants("theme") 
               .Where(x => x.Attribute("name").Value == theme) 
               .Where(x => x.Descendants("node").First().Attribute("type").Value == parentType) 
               .Select(x => x.Descendants("node").First().Descendants().First().Attribute("type").Value); 

       foreach (var t in childType) { 
        result += t; 
       } 
       return result; 

現在如果我通過主題「敏捷」和父母「迭代」它返回故事。

就像我說的不是很漂亮,但它的工作原理。

謝謝大家誰發佈的答案。