如何使用Linq到XML获取数组?

时间:2022-07-12 21:15:25

How I can get a list of all genres? Now I only get the first genre of each song.

我怎样才能得到所有流派的列表?现在我只知道每首歌的第一种类型。

XML file:

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# code:

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

Result:

结果:

Pop
Rock

But I need:

但我需要:

Rock
American
Pop
Unplugged

Thanks.

谢谢。

7 个解决方案

#1


3  

Since you are not performing any filters, you can directly use Descendants like this:-

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

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

Or if you prefer query syntax:-

或者如果你喜欢查询语法:-

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

You need to import using System.Linq; for this.This will produce the outpu you expect i.e. Rock American Pop Unplugged even though it is not ordered. You can always use order by caluse for that.

您需要使用System.Linq导入。对于这个。这将产生你所期望的outpu,即摇滚美国流行的不插电,即使它没有被订购。你可以用caluse的顺序来做这个。

Check this answer to understand why I am using Descendants instead of Elements.

检查这个答案,以理解为什么我使用后代而不是元素。

#2


1  

If you don't need any additional filtering of genres, you can easily get all the genres in document like this:

如果你不需要任何额外的体裁筛选,你可以很容易地得到所有体裁像这样的文件:

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

Note: XPathSelectElements is an extension method, make sure you're using System.Xml.XPath namespace in your sourcecode in order to use this method.

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

#3


1  

In case your xml also contains "Genre" nodes for elements other than songs:

如果您的xml也包含除歌曲之外的元素的“类型”节点:

XDocument doc = XDocument.Parse(xml);

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

#4


0  

Assuming you need ordered list of genre for each song. You can try below code.

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

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


0  

Try this

试试这个

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


0  

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

#7


0  

The problem is you are selecting a single genre using .Element(string), you should use .GetElements(string) if you dont wanna use .Descendants(string):

问题是你正在使用。element (string)选择一个类型,如果你不想使用。descendants (string):

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

The linq above is equivalent to "xSongs.(many)Song.Genres.(many)Genre.Value"

上面的linq相当于“xSongs.(许多)歌曲。类型。(many)Genre.Value”

And if you rather use query syntax:

如果你更喜欢使用查询语法:

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

Since you have more than one one-to-many relation in your xml, you need to have more than one from in your linq query.

由于在xml中有多个一对多关系,所以在linq查询中需要多个关系。

#1


3  

Since you are not performing any filters, you can directly use Descendants like this:-

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

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

Or if you prefer query syntax:-

或者如果你喜欢查询语法:-

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

You need to import using System.Linq; for this.This will produce the outpu you expect i.e. Rock American Pop Unplugged even though it is not ordered. You can always use order by caluse for that.

您需要使用System.Linq导入。对于这个。这将产生你所期望的outpu,即摇滚美国流行的不插电,即使它没有被订购。你可以用caluse的顺序来做这个。

Check this answer to understand why I am using Descendants instead of Elements.

检查这个答案,以理解为什么我使用后代而不是元素。

#2


1  

If you don't need any additional filtering of genres, you can easily get all the genres in document like this:

如果你不需要任何额外的体裁筛选,你可以很容易地得到所有体裁像这样的文件:

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

Note: XPathSelectElements is an extension method, make sure you're using System.Xml.XPath namespace in your sourcecode in order to use this method.

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

#3


1  

In case your xml also contains "Genre" nodes for elements other than songs:

如果您的xml也包含除歌曲之外的元素的“类型”节点:

XDocument doc = XDocument.Parse(xml);

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

#4


0  

Assuming you need ordered list of genre for each song. You can try below code.

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

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


0  

Try this

试试这个

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


0  

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

#7


0  

The problem is you are selecting a single genre using .Element(string), you should use .GetElements(string) if you dont wanna use .Descendants(string):

问题是你正在使用。element (string)选择一个类型,如果你不想使用。descendants (string):

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

The linq above is equivalent to "xSongs.(many)Song.Genres.(many)Genre.Value"

上面的linq相当于“xSongs.(许多)歌曲。类型。(many)Genre.Value”

And if you rather use query syntax:

如果你更喜欢使用查询语法:

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

Since you have more than one one-to-many relation in your xml, you need to have more than one from in your linq query.

由于在xml中有多个一对多关系,所以在linq查询中需要多个关系。