Linq to XML returns an attribute that exists at a different level

I am trying to write a Linq to XML query that returns the keyword back and includes the 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 photocells and video elements. Each element has a mediattype attribute.

I want to return a query for each keyword with its media type.

Something like that..

mediatype   keyword
---------   -------              
photo       fish
photo       abstract
video       stream
video       river
video       water
video       salmon
video       fish

I managed to cancel the keywords using 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 am stuck in returning the mediatype attribute. This attribute exists at a different level than the keyword.

+4
source share
3 answers

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
                                                             }));

, photo video, . SelectMany, , , ,

+4

:

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

, video mediatype grandparent. , - Ancestors(), .

+1

If you have a stable structure for your XML file, you can use a simple choice:

  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();
0
source

Source: https://habr.com/ru/post/1669200/


All Articles