我如何获得数组的数组使用Linq到XML

本文关键字:数组 Linq XML 何获得 | 更新日期: 2023-09-27 18:15:31

如何获得所有类型的列表?现在我只能得到每首歌的第一种类型。

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

谢谢。

我如何获得数组的数组使用Linq到XML

由于您没有执行任何过滤器,您可以直接使用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来代替。

检查这个答案,了解为什么我使用Descendants而不是Elements

如果您不需要任何额外的类型过滤,您可以轻松地获得文档中的所有类型,如下所示:

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

注意:XPathSelectElements是一个扩展方法,为了使用这个方法,请确保在源代码中使用System.Xml.XPath命名空间。

如果您的xml还包含用于歌曲以外元素的"Genre"节点:

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

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

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

试试这个

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();
        }
    }
}
IEnumerable<string> genres = xSongs.Elements("Song")
    .Select(song => song.Element("Genres"))
    .SelectMany(genres => genres.Elements("Genre"))
    .Select(genre => genre.Value)
    .OrderBy(x => x);

问题是你选择使用.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