使用LINQ进行XML解析,有两个名称相同但级别不同的标记,并且不总是有值

本文关键字:解析 XML 进行 LINQ 使用 两个 | 更新日期: 2023-09-27 18:24:55

我有以下XML:

   <request>
       <book>
          <id>1833801</id>
          <title>The Yiddish Policemen's Union   </title> 
           <work>
               <id>1234</id>
               <name/>
           </work>
           <similar_books>
              <book><id>243859</id><title>Stations of Tide</title>                           <isbn>0380817616</isbn>
                 <authors><author><id>14454</id><name>Michael Swanwick</name></author>            </authors>
              </book>
          </similar_books>
          <authors>
              <author>
         <id>2715</id><name>Michael Chabon</name>
           <ratings_count>215884</ratings_count></author>
          </authors>
          <popular_shelves>
         <shelf name="jewish" count="104"/><shelf name="sci-fi" count="100"/>                   
         </popular_shelves>
       </book>                
     </request>

我想让所有的标签都有各自的值,我使用以下代码:

           HttpWebRequest oReq = (HttpWebRequest)WebRequest.Create(uriRoot);
                    HttpWebResponse resp = (HttpWebResponse)oReq.GetResponse();
                    log.Info(" (ISBN= " + isbn10 + ") Http request has response.");
                    if (resp.ContentType.StartsWith("application/xml", StringComparison.InvariantCultureIgnoreCase))
                    {
                        Stream resultStreamISBN = resp.GetResponseStream();
                        Encoding encode = System.Text.Encoding.GetEncoding("utf-8"); //encoding for non-latin chars
                        StreamReader responseReader = new StreamReader(resultStreamISBN, encode);
        XDocument xdoc = XDocument.Parse(responseReader.ReadToEnd());
        var books = (from u in xdoc.Descendants().Elements("book")
                     select new
                     {
                         id = (string)u.Element("title"),
                         title = (string)u.Element("title"),               
                         works = (from i in u.Elements("work")
                                  select new
                                  {
                                      work_best_book_id = (int)i.Element("id"),
                                      work_name = (string)i.Element("name"),
                                  }).ToList(),
                          authors = (from i in u.Elements("authors").Elements("author")
                                    select new
                                    {
                                        id = (int)i.Element("id"),
                                        name = (string)i.Element("name"),                                       
                                        rating = (int)i.Element("rating_count")
                                    }).ToList(),
                         popular_shelves = (from i in u.Elements("popular_shelves").Elements("shelf")
                                            select new
                                            {
                                                name = (string)i.Attribute("name"),
                                                count = (int)i.Attribute("count")
                                            }).ToList(),
                     }).ToList();

该代码返回null值,并且工作不正常。我还应该注意,不同的xml文件可能不具有所有标记的值。

关于如何改进我的代码,有什么建议吗?

使用LINQ进行XML解析,有两个名称相同但级别不同的标记,并且不总是有值

检查缺少的元素,例如:

name = i.Element("name") == null ? null : i.Element("name")

对于值类型,您必须将它们更改为可为null的类型才能正常工作。

您可以转换

id = (int)i.Element("id"),

id = (int?)i.Element("id"),

全修改码

// I am inserting the following line to demonstrate how I load the XML in test code
// Basically, I copied & pasted xml in a file OP gave named request.xml
//XDocument xdoc = XDocument.Load( @"d:'Data'request.xml");

编辑

XDocument xdoc = XDocument.Load("http://www.goodreads.com/book/isbn?isbn=0007295685&key=lbScLXWyNGQ1q0BDoFFSg");
var books = (from u in xdoc.Descendants().Elements("book")
                select new
                {
                    id = (string)u.Element("title"),
                    title = (string)u.Element("title"),
                    works = (from i in u.Elements("work")
                            select new
                            {
                                work_best_book_id = (int?)i.Element("id"),
                                work_name = (string)i.Element("name"),
                            }).ToList(),
                    authors = (from i in u.Elements("authors").Elements("author")
                            select new
                            {
                                id = (int?)i.Element("id"),
                                name = (string)i.Element("name"),
                                rating = (int?)i.Element("rating_count")
                            }).ToList(),
                    popular_shelves = (from i in u.Elements("popular_shelves").Elements("shelf")
                                    select new
                                    {
                                        name = (string)i.Attribute("name"),
                                        count = (int?)i.Attribute("count")
                                    }).ToList(),
                }).ToList();