2012-02-07 51 views
13

Tôi có một tài liệu XML có chứa một loạt các nút mục mà trông như thế này:Cách tốt nhất để truy vấn XDocument bằng LINQ?

<data> 
    <item> 
     <label>XYZ</label> 
     <description>lorem ipsum</description> 
     <parameter type="id">123</parameter> 
     <parameter type="name">Adam Savage</parameter> 
     <parameter type="zip">90210</parameter> 
    </item> 
</data> 

và tôi muốn LINQ nó thành một loại vô danh như thế này:

var mydata = 
    (from root in document.Root.Elements("item") 
    select new { 
     label = (string)root.Element("label"), 
     description = (string)root.Element("description"), 
     id = ..., 
     name = ..., 
     zip = ... 
    }); 

cách tốt nhất là gì thế nào để kéo từng loại tham số theo giá trị của thuộc tính 'type' của nó? Vì có nhiều yếu tố tham số, bạn hãy kết hợp với root.Elements("parameter") là một bộ sưu tập. Cách tốt nhất tôi có thể nghĩ để làm điều đó là như thế này bằng phương pháp dưới đây nhưng tôi cảm thấy như phải có một cách tốt hơn?

(from c in root.Descendants("parameter") where (string)c.Attribute("type") == "id" 
select c.Value).SingleOrDefault() 

Trả lời

25

Tôi sẽ sử dụng các phương pháp truy vấn tích hợp sẵn trong LINQ to XML thay vì XPath. Truy vấn của bạn có vẻ ổn với tôi, ngoại trừ:

  • Nếu có nhiều mục, bạn cần phải tìm con cháu thay thế; hoặc chỉ sử dụng Element nếu bạn đang tìm kiếm hậu duệ trực tiếp của mặt hàng đó
  • Bạn có thể muốn kéo tất cả các giá trị cùng một lúc và chuyển đổi chúng thành một cuốn từ điển
  • Nếu bạn đang sử dụng các kiểu dữ liệu khác nhau về nội dung , bạn có thể muốn truyền phần tử thay vì sử dụng .Value
  • Bạn có thể muốn tạo phương thức trả lại kết quả phù hợp XElement cho một loại nhất định, thay vì có một số truy vấn.

Cá nhân tôi không nghĩ rằng tôi thậm chí còn sử dụng biểu thức truy vấn cho điều này. Ví dụ:

static XElement FindParameter(XElement element, string type) 
{ 
    return element.Elements("parameter") 
        .SingleOrDefault(p => (string) p.Attribute("type") == type); 
} 

Sau đó:

var mydata = from item in document.Root.Elements("item") 
      select new { 
       Label = (string) item.Element("label"), 
       Description = (string) item.Element("description"), 
       Id = (int) FindParameter(item, "id"), 
       Name = (string) FindParameter(item, "name"), 
       Zip = (string) FindParameter(item, "zip") 
      }; 

tôi nghi ngờ bạn sẽ thấy đó là gọn gàng hơn bất kỳ thay thế sử dụng XPath, giả sử tôi đã hiểu những gì bạn đang cố gắng làm.

+0

vâng có vẻ như một cách tiếp cận tốt Jon ... vấn đề khác tôi phải tranh luận là đôi khi các giá trị là các chuỗi rỗng để có một phương thức trợ giúp để xử lý cả truy vấn thuộc tính và xử lý một cách duyên dáng dàn diễn viên vào đúng loại trong sự kiện của chuỗi rỗng có thể có ý nghĩa nhất, cảm ơn – snappymcsnap

7

sử dụng XPATH - đó là rất nhanh (trừ xmlreader - nhưng một nhiều của nếu nhân)

using (var stream = new StringReader(xml)) 
    { 
    XDocument xmlFile = XDocument.Load(stream); 

    var query = (IEnumerable)xmlFile.XPathEvaluate("/data/item/parameter[@type='id']"); 

    foreach (var x in query.Cast<XElement>()) 
    { 
     Console.WriteLine( x.Value); 
    } 

    } 
+7

vì vậy xpath nhanh hơn việc sử dụng các phương pháp LINQ được tích hợp? – snappymcsnap

+1

Câu hỏi không may mắn không bao giờ được trả lời! –

Các vấn đề liên quan