2010-01-18 142 views
3

我想从XML文件中提取信息到使用LINQ to XML的对象中。尽管我可以返回文档和部分Id属性,但我无法访问每个部分元素的Items,它将返回文档中所有项目的IEnumerable。我知道这是正确的,因为我打电话给后裔,但我努力让它只返回每个部分元素的子项。任何人都可以帮忙吗?LINQ to XML选择子元素

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")); 
     } 
    } 
} 
+1

我对目标有点不清楚。您的匿名对象由文档ID,文档中的所有部分以及文档所有部分中的所有项目组成。如果您试图将XML层次结构重建为匿名对象,那么您将需要多个查询。为什么不在这种情况下使用XML? – womp 2010-01-18 23:01:50

回答

6

你有一些小的错别字,在属性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" 
ItemId: id="1.1.1" 
ItemId: id="1.1.2" 
ItemId: id="1.1.3" 
SectionId: id="1.2" 
ItemId: id="1.2.1" 
ItemId: id="1.2.2" 
+0

抱歉有关拼写错误,但仍然不能解决问题。我试图达到的目标是只返回每个部分的子项目。 – Cragly 2010-01-19 08:46:31

+0

@Cragly,我只是重写了我的答案,看看 – 2010-01-19 10:50:24

+0

非常好!奇迹般有效。这样一个简单的修复。由于花了很长时间才看到这棵树,所以一定不能看到树木。好人。 – Cragly 2010-01-19 11:00:45

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项containes XElement s的相关项目。

+0

感谢这篇文章,但我希望能够访问那些包含项目XElements并将它们分配给对象的Items属性,以便获取与其特定部分关联的项目的IEnumerable 。 – Cragly 2010-01-19 08:44:18

+0

你能举一个你想要的数据结构的例子吗?为什么选择XElement而不是类型?!?! – salgo60 2010-01-19 13:23:38