2009-01-12 29 views
5

Chúng tôi sử dụng một dịch vụ web của bên thứ ba mà trả về XML mà trông giống như sau (giảm bớt cho ngắn gọn):Đây có phải là cách hiệu quả nhất để thể hiện truy vấn XDocument này không?

<Response> 
    <block name="availability"> 
    <block name="cqual"> 
     <a name="result-code" format="text">L</a> 
    </block> 
    <block name="exchange"> 
     <a name="code" format="text">MRDEN</a> 
    </block> 
    <block name="mqual"> 
     <a name="rate-adaptive" format="text">G</a> 
    </block> 
    </block> 
    <block name="products"> 
    <block> 
     <a name="product-id" format="counting">1235</a> 
     <block name="realms"> 
     <block> 
      <a name="realm" format="text">[email protected]</a> 
     </block> 
     </block> 
    </block> 
    <block> 
     <a name="product-id" format="counting">1236</a> 
     <block name="realms"> 
     <block> 
      <a name="realm" format="text">[email protected]</a> 
     </block> 
     </block> 
    </block> 
    <block> 
     <a name="product-id" format="counting">1237</a> 
     <block name="realms"> 
     <block> 
      <a name="realm" format="text">[email protected]</a> 
     </block> 
     </block> 
    </block> 
    </block> 
    <status no="0" /> 
</Response> 

Đối với một mã số sản phẩm cụ thể tôi cần để có được những tên realm tức là văn bản bên trong của:

<a name="realm" format="text">-u @ surfuk2</a>

Bởi vì mỗi tên phần tử là một trong hai <block> hoặc <a> đó là một chút phiền hà để phân tích với LINQ vào biểu thức xml hoặc truy vấn.

Dưới đây là cách hiệu quả nhất/hiệu quả/biểu cảm để lấy tên lĩnh vực cho một sản phẩm cụ thể, ví dụ: 1235:

List<XElement> products = response 
    .Element("Response") 
    .Elements("block") 
    .Where(x => x.Attribute("name").Value == "products") 
    .Elements("block").ToList(); 
// 
// I broke down the query to aid readability 
// 
string realm = products.Elements("a") 
    .Where(x => x.Attribute("name").Value == "product-id") 
    .Where(y => y.Value == "1235") // hardcoded for example use 
    .Ancestors() 
    .First() 
    .Elements("block") 
    .Where(z => z.Attribute("name").Value == "realms") 
    .Elements("block") 
    .Elements("a") 
    .First().Value; 

Trả lời

2

Định nghĩa của realm theo quy định là tương đương với đơn giản:

string realm = (string) products.XPathEvaluate(
    "string(
     /*/blocks[@name='products'] 
       /*/a[@name='product-id' and . = '1236'] 
           /following-sibling::block[1] 
     ) 
    " 
            ) 

này trên thực tế là cả hai dễ đọc hơn và nhỏ gọn hơn hơn định nghĩa của realm cung cấp trong câu hỏi ban đầu.

Vì hiệu quả có liên quan, việc đánh giá một biểu thức XPath đơn lẻ cũng có thể hiệu quả hơn, tuy nhiên, để tìm hiểu xem điều này có đúng không, chúng tôi cần viết một ứng dụng sẽ so sánh thời gian hai phương pháp.

+0

Cảm ơn bạn đã phản hồi. Tôi biết tôi có thể ngắn gọn hơn rất nhiều với XPath, nhưng tôi đã tưởng tượng kéo dài chân LINQ của tôi ngày hôm nay trên một :-) – Kev

0

Có vẻ như vậy, nhưng tại sao bạn cần tất cả các cuộc gọi ToList()? Tôi thấy ba trong số các cuộc gọi này và tôi không nghĩ rằng chúng cần thiết để chúng chỉ làm chậm mã của bạn. Nhưng sau đó một lần nữa, tôi đã không sử dụng nhiều LINQ-to-XMl.

+0

Eh ... có số dư thừa từ phiên gỡ lỗi. Sắp xếp ngay bây giờ. – Kev

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