Linq to XML 拉回存在于不同级别的属性

Linq to XML pulling back an attribute that exists on a different level

我正在尝试编写一个 Linq to XML 查询,它可以提取关键字并包含一个属性 (mediatype)

考虑以下 XML 数据...

    <?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>

有照片元素和视频元素。每个元素都有一个 mediattype 属性。

我想返回对每个关键字及其媒体类型的查询。

像这样..

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

我已经能够使用以下代码拉回关键字...

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

但是,我一直坚持撤回 mediatype 属性。此属性存在于与关键字不同的级别。

你可以这样做:

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

总而言之,您 select 首先是名称为 photovideo 的所有节点,然后根据这些元素中的每一个,您需要获取关键字 inside.Using SelectMany 扩展方法将结果展平,最终只得到一个集合

如果您的 XML 文件结构稳定,您可以使用简单的 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();

你也可以这样做:

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

只要你知道带mediatypevideo元素永远是祖父母元素。如果没有,您可能应该使用 Ancestors() 之类的东西来找到它。