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

时间:2015-10-01 07:37:11

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

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

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

感谢。

7 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

如果您不需要任何其他类型的过滤,您可以轻松获取文档中的所有类型:

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

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

答案 2 :(得分:1)

如果您的xml还包含&#34;类型&#34;歌曲以外的元素的节点:

XDocument doc = XDocument.Parse(xml);

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

答案 3 :(得分:0)

问题是您使用.Element(string)选择单一类型,如果您不想使用.GetElements(string),则应使用.Descendants(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

答案 4 :(得分:0)

假设您需要每首歌曲的有序列表。您可以尝试以下代码。

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)

试试这个

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