简体   繁体   中英

Accessing nested elements while iterating an XML LINQ query?

With this XML data:

<item>
  <placemarks>
    <placemark>
      <uid>{EA5FA2B2-78CB-4FAA-9F17-EBB361410499}</uid>
    </placemark>
  </placemarks>
  <links>
    <link>
      <title>Book Online</title>
      <link>https://blah</link>
    </link>
  <link>
    <title>Call to Book</title>
    <link>tel:1-866-555-5555</link>
  </link>
</links>
</item>

I'm trying to create Hotel objects w/ various attributes from the XML. Everything works fine until I hit nested XML tags and then I got stuck:

var items = root.Descendants ("item");
var hotels = from it in items
        select new Hotel () {
                Uid = it.Element ("uid").Value,
                Name = it.Element ("name").Value,
                Description = it.Element ("description").Value,
                ImageUrl = it.Element ("image_url").Value,
                RoomType = it.Element("custom_1").Value,
                PlacemarkId = it.Element("placemarks").Element("placemark").Element("uid").Value,
                BookUrl = (from links in it.Descendents("links") where links.Element("link").Element("title) = "Book Online").Value
            };

How do I get PlacemarkId to work? I keep getting null because the methods after the first Element("placemarks") evidently fails :-( And obviously, setting the BookUrl property won't compile, but that's what I'd like to do. It's really ugly because of the weird XML schema w/ nested link tags :-(

Sorry for the noob question. I tried googling for every combo of "nested xml linq select" I could think of w/ no luck :-P Would help even more if someone can let me know what I'm trying to do is called in LINQ. I would think it's possible...

Thanks in advance :-)

You can use XPathSelectElement() extension method to avoid null reference exception in case some <item> don't have placemark child (without having to manually check for nulls from C# code) :

var hotels = from it in items
        select new Hotel()
        {
            ......
            ......
            PlacemarkId = (string)it.XPathSelectElement("placemarks/placemark/uid"),
            BookUrl = (string)it.XPathSelectElement("links/link[title='Book Online']/link"),
        };

Getting BookUrl value can also be done using XPath as demonstrated above. Or if you're sure the XML structure is consistent for this part (no element is ever missing), you can use LINQ without null checking like so :

BookUrl = (from link in it.Elements("links").Elements("link") 
           where (string)link.Element("title") == "Book Online"
           select link.Element("link")).First().Value

For reference :

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