LINQ to XML查询返回错误的数据

时间:2013-08-16 08:19:40

标签: c# xml linq-to-xml

我有这个xml

<?xml version="1.0" encoding="utf-8" ?>
<Departments>
 <Department>
  <id>001</id>
  <Section>
    <SectionId>001001</SectionId>
    <Room>
      <RoomID>001001001</RoomID>
      <Owner>guest1</Owner>
    </Room>
    <Room>
      <RoomID>001001002</RoomID>
      <Owner>guest11</Owner>
    </Room>
  </Section>
  <Section>
    <SectionId>001002</SectionId>
    <Room>
      <RoomID>001002001</RoomID>
      <Owner>guest2</Owner>
    </Room>
 </Section>
</Department>
</Departments>  

这是我使用Linq to Xml的代码

var xDoc = XDocument.Load(inputUrl);

var sections = from el in xDoc.Descendants("Department")
                       where el.Element("id").Value.Equals("001")
                       select el.Element("Section");

var rooms = from el in sections
               where el.Element("SectionId").Value.Equals("001001")
               select el.Element("Room");

var roomsList = (from el in rooms
            select new Room
            {
                roomID = (string)el.Element("RoomID"),
                owner = (string)el.Element("Owner")
            }).ToList();

我的问题是我只在列表中获得一个房间,但我应该得到两个。如果这是使用LINQ到xml的正确方法,请另外建议,我对LINQ来说还不够。

5 个答案:

答案 0 :(得分:2)

sectionsrooms个查询更改为:

var sections = xDoc.Descendants("Department")
                   .FirstOrDefault(x => (string)x.Element("id") == "001")
                   .Elements("Section");

var rooms = sections.Where(x => (string)x.Element("SectionId") == "001001")
                    .Elements("Room");

通过这些,您将获得2个房间。

为什么你的代码不起作用?

  1. select el.Element("Section")仅选择section中的第一个Department元素 - 您永远无法通过section
  2. id == "001002"获得空间 {li> select el.Element("Room")rooms查询中仅返回每个匹配部分的第一个房间。

    您可以将Element更改为Elements并添加其他SelectMany(x => x)次调用,以使基于语法的查询有效:

    var sections = from el in xDoc.Descendants("Department")
                    where el.Element("id").Value.Equals("001")
                    select el.Elements("Section");
    
    var rooms = from el in sections.SelectMany(x => x)
                where el.Element("SectionId").Value.Equals("001001")
                select el.Elements("Room");
    
    var roomsList = (from el in rooms.SelectMany(x => x)
                        select new 
                        {
                            roomID = (string)el.Element("RoomID"),
                            owner = (string)el.Element("Owner")
                        }).ToList();
    

答案 1 :(得分:2)

作为其他答案的替代方案,您可以使用Extensions.XPathSelectElements Method (XNode, String)(确保将using System.Xml.XPath指令添加到文件顶部):

string 
    departmentId = "001", 
    sectionId = "001001";
var xDoc = XDocument.Load(inputUrl);
var rooms = xDoc.XPathSelectElements(
    String.Format(
        "//Department[id={0}]/Section[SectionId={1}]/Room",
        departmentId,
        sectionId))
    .Select(el => new Room
    {
        roomID = (string)el.Element("RoomID"),
        owner = (string)el.Element("Owner")
    }).ToList();

这是一个自己喜欢的问题。我觉得这写得更短更容易阅读。

答案 2 :(得分:1)

只是为了表明有很多方法可以给猫皮肤涂抹:

var xDoc = XDocument.Load(@"C:\TEST\TEST.XML");

var depts = from e in xDoc.Descendants("Department")
            where e.Element("id").Value.Equals("001")
            select e;

var sections = from e in depts.Descendants("Section")
            where e.Element("SectionId").Value.Equals("001001")
            select e;

var rooms = (from e in sections.Descendants("Room")
            select new //Room 
            {
                ID = (string)e.Element("RoomID"),
                Owner = (string)e.Element("Owner")
            }).ToList();

答案 3 :(得分:0)

如果你改变了怎么办?

select el.Element("Room");

select el.Elements("Room");

答案 4 :(得分:0)

您只在中间查询中选择一个房间,它应该是.Elements(...)(注意尾随s):

        var rooms = from el in sections
                       where el.Element("SectionId").Value.Equals("001001")
                       select el.Elements("Room");

这同样适用于您的section查询。