如何在C#中使用LINQ to xml生成对象数组

时间:2014-02-15 14:05:15

标签: c# xml linq linq-to-xml

我有一个这样的对象:

public class ClientCredentials
{
    public string UserName { get; set; }

    public string Password { get; set; }

    public string Rights { get; set; }
}

和xml看起来像这样:

<?xml version="1.0" encoding="utf-8" ?> 
<users>
  <user>
      <username>playerone</username>
      <password>654321</password>
      <rights>true</rights>
  </user>
  <user>
      <username>amoreroma</username>
      <password>123456789</password>
      <rights>false</rights>
  </user>
</users>

我只想在LINQ 之后生成一个 ClientCredentials 对象列表到给定的XML

我试过这样:

XDocument document = XDocument.Load(@"path\to\file\file.xml");
    var query = document.Descendants("users").Select(s => new ClientCredentials
                    {
                        UserName = s.Element("username").Value,
                        Password = s.Element("password").Value,
                        Rights = s.Element("rights").Value
                    }).ToList();

但我收到错误引用没有设置为对象的实例

2 个答案:

答案 0 :(得分:3)

您需要Descendants("user")而不是Descendants("users")。您的usernamepasswordrights元素是user元素的子元素。不是Users元素。这就是你得到NullReferenceException.的原因你也可以使用显式强制转换来避免NullReferenceException。如果找不到任何元素,你的代码仍然会抛出异常,因为你是直接访问Value属性。

var query = document.Descendants("user").Select(s => new ClientCredentials
                {
                    UserName = (string)s.Element("username"),
                    Password = (string)s.Element("password"),
                    Rights = (string)s.Element("rights")
                }).ToList();

答案 1 :(得分:0)

这是使用查询语法表示的LINQ查询。而不是使用Descendants()方法,查询通过Root.Elements("user")包含了感兴趣元素的直接路径:

var query =
    from el in document.Root.Elements("user")
    select new ClientCredentials
        {
            UserName = (string)el.Element("username"),
            Password = (string)el.Element("password"),
            Rights = (string)el.Element("rights")
        };

为了演示此查询,我使用您提供的示例XML数据创建了一个程序。此外,您询问缺少的元素是否会生成异常。正如@ Selman22指出的那样,您可以通过删除.Value属性并使用{{1}来避免缺少元素的异常} 投。这样做会导致为缺少的元素返回空字符串。为了表明这一点,我添加了第三个(string)元素并省略了它的<user>子元素。

请参阅下面的示范程序格式化输出,然后是程序本身。

演示程序输出

<rights>

演示计划

请注意,我在查询表达式的末尾删除了UserName:[playerone] Password:[654321] Rights:[true] -- UserName:[amoreroma] Password:[123456789] Rights:[false] -- UserName:[norights] Password:[20140215] Rights:[] -- ,因为这里不需要它。 (这意味着ToList()只是query。)

IEnumerable