如何获取所有类型的列表? 现在我只得到每首歌的第一个类型。
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
感谢。
答案 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);