C# Linq到XML回拉存在于不同级别的属性

C# Linq到XML回拉存在于不同级别的属性,c#,xml,linq,linq-to-xml,C#,Xml,Linq,Linq To Xml,我正在尝试编写一个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

我正在尝试编写一个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>
我已经能够拉回来的关键字与以下代码

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();
    }
}
使用系统;
使用System.Xml.Linq;
使用System.Linq;
班级计划
{
公共静态void Main(字符串[]args)
{
字符串strPath=@“C:\videodata\media.xml”;
XElement xEle=XElement.Load(strPath);
var keywordquery=从xEle.subjects中的k开始(“关键字”)
选择新的
{
关键字=(字符串)k.Value
};
foreach(关键字查询中的var k)
{
Console.WriteLine(k.keyword);
}
Console.WriteLine(“按以继续”);
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
                                                             }));

总之,首先选择名称为
photo
video
的所有节点,然后根据这些元素中的每一个元素,您需要获取其中的关键字。使用
SelectMany
扩展方法,您可以将结果展平,最终只获得一个集合如果您的XML文件结构稳定,您可以使用简单的选择:

  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=xEle.subjects(“关键字”)
.Select(x=>new{MediaType=x.Parent?.Parent.Attribute(“MediaType”).Value,关键字=x.Value});
foreach(关键字查询中的var k)
{
Console.WriteLine($“{k.MediaType}{k.KeyWords}”);
}
Console.WriteLine(“按以继续”);
Console.ReadLine();

您也可以这样做:

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

只要您知道带有
mediatype
video
元素将始终是祖辈元素。如果没有,您可能应该使用类似于
祖先()
的方法来查找它。

这就是答案,它只是告诉我,关于Linq to Xml,我还有很多需要学习的地方。非常感谢。欢迎@codingguy3000,使用linq有多种方法,一旦你知道如何使用它,它就非常强大,我绝对建议你多了解它,快乐编码;)但是使用
SelectMany的解决方案非常优雅。
var keywordquery = from k in xEle.Descendants("keyword")
                   select new
                   {
                       keyword = (string)k.Value,
                       mediatype = (string)k.Parent.Parent.Attribute("mediatype")
                   };