简体   繁体   中英

nested linq to XML query

How can I get LINQ to loop the nested winning branch? I want to loop the sum_sweeden and sum_japan fields.

This is my XML structure:

<TheAPI>
  <TheResult>
    <command>booksResults</command>
  </TheResult>
  <TheData>
    <books>
      <book id="101495">
        <coupon_close_date>1366030400</coupon_close_date>
        <coupon_local_close_date>1366012400</coupon_local_close_date>
        <book_status id="1">Published</book_status>
        <book_details>
          <book_detail>
            <author>bnvbnvb</author>
            <publisher>nnbnbn</publisher>           
          </book_detail>
        </book_details>
        <deals_breakdowns>
          <deal_breakdown id="1">
            <winning deal="5">
              <sum_sweeden>715.00</sum_sweeden>
              <sum_japan>715.00</sum_japan>
            </winning>
          </deal_breakdown>
          <deal_breakdown id="2">
            <winning>
              <sum_sweeden>100.00</sum_sweeden>
              <sum_japan>100.00</sum_japan>
            </winning>
          </deal_breakdown>
        </deals_breakdowns>
      </book>
      <book id="101417">
        <coupon_close_date>1387684800</coupon_close_date>
        <coupon_local_close_date>1387666800</coupon_local_close_date>
        <book_status id="1">Published</book_status>
        <book_details>
          <book_detail>
            <author>mn xccx cvx</author>
            <publisher>hjgh hg jghjg</publisher>         
          </book_detail>
        </book_details>
        <deals_breakdowns>
          <deal_breakdown id="1">
            <winning>0</winning>
          </deal_breakdown>
          <deal_breakdown id="2">
            <winning>
              <sum_sweeden >100</sum_sweeden>
              <sum_japan >100</sum_japan>
            </winning>
          </deal_breakdown>
        </deals_breakdowns>
      </book>
  </TheData>
</TheAPI>

I was able successfully to loop all the book with LINQ:

public class ResultsBookData
{
    public decimal couponCloseDate { get; set; }
    public decimal SumSweeden { get; set; }
    public int BookStatusId { get; set; }
    public string BookStatus { get; set; }
    public string Author { get; set; }
    public string Publisher { get; set; }
    public decimal SumJapan { get; set; }              
}

var result = (from node in books.Elements("book")
              select new ResultsBookData()
              {
                  couponCloseDate = node.SafeValueAsInt("coupon_close_date"),
                  SumSweeden = node.SafeValueAsInt("sum_sweeden"),
                  BookStatusId = node.SafeAttAsInt("book_status", "id"),
                  BookStatus = node.SafeValueAsString("book_status"),
                  Author = node.Element("book_details").HasElements ? node.Element("book_details").Element("book_detail").Element("author").Value : null,
                  Publisher = node.Element("book_details").HasElements ? node.Element("book_details").Element("book_detail").Element("publisher").Value : null,      
                  SumSweeden = node.Element("deals_breakdowns").Element("deals_breakdown").Element("winning").SafeValueAsDecimal("sum_sweeden"),      
                  SumJapan = node.Element("deals_breakdowns").Element("deals_breakdown").Element("winning").SafeValueAsDecimal("sum_japan"),
              }).ToList()

First - you have several <deals_breakdown> elements in <deals_breakdowns> . So, you need to select all of them with Elements("deals_breakdown") . Second - you need to aggregate (summarize) <sum_sweeden> element values, because you have SumSweeden property which expects single decimal value, not collection of decimals:

SumSweeden = node.Element("deals_breakdowns")
                 .Elements("deals_breakdown")
                 .Sum(b => b.Element("winning")
                            .SafeValueAsDecimal("sum_sweeden")),

Also keep in mind, that you can safely cast elements to strings or some nullable types (bool, int, decimal). With this in mind you can get rid of your custom extension methods and use following query:

from book in books.Elements("book")
let bookStatus = book.Element("book_status")
let bookDetail = book.Elements("book_details").Elements("book_detail").FirstOrDefault()
let winnings = book.Element("deals_breakdowns").Elements("deal_breakdown").Elements("winning")
select new ResultsBookData()
{
    couponCloseDate = (int)book.Element("coupon_close_date"),
    BookStatusId = (int)bookStatus.Attribute("id"),
    BookStatus = (string)bookStatus,
    Author = bookDetail == null ? null : (string)bookDetail.Element("author"),
    Publisher = bookDetail == null ? null : (string)bookDetail.Element("publisher"),
    SumSweeden = winnings.Sum(w => (decimal?)w.Element("sum_sweeden") ?? 0),
    SumJapan = winnings.Sum(w => (decimal?)w.Element("sum_japan") ?? 0)
}

Result:

{
   couponCloseDate: 1366030400.0,
   SumSweeden: 815.00,
   BookStatusId: 1,
   BookStatus: "Published",
   Author: "bnvbnvb",
   Publisher: "nnbnbn",
   SumJapan: 815.00      
},
{
   couponCloseDate: 1387684800.0,
   SumSweeden: 100.0,
   BookStatusId: 1,
   BookStatus: "Published",
   Author: "mn xccx cvx",
   Publisher: "hjgh hg jghjg",
   SumJapan: 100.0
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM