【问题标题】:How I can get an array of array using Linq to XML?如何使用 Linq to XML 获取数组数组?
【发布时间】:2015-10-01 07:37:10
【问题描述】:

如何获取所有流派的列表? 现在我只得到每首歌的第一个流派。

XML 文件:

<Library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Songs>
    <Song>
      <Title>High Hopes</Title>
      <Genres>
        <Genre>Rock</Genre>
        <Genre>American</Genre>      
      </Genres>
     </Song>
    <Song>
      <Title>Imagine</Title>
      <Genres>
        <Genre>Pop</Genre>
        <Genre>Unplugged</Genre>      
      </Genres>
    </Song>
  </Songs>
</Library>

C# 代码:

public void ListGenres()
{
  System.Xml.Linq.XElement xLibrary = System.Xml.Linq.XElement.Load(@"c:\Library.xml");
  System.Xml.Linq.XElement xSongs = xLibrary.Element("Songs");
  System.Collections.Generic.IEnumerable<string> genres = 
                from code in xSongs.Elements("Song")
                let genre = (string)code.Element("Genres").Element("Genre")
                orderby genre
                select genre;
  foreach (string genre in genres)
  {
      Console.WriteLine(genre);
  }
}

结果:

Pop
Rock

但我需要:

Rock
American
Pop
Unplugged

谢谢。

【问题讨论】:

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


    【解决方案1】:

    由于您没有执行任何过滤器,因此您可以直接使用Descendants,如下所示:-

    XDocument xLibrary = XDocument.Load(@"c:\Library.xml");
    IEnumerable<string> result = xLibrary.Descendants("Genre").Select(x => (string)x);
    

    或者,如果您更喜欢查询语法:-

    IEnumerable<string> res = from genre in xdoc.Descendants("Genre")
                                          select (string)genre;
    

    您需要为此导入 using System.Linq;。这将产生您期望的输出,即 Rock American Pop Unplugged,即使它没有被订购。您可以随时使用order by caluse。

    查看this 答案以了解我为什么使用Descendants 而不是Elements

    【讨论】:

    • IEnumerable 结果 = xLibrary.Descendants("Genre").Select(x => (string)x).Distinct();
    • @RahulSingh 很好的解释:)
    【解决方案2】:

    如果您不需要任何额外的流派过滤,您可以像这样轻松获取文档中的所有流派:

    var genres = xLibrary.XPathSelectElements("//Genre").Select(g => g.Value);
    

    注意:XPathSelectElements 是一种扩展方法,请确保您在源代码中使用 System.Xml.XPath 命名空间才能使用此方法。

    【讨论】:

      【解决方案3】:

      如果您的 xml 还包含歌曲以外的元素的“流派”节点:

      XDocument doc = XDocument.Parse(xml);
      
      var genres = doc.Root.Element("Songs")
                           .Elements("Song")
                           .Elements("Genres")
                           .Elements("Genre")
                           .Select(e => e.Value);
      

      【讨论】:

        【解决方案4】:

        假设您需要每首歌曲的流派排序列表。你可以试试下面的代码。

        public void ListGenres()
        {
          System.Xml.Linq.XElement xLibrary = System.Xml.Linq.XElement.Load(@"c:\Library.xml");
          System.Xml.Linq.XElement xSongs = xLibrary.Element("Songs");
          System.Collections.Generic.IEnumerable<List<string>> genresList = 
                        from code in xSongs.Elements("Song")
                        let genreList = (string)code.Element("Genres")
                        select genreList.ToList();
          foreach (List<string> genreList in genresList)
          {
             var orderedList = genreList.OrderBy(x=>x);
             foreach(string genre in orderedList)
              Console.WriteLine(genre);
          }
        }
        

        【讨论】:

          【解决方案5】:

          试试这个

          using System;
          using System.Collections.Generic;
          using System.Linq;
          using System.Text;
          using System.Xml;
          using System.Xml.Linq;
          
          namespace ConsoleApplication52
          {
              class Program
              {
                  static void Main(string[] args)
                  {
                      string input =
                          "<Library xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
                            "<Songs>" +
                              "<Song>" +
                                "<Title>High Hopes</Title>" +
                                "<Genres>" +
                                  "<Genre>Rock</Genre>" +
                                  "<Genre>American</Genre>" +
                                "</Genres>" +
                               "</Song>" +
                              "<Song>" +
                                "<Title>Imagine</Title>" +
                                "<Genres>" +
                                  "<Genre>Pop</Genre>" +
                                  "<Genre>Unplugged</Genre>" +
                                "</Genres>" +
                              "</Song>" +
                            "</Songs>" +
                          "</Library>";
          
                      XElement library = XElement.Parse(input);
          
                      var results = library.Descendants("Song").Select(x => new
                      {
                          title = x.Element("Title").Value,
                          genres = x.Descendants("Genre").Select(y => new {
                              genere = y.Value
                          }).ToList()
                      }).ToList();
                  }
              }
          }
          

          【讨论】:

            【解决方案6】:
            IEnumerable<string> genres = xSongs.Elements("Song")
                .Select(song => song.Element("Genres"))
                .SelectMany(genres => genres.Elements("Genre"))
                .Select(genre => genre.Value)
                .OrderBy(x => x);
            

            【讨论】:

              【解决方案7】:

              问题是您使用.Element(string) 选择单一类型,如果您不想使用.Descendants(string),则应使用.GetElements(string)

              IEnumerable<string> genres = xSongs
                  .Elements("Song")
                  .SelectMany(song => song
                      .Element("Genres")
                      .Elements("Genre")
                      .Select(genre => genre.Value));
              

              上面的linq等价于"xSongs.(many)Song.Genres.(many)Genre.Value"

              如果您更愿意使用查询语法:

              IEnumerable<string> genres = from song in xSongs.Elements("Song")
                                           let songGenres = song.Element("Genres").Elements("Genre")
                                           from genre in songGenres
                                           select genre.Value;
              

              由于您的 xml 中有多个 一对多 关系,因此您的 linq 查询中需要有多个 from

              【讨论】:

                猜你喜欢
                • 2013-10-27
                • 1970-01-01
                • 2010-11-18
                • 2013-10-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-02-22
                相关资源
                最近更新 更多