【问题标题】:Getting a specific node from xml using linq使用 linq 从 xml 获取特定节点
【发布时间】:2011-08-10 15:52:08
【问题描述】:

我在 linq 查询到 xml 树时遇到了一些问题。树形结构如下所示:

<Student>
  <ID> Hello </Hello>
  <Classroom>
     <Name> 1B </Name>
     <Year> 1 </Year>
  </Classroom>
  <Classroom>
     <Name> 2B </Name>
     <Year> 2 </Year>
  </Classroom>
  <Classroom>
     <Name> 3B </Name>
     <Year> 3 </Year>
  </Classroom>
</Student>

现在这是 5 个学生条目中的一个。假设我从另一个方法传递了一个 XElement Student 节点,我想搜索一个给定 XElement Student 节点和教室名称的教室。所以我必须写一个这样的方法:

getClassRoomNode(XElement StudentNode, string classroomName)

这是我尝试过的。请让我知道我错在哪里

XElement classroom = StudentNode.Descendants("Classroom")
                                .Where(arg => arg.Element("Name").Value == classroomName)
                                .Select(arg => arg.Parent)
                                .First();

这将再次返回 StudentNode 而不是教室节点。谁能帮我解决这个问题?

【问题讨论】:

  • 您的 XML 中有错误,格式不正确的“
  • 对不起,这只是一个例子......现在修复

标签: c# linq-to-xml


【解决方案1】:

您无需选择父母,只需获取First(),甚至更好的Single() 教室。

XElement classroom = StudentNode.Descendants("Classroom")
    .Single(arg => arg.Element("Name").Value == classroomName);

我建议最好出错而不是忽略后续匹配。如果意图是匹配许多匹配中的第一个,那么显然,

XElement classroom = StudentNode.Descendants("Classroom")
    .First(arg => arg.Element("Name").Value == classroomName);

【讨论】:

    【解决方案2】:

    摆脱Select,你正在重新选择父级!

    XElement classroom = StudentNode.Descendants("Classroom").Where(arg => arg.Element("Name").Value == classroomName).First();
    

    【讨论】:

    • First() 可以替换 Where()
    【解决方案3】:

    您的代码完全按照它的要求执行:选择 name 元素的内容等于 classroomName 节点,然后选择该 节点的父节点,即 节点。

    修复:

    XElement classroom =
        StudentNode.Elements("Classroom")
                   .First(arg => (string)arg.Element("Name") == classroomName);
    

    这将返回第一个 节点,其中 name 元素的内容等于 classroomName

    【讨论】:

    • 它不会抱怨因为classroomName 不是XElement
    • @Jodrell:不,因为(string)arg.Element("Name") 元素的内容作为字符串返回。
    • 你是对的,我错过了明确的演员 msdn.microsoft.com/en-us/library/bb155263.aspx 请注意 CLS 合规性。
    【解决方案4】:

    您正在选择“课堂”节点的父节点。像这样更改查询:

    XElement classroom = StudentNode.Descendants("Classroom").First(arg => arg.Element("Name").Value == classroomName);
    

    您应该使用 FirstOrDefault 而不是使用 First 并检查 null 值以停止根据您的查询未找到 Classroom 节点时可能发生的任何异常。 (如果您在代码的其他地方处理此异常,请忽略这一点)

    Enumerable.FirstOrDefault

    【讨论】:

    • .Select(arg =&gt; arg) 仍然是多余的,为什么要包含它?
    • 另外,First() 可以替换 Where()
    【解决方案5】:

    这是因为您正在选择教室节点的父节点。只需摆脱最后一个选择器:

    XElement classroom = StudentNode.Descendants("Classroom").Where(arg => arg.Element("Name").Value == classroomName).First();
    

    或者甚至更简单,正如所指出的,将 First 和 Where 结合在一起。

    XElement classroom = StudentNode.Descendants("Classroom").First(arg => arg.Element("Name").Value == classroomName)
    

    但是,如果没有匹配,这将引发异常,另一方面,FirstOrDefault 将在不匹配时返回 null;

    XElement classroom = StudentNode.Descendants("Classroom").FirstOrDefault(arg => arg.Element("Name").Value == classroomName)
    

    【讨论】:

    • First() 可以替换 Where()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-29
    • 2019-12-03
    相关资源
    最近更新 更多