C# LINQ 将 XML 转换为列表

4
我想知道是否有一种方法可以使用linq to xml将结果列表转化为一个列表。例如,如果我有以下xml:
<?xml version="1.0"?>
<Sports xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <SportPages>
        <SportPage type="test">
            <LinkPage>
                <IDList>
                    <string>1</string>
                    <string>2</string>
                </IDList>
            </LinkPage>
        </SportPage>
    </SportPages>
</Sports>

我该如何从IDList中获取字符串列表?

我对linq to xml相当陌生,所以我只是尝试了一些东西,目前我到了这个地步:

var IDs = from sportpage in xDoc.Descendants("SportPages").Descendants("SportPage")
                      where sportpage.Attribute("type").Value == "Karate"
                      select new
                      {
                          ID = sportpage.Element("LinkPage").Element("IDList").Elements("string")
                      };

但是变量混乱不堪,很难看懂。有没有办法可以从中获取字符串列表呢?

谢谢

5个回答

6

这个查询是有效的 - 经过测试和验证:

var ID2 = (from sportpage in xDoc.Descendants("SportPages").Descendants("SportPage")
           where sportpage.Attribute("type").Value == "Karate"
           select sportpage)
          .Descendants("LinkPage")
          .Descendants("IDList")
          .Elements("string")
          .Select(d => d.Value)
          .ToList();

给我一个包含两个字符串 "1" 和 "2" 的列表。

1
如果你的 SportPage 元素没有 type 属性,这将引发一个对象空引用异常。 - Matthew Whited
已解决,我删除了LinkPage和SportPages的后代,因为通过其他回复,我发现它会自动搜索 :) 所以非常感谢你们所有人! - WtFudgE

2
var myStrings = xDoc.Descendants("SportPage")
                    .Where(d => d.Attribute("type").Value == "Karate")
                    .Descendants("IDList")
                    .Descendants("string")
                    .Select(d => d.Value);

查看您的字符串:

xDoc.Descendants("SportPage")
    .Descendants("IDList")
    .Where(d => d.Attribute("type").Value == "Karate")
    .Descendants("string")
    .Select(d => d.Value)
    .ToList()
    .ForEach(Console.WriteLine);

1
但是你忽略了条件sportpage.Attribute("type").Value == "Karate" - marc_s

1

你是指这个吗?

List<string> IDs = xDoc.Descendants("SportPages").Descendants("SportPage")
    .Where( anySportPage => anySportpage.Attribute("type").Value == "Karate" )
    .Select( karateSportPage => karateSportpage.Element("LinkPage").Element("IDList").Elements("string"))
    .ToList();

我得到了以下错误信息:"错误:无法隐式转换类型'System.Collections.Generic.List<System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>>'为'System.Collections.Generic.List<string>'"。 - marc_s
你需要更加注意大小写:例如,这个语句是不起作用的:.Where( anySportPage => anySportpage. - 你需要在两种情况下使用相同的大小写!anySportPage vs. anySportpage - 不相同! - marc_s
源于没有测试和假设我知道来自 .Elements() 的内容。(使用 var IDs 可以工作,但我从来不喜欢 var。)感谢您的更正和写下正确答案。 :) - ANeves

0

我认为你觉得"var"混乱的原因是你在选择语句中使用"new"创建了匿名类型。如果你只选择一个想要的项目,那么"var"就不会是一个匿名类型。

例如:

select sportpage.Element("LinkPage").Element("IDList").Elements("string");

然而,我更喜欢使用像这样的点符号来做到这一点。
List<string> ids = xDoc.Elements("SportPages").Elements("SportPage").Where(sportPage => sportPage.Attribute("type").Value == "Karate").Elements("LinkPage").Elements("IDList").Elements("string").Select(id => id.Value).ToList();

0
你遇到的最大问题是没有从返回的元素集中获取 .Value。但这里有另一种方法可以做到。
var ids = from sportPage in xDoc.Descendants("SportPage")
          let attrib = sportPage.Attribute("type")
          where attrib != null
          let type = attrib.Value
          where !string.IsNullOrEmpty(type)
              && type == "Karate"
          from id in sportPage.Descendants("IDList").Elements()
          select id.Value;

这种方法有点懒。如果您有一个明确的模式,您可以在问题示例中使用相同的内容。您只需要在选择语句的末尾添加“.Value”。 - Matthew Whited

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接