Q: Linq to XML pulling back an attribute that exists on a different level I'm trying to write a Linq to XML query that pulls back keyword and includes an attribute (mediatype)
Consider the following XML data...
    <?xml version="1.0" encoding="utf-8"?>
<media>
    <photos>        
        <photo mediatype="photo" photographer="Jag_cz" description="Colored splashes in abstract shape, isolated on white background" id="16" name="50623755_F.jpg" folder="HR Headset">
            <keywords>
                <keyword>fish</keyword>
                <keyword>abstract</keyword>         
            </keywords>
        </photo>
    </photos>
    <videos>
        <video mediatype="video" description="Bear by a stream" folder="streamfolder" name="stream.mp4">
            <keywords>
                <keyword>stream</keyword>
                <keyword>river</keyword>
                <keyword>water</keyword>
            </keywords>
        </video>
        <video mediatype="video" description="Stream with a bear" folder="bearfolder" name="bear.mp4">
            <keywords>
                <keyword>salmon</keyword>
                <keyword>fish</keyword>
            </keywords>
        </video>
    </videos>
</media>

There are photo elements and video elements. Each element has a mediattype attribute. 
I want pull back a query of each keyword with it's media type.
Something like this..
mediatype   keyword
---------   -------              
photo       fish
photo       abstract
video       stream
video       river
video       water
video       salmon
video       fish

I have been able to pull back the keywords with the following code...
using System;
using System.Xml.Linq;
using System.Linq;

class Program
{
    public static void Main(string[] args)
    {
        String strPath = @"C:\videodata\media.xml";

        XElement xEle = XElement.Load(strPath);

        var keywordquery = from k in xEle.Descendants("keyword")
                           select new
                               {
                                   keyword = (string)k.Value
                               };

        foreach (var k in keywordquery)
        {
            Console.WriteLine(k.keyword);
        }

        Console.WriteLine("Press <enter> to continue");
        Console.ReadLine();
    }
}

However, I'm stuck on pulling back the mediatype attribute. This attribute exists on a different level than keyword. 

A: You can do something like this:
var query=  xEle.Descendants().Where(e=>e.Name=="photo" || e.Name=="video")
                              .SelectMany(e=>e.Descendants("keyword")
                                              .Select(x=>new {mediatype=e.Name,
                                                              keyword=x.Value
                                                             }));

In summary, you select first all the nodes with name  photo and video, and then per each of these elements you need to get the keywords inside.Using the SelectMany extension method you flatten the result to finally get just one collection

A: You could do this as well:
var keywordquery = from k in xEle.Descendants("keyword")
                   select new
                   {
                       keyword = (string)k.Value,
                       mediatype = (string)k.Parent.Parent.Attribute("mediatype")
                   };

As long as you know that the video element with the mediatype will always be the grandparent element.  If not, you should probably use something like Ancestors() to find it.

A: If you have stable structure of your XML file you can use simple select:
  var keywordquery = xEle.Descendants("keyword")
    .Select(x => new { MediaType = x.Parent?.Parent.Attribute("mediatype").Value, KeyWords = x.Value});

  foreach (var k in keywordquery)
  {
    Console.WriteLine($"{k.MediaType} | {k.KeyWords}");
  }

  Console.WriteLine("Press <enter> to continue");
  Console.ReadLine();

