使用XDocument根据名称属性的值获取XML元素

19

我有一个像这样的XML结果

<response>
  <lst name="responseHeader">
    <int name="status">0</int>
    <int name="QTime">16</int>
  </lst>
  <result name="response" numFound="3" start="0" maxScore="1.0">
    <doc>
      <str name="ContaFirstname">
        firstname1                                                   
      </str>
      <str name="ContaId">6557</str>
      <str name="ContaJobTitle">Manager</str>
      <str name="ContaSurname">surname1
      </str>
    </doc>
    <doc>
      <str name="ContaFirstname">firstname2</str>
      <str name="ContaId">6203</str>
      <str name="ContaJobTitle">Director</str>
      <str name="ContaSurname">surname2</str>
    </doc>
  </result>
</response>

我想获取一个对象列表,每个对象都包含ContaFirstnameContaIdContaJobTitleContaSurname的值。

我尝试了类似这样的代码,但是结果不对,因为我得到的都是 NULL。

var test = from c in xml.Descendants("doc")
                    select new 
                    {
                        firstname = c.Element("ContaFirstname"),
                        surnmane = c.Element("ContaSurname")
                    }; 

那么如何通过名称访问这些元素?


1
你想要结果是字符串还是XElements?你已经接受的答案将给你元素。 - Jon Skeet
是的,实际上我进行了一个简单的转换以得到我想要的内容。 - kbaccouche
2个回答

32

你不希望通过名称来访问元素,因为大多数人会误解这个语句。你希望通过它们name属性的值来访问这些元素:

firstname = (string) c.Elements("str")
                      .First(x => x.Attribute("name").Value == "ContaFirstname");
//etc

由于它需要进行多次操作,因此您可能希望将其抽象为单独的方法。例如:

public static XElement ElementByNameAttribute(this XContainer container,
                                              string name)
{
    return container.Elements("str")
                    .First(x => x.Attribute("name").Value == name);
}

那么:

var test = from c in xml.Descendants("doc")
           select new 
           { 
               firstname = c.ElementByNameAttribute("ContaFirstname").Value,
               surnmane = c.ElementByNameAttribute("ContaSurname").Value
           }; 

如果您有机会为您的文档提供一个更加合理的结构,那将是更好的选择...


感谢您的回答,您说得对,那确实令人困惑。我编辑了我的问题标题以避免这种情况。 - kbaccouche
@the_ruby_racer:看看我的编辑,包括一个扩展方法,它将使您的生活比一遍又一遍地重复相同的代码更轻松。 - Jon Skeet
4
你在 First(x => x.Attribute("name").Value == name); 中忘记了一个 > 符号吗? - Ouadie
此外,将扩展添加到 XContainer 而不是 XElement 是有意义的,因为其他继承自 XContainer 的对象也可以使用它(例如 XDocument)。 - Marwie
@Marwie:嗯,我理解了。完成了。 - Jon Skeet

3
这能解决你的问题吗:
var test = from c in xml.Descendants("doc")
           select new 
           {
               firstname = c.Elements("str").First(element => element.Attribute("name").Value == "ContaFirstname"),
               surnmane = c.Elements("str").First(element => element.Attribute("name").Value == "ContaSurname")
           }; 

或者,如果你想要值(而不是XElement):

var test = from c in xml.Descendants("doc")
           select new 
           {
               firstname = c.Elements("str").First(element => element.Attribute("name").Value == "ContaFirstname").Value,
               surnmane = c.Elements("str").First(element => element.Attribute("name").Value == "ContaSurname").Value
           }; 

1
这将使属性XElement引用,这对我来说似乎很奇怪。 - Jon Skeet

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