2012-02-06 34 views
5

Tôi có một khách hàng gửi một nguồn cấp dữ liệu xml mà tôi phân tích bằng cách sử dụng mã sau đây. Mã này hoạt động.Làm cách nào để bỏ qua một điều cụ thể với mệnh đề LINQ where?

reviews = from item in xmlDoc.Descendants("node") 
          select new ForewordReview() 
          { 
           PubDate = (string)item.Element("created"), 
           Isbn = (string)item.Element("isbn"), 
           Summary = (string)item.Element("review") 
          }; 

Sau khi nhận được tất cả "bài đánh giá" của tôi, tôi đã bỏ IEnumerable làm Danh sách và trả lại. Ban đầu, tôi đã có một thời gian vui vẻ và dễ dàng phân tích cú pháp XML của họ mà sử dụng để trông như thế này:

<reviews> 
    <node> 
     <created>01-01-1900</created> 
     <ISBN>12345657890123</ISBN> 
     <Review>This is a nice and silly book</Review> 
    </node> 
    <node> 
     <created>01-01-2011</created> 
     <ISBN>1236245234554</ISBN> 
     <Review>This is a stupid book</Review> 
    </node> 
    <node> 
     <created>12-06-1942</created> 
     <ISBN>1234543234577</ISBN> 
     <Review>This is a old, naughty book</Review> 
    </node> 
</reviews> 

Họ đã, tuy nhiên, thay đổi sơ đồ của họ, mà tôi không có quyền truy cập, và bây giờ họ là XML thêm vào một thẻ <node> cuối cùng vào cuối mà không chứa các phần tử quá cố mà tôi đang tìm kiếm, và vì vậy, phân tích cú pháp của tôi bị hỏng trên thẻ cuối cùng này và tôi ném một ngoại lệ. Dưới đây là ví dụ:

<reviews> 
    <node> 
     <created>01-01-1900</created> 
     <ISBN>12345657890123</ISBN> 
     <Review>This is a nice and silly book</Review> 
    </node> 
    <node> 
     <created>01-01-2011</created> 
     <ISBN>1236245234554</ISBN> 
     <Review>This is a stupid book</Review> 
    </node> 
    <node> 
     <created>12-06-1942</created> 
     <ISBN>1234543234577</ISBN> 
     <Review>This is a old, naughty book</Review> 
    </node> 
    <node> 
     <count>4656</count> 
    </node> 
</reviews> 

Tôi cần biết cách có bỏ qua thẻ cuối cùng này (luôn ở cuối tài liệu) mặc dù nó có cùng tên với tất cả "nút" khác thẻ tôi đang tìm kiếm. Tôi có một thử bắt xung quanh khối mã này nhưng nó không trả lại danh sách các đánh giá tốt ra nếu nó thấy lỗi này.

Xin cảm ơn các bạn.

+1

có thể thêm một 'nơi item.Element (" count ") == null' _ (hoặc đường khác tròn" tạo "! = Null) _ – ordag

+0

@ordag Tôi thực sự kết hợp bạn vào giải pháp của tôi cũng như với một số kiểm tra null từ đề nghị delltrees. Cảm ơn. –

Trả lời

1

thêm kiểm tra null

PubDate = (string)(item.Element("created") ?? ""), 
Isbn = (string)(item.Element("isbn") ?? ""), 
Summary = (string)(item.Element("review") ?? "") 

Luôn thêm kiểm tra null để tất cả mọi thứ bạn làm. Thực hành tốt. Trong trường hợp này, nó sẽ loại bỏ lỗi này, nhưng có khả năng cắt một lỗi sau này trong chương trình của bạn, nơi bạn cho rằng các chuỗi này không rỗng, vì vậy hãy chắc chắn và kiểm tra null sau.

+0

Vì vậy, nếu nó gặp nút lạ, nó sẽ tải lên pubdate, isbn và tóm tắt trong một đối tượng và cung cấp cho mỗi một chuỗi rỗng? Tôi chắc chắn có thể xử lý rằng hạ lưu, nếu đó là trường hợp. –

+0

chính xác. string.Empty có thể là một lựa chọn tốt hơn, nhưng đây chỉ là một ghi chú nhanh chóng – deltree

+0

@deltree: Tôi nghĩ rằng "" dễ đọc hơn string.Empty. –

4

Nếu đó là lúc nào cũng là nút cuối cùng,

var nodes = xmlDoc.Descendants("node"); 
reviews = nodes.Take(nodes.Count() - 1).Select(...); 
+0

Nó luôn là "nút" cuối cùng nhưng không phải là phần tử cuối cùng. Phần tử "đánh giá" là phần tử gốc. Điều đó có quan trọng không? –

+0

@fullNelson: Điều này sẽ lấy tất cả các phần tử được gọi là "nút" trừ phần tử cuối cùng. Bạn đã đọc mã chưa? –

+0

Tôi đã đọc nó. Tôi không bao giờ sử dụng kiểu cú pháp này (như tôi mới làm quen với LINQ) vì vậy tôi không biết nó hoạt động như thế nào. –

1

Bạn có thể đếm số lượng các nút và sau đó sử dụng quá tải này đâu, mà cũng trôi qua một số chỉ số: (http://msdn.microsoft.com/en-us/library/bb549418.aspx)

public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source, 
Func<TSource, int, bool> predicate) 

Vì vậy, một cái gì đó như thế này:

var count = xmlDoc.Descendants("node").Count(); 
xmlDoc.Descendants("node").Where((node,index) => index < count-1).Select(..) 
+0

Đó là những gì 'Take' dành cho. –

+0

Tôi chắc chắn rằng tôi biết những gì đang xảy ra ở đây, nhưng sự khác biệt về cú pháp từ mã của tôi khiến tôi tắt. Tôi nghĩ rằng những gì bạn và Matti đang sử dụng là một ký hiệu 'chấm'. Đối với tôi, tôi không biết cách thêm bộ lọc này trước mệnh đề trong câu lệnh where. –

+0

@fullnelson Các câu lệnh tương tự được viết/đọc dễ dàng hơn bằng cách sử dụng cú pháp LINQ và một số được viết/đọc dễ dàng hơn bằng cách sử dụng các phương thức mở rộng (như trên). Bạn nên biết rằng các câu lệnh linq có thể được dịch trực tiếp sang các phương thức mở rộng. – MichaelvR

2

Something như thế này nên làm như lừa:

var reviews = from item in xmlDoc.Descendants("node").Where(x => x.Element("created") != null) 
select new 
{ 
    PubDate = (string)item.Element("created"), 
    Isbn = (string)item.Element("isbn"), 
    Summary = (string)item.Element("review") 
}; 

Bạn có thể bổ sung kiểm tra null cho các phần tử khác nếu bạn muốn.

0

Bạn có thể ném mệnh đề "where" vào đó.

reviews = from item in xmlDoc.Descendants("node") where item.Descendants().Any(n => n.Name == "Review") 
         select new ForewordReview() 
         { 
          PubDate = (string)item.Element("created"), 
          Isbn = (string)item.Element("isbn"), 
          Summary = (string)item.Element("review") 
         }; 

Mẫu này sẽ chỉ kiểm tra nút con được gọi là "Xem xét", vì vậy bạn nên kiểm tra tất cả các nút con bắt buộc của mình.

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