【问题标题】:Linq to XML pulling back an attribute that exists on a different levelLinq to XML 拉回存在于不同级别的属性
【发布时间】:2017-02-08 21:40:51
【问题描述】:

我正在尝试编写一个 Linq to XML 查询,该查询会拉回关键字并包含一个属性(媒体类型)

考虑以下 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 属性。此属性存在于与关键字不同的级别。

【问题讨论】:

    标签: c# xml linq linq-to-xml


    【解决方案1】:

    你可以这样做:

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

    总而言之,您首先选择名称为photovideo 的所有节点,然后根据这些元素中的每一个,您需要获取其中的关键字。使用SelectMany 扩展方法,您可以将结果展平为finally只获得一个集合

    【讨论】:

    • 这就是答案,它只是告诉我,关于 Linq to Xml,我还有很多东西要学习。谢谢!
    • 不客气@codingguy3000,使用linq有多种方法,一旦你知道如何使用它,它真的很强大,我绝对建议你更多地了解它,快乐编码;)
    【解决方案2】:

    你也可以这样做:

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

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

    【讨论】:

      【解决方案3】:

      如果您的 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();
      

      【讨论】:

      • 但是SelectMany 的解决方案真的很优雅。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-24
      • 1970-01-01
      • 2012-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多