【问题标题】:LINQ to XML Selecting Child ElementsLINQ to XML 选择子元素
【发布时间】:2023-03-06 20:05:01
【问题描述】:

我正在尝试使用 LINQ to XML 将 XML 文件中的信息提取到对象中。虽然我可以返回文档和部分 ID 属性,但我无法访问每个部分元素的项目,但它返回文档中所有项目的 IEnumerable。我知道这是正确的,因为我正在调用 Descendants,但我正在努力让它只返回每个部分元素的子项。有人可以帮忙吗?

XML 文档

<root>
<document id="1">
  <section id="1.1">
    <item id="1.1.1"></item>
    <item id="1.1.2"></item>
    <item id="1.1.3"></item>
  </section>
  <section id="1.2">
    <item id="1.2.1"></item>
    <item id="1.2.2"></item>
  </section>
</document>
</root>

LINQ 查询

XElement documentRoot = XElement.Load("document.xml");
var documents = (from docs in documentRoot.Descendants("document")
                 select new
                    {
                        Id = (string) docs.Attribute("id"),
                        Sections = docs.Elements("section"),
                        Items = docs.Elements("section").Elements("item")
                    }).ToList();

foreach(var doc in documents)
{
    foreach(var section in doc.Sections)
    {
        Console.WriteLine("SectionId: " + section.Attribute("Id"));  
        foreach(var item in doc.Items)
        {
            Console.WriteLine("ItemId: " + section.Attribute("Id"));
        }
    }
}

【问题讨论】:

  • 我对目标有点不清楚。您的匿名对象由文档 ID、文档中的所有部分以及文档所有部分中的所有项目组成。如果您尝试将 XML 层次结构重构为匿名对象,您将需要多个查询。在这种情况下,为什么不直接使用 XML?

标签: c# linq-to-xml


【解决方案1】:

您在属性Id 和项目循环处有一些小错别字。但是,如果您试图将所有部分项目放入该项目集合中,那么您在设计级别就错了,因为 Items 应该是 Section 属性,而不是 Document (因此您需要查询您的 XML两次)。

或者,您可以执行以下操作:

var documents =
    (from docs in documentRoot.Descendants("document")
     select new
     {
         Id = (string) docs.Attribute("id"),
         Sections = docs.Elements("section")
     }).ToList();

foreach (var doc in documents)
{
    foreach (var section in doc.Sections)
    {
        Console.WriteLine("SectionId: " + section.Attribute("id"));
        foreach (var item in section.Elements("item"))
        {
            Console.WriteLine("ItemId: " + item.Attribute("id"));
        }
    }
}

输出:

SectionId: id="1.1" 项目 ID:id="1.1.1" 项目 ID:id="1.1.2" 项目 ID:id="1.1.3" SectionId: id="1.2" 项目 ID:id="1.2.1" 项目 ID:id="1.2.2"

【讨论】:

  • 抱歉有错别字,但仍然没有解决问题。我想要实现的是只返回每个部分的子项。
  • @Cragly,我只是重写了我的答案,看看
  • 太棒了!奇迹般有效。如此简单的修复。一定无法看到树木的木材,因为花了这么长时间看着这棵树。好人。
【解决方案2】:

你想要一个扁平的结构吗?!?! (来自 LinqPad)

XElement documentRoot  = XElement.Parse (
@"<root> 
<document id='1'> 
  <section id='1.1'> 
    <item id='1.1.1'></item> 
    <item id='1.1.2'></item> 
    <item id='1.1.3'></item> 
  </section> 
  <section id='1.2'> 
    <item id='1.2.1'></item> 
    <item id='1.2.2'></item> 
  </section> 
</document> 
</root> 
");




var documents = (from docs in documentRoot.Descendants("section") 
                 select new 
                    { 
                        SectionId = (string) docs.Attribute("id"), 
                        Items = docs.Elements("item") 
                    }); 
 documents.Dump();

这给出了 2 个 SectionId 项目,其中包含 XElements 和相关项目。

【讨论】:

  • 感谢您的帖子,但我最理想的情况是能够访问那些包含的项目 XElements 并将它们分配给对象的 Items 属性,因此我得到一个 IEnumerable 与相关联的项目其具体部分。
  • 你能举一个你想要的数据结构的例子吗?为什么是 XElement 而不是类型?!?!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多