0

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 :-)

2
  • Use Descendants("uid") instead of Element(). Commented Jun 20, 2015 at 20:43
  • So to complicate things, <item> has a <uid> tag directly underneath it (I tried to show a subset of the xml doc). If I used Descendents("uid"), it picked out this first one instead (which goes into the Uid property of Hotel). Commented Jun 20, 2015 at 20:58

1 Answer 1

2

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 :

Sign up to request clarification or add additional context in comments.

1 Comment

Didn't realize you could mix XPath w/ LINQ-XML. Thanks! :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.