2013-08-16 157 views
1

我有這樣的XML的LINQ to XML查詢返回錯誤的數據

<?xml version="1.0" encoding="utf-8" ?> 
<Departments> 
<Department> 
    <id>001</id> 
    <Section> 
    <SectionId>001001</SectionId> 
    <Room> 
     <RoomID>001001001</RoomID> 
     <Owner>guest1</Owner> 
    </Room> 
    <Room> 
     <RoomID>001001002</RoomID> 
     <Owner>guest11</Owner> 
    </Room> 
    </Section> 
    <Section> 
    <SectionId>001002</SectionId> 
    <Room> 
     <RoomID>001002001</RoomID> 
     <Owner>guest2</Owner> 
    </Room> 
</Section> 
</Department> 
</Departments> 

,這是使用LINQ to XML我的代碼

var xDoc = XDocument.Load(inputUrl); 

var sections = from el in xDoc.Descendants("Department") 
         where el.Element("id").Value.Equals("001") 
         select el.Element("Section"); 

var rooms = from el in sections 
       where el.Element("SectionId").Value.Equals("001001") 
       select el.Element("Room"); 

var roomsList = (from el in rooms 
      select new Room 
      { 
       roomID = (string)el.Element("RoomID"), 
       owner = (string)el.Element("Owner") 
      }).ToList(); 

我的問題是我只在列表獲得1間房間,但我應該得到兩個。請同樣建議,如果這是使用LINQ to xml的正確方式,那麼對於LINQ我是相當新的。

回答

1

只是表明,有很多方法可以皮膚貓:

var xDoc = XDocument.Load(@"C:\TEST\TEST.XML"); 

var depts = from e in xDoc.Descendants("Department") 
      where e.Element("id").Value.Equals("001") 
      select e; 

var sections = from e in depts.Descendants("Section") 
      where e.Element("SectionId").Value.Equals("001001") 
      select e; 

var rooms = (from e in sections.Descendants("Room") 
      select new //Room 
      { 
       ID = (string)e.Element("RoomID"), 
       Owner = (string)e.Element("Owner") 
      }).ToList(); 
0

如果你改變什麼:

select el.Element("Room"); 

select el.Elements("Room"); 
+0

如果我使用的元素(「房間」)我得到這個錯誤錯誤\t System.Collections.Generic.IEnumerable <的System.Xml。 Linq.XElement>'不包含'Element'的定義,並且沒有可以找到接受類型'System.Collections.Generic.IEnumerable '的第一個參數的擴展方法'Element'你在這條線上缺少使用指令或程序集引用?)roomID =(string)el.Element(「RoomID」), – TRS

+0

這不是唯一的問題。他也只從'部門'中獲得第一個「部分」。 – MarcinJuraszek

0

你只是在中間的查詢選擇一個房間,應該是.Elements(...)(注意尾隨s):

 var rooms = from el in sections 
         where el.Element("SectionId").Value.Equals("001001") 
         select el.Elements("Room"); 

這同樣適用於您的section查詢。

+0

如果我使用元素(「房間」),我得到這個錯誤錯誤系統。Collections.Generic.IEnumerable '不包含'Element'的定義,也沒有接受類型爲「System.Collections.Generic.IEnumerable '可以在此行找到(你是否缺少使用指令或程序集引用?)roomID =(string)el.Element(「RoomID」), – TRS

+0

這不是唯一的問題。他也只從'部門'中獲得第一個「部分」。 – MarcinJuraszek

2

變化sectionsrooms查詢:

var sections = xDoc.Descendants("Department") 
        .FirstOrDefault(x => (string)x.Element("id") == "001") 
        .Elements("Section"); 

var rooms = sections.Where(x => (string)x.Element("SectionId") == "001001") 
        .Elements("Room"); 

有了這些,你會得到2個房間。

爲什麼不是你的代碼工作?

  1. select el.Element("Section")Department只選擇第一section元素 - 你永遠無法從sectionid == "001002"
  2. select el.Element("Room")rooms查詢來獲取返回房間只從每一個匹配部分的第一個房間。

您可以更改ElementElements,並增加額外SelectMany(x => x)通話,讓您的基於語法的查詢工作:

var sections = from el in xDoc.Descendants("Department") 
       where el.Element("id").Value.Equals("001") 
       select el.Elements("Section"); 

var rooms = from el in sections.SelectMany(x => x) 
      where el.Element("SectionId").Value.Equals("001001") 
      select el.Elements("Room"); 

var roomsList = (from el in rooms.SelectMany(x => x) 
        select new 
        { 
         roomID = (string)el.Element("RoomID"), 
         owner = (string)el.Element("Owner") 
        }).ToList(); 
+0

您可以添加一段關於此代碼工作原因的解釋 - 即,它有什麼不同? – Tim

+0

@Tim剛剛做到了!希望現在更清楚。 – MarcinJuraszek

+0

是的,這是 - 謝謝!我正在摸索着試圖找出這個問題的答案。 – Tim

2

作爲替代其他的答案,你可以使用Extensions.XPathSelectElements Method (XNode, String)(請確保您在using System.Xml.XPath指令添加到您的文件的頂部):

string 
    departmentId = "001", 
    sectionId = "001001"; 
var xDoc = XDocument.Load(inputUrl); 
var rooms = xDoc.XPathSelectElements(
    String.Format(
     "//Department[id={0}]/Section[SectionId={1}]/Room", 
     departmentId, 
     sectionId)) 
    .Select(el => new Room 
    { 
     roomID = (string)el.Element("RoomID"), 
     owner = (string)el.Element("Owner") 
    }).ToList(); 

它自己喜好的問題。我覺得這篇文章寫得更簡短,更易於閱讀。

+1

我認爲這是我的首選解決方案;它很容易閱讀。 –

+0

我喜歡這個,漂亮整潔:-) – TRS

+1

對不起,我改變了我的想法使用Linq到Xml,這個小例子是一個問題的改造,我的XML文件是相當大的,並按照這個我看到使用Linq的點Xml比XPath http://blog.dreamlabsolutions.com/post/2008/12/04/LINQ-to-XML-and-LINQ-to-XML-with-XPath-performance-review.aspx – TRS