【问题标题】:Linq to XML Element inside ElementLinq to XML Element inside Element
【发布时间】:2017-10-06 06:15:31
【问题描述】:

我编写了一个读取 XML 并将信息写入对象的方法。 XML 包含带有信息的元素,但是一些信息被封装了,我不知道如何从中获取信息。 XML 包含大约 200 个“结果”。

XML 结构

 <result id="xxxxx">
      <name>Name</name>
      <age>25</age>
      <info>
           <x>Some text</x>
           <y>More Text</y>
      </info>
 </result>

代码

XDocument rootDocument = XDocument.Load(file);
var xy = from r in rootDocument.Descendants("result")
        select new
        {
            Name = r.Element("name")
            Age = r.Element("age"),
            x = r.Element("info").Element("x"),
            y = r.Element("info").Element("y"),
        };

foreach (var r in xy)
{
    Object o = new Object()
    {
        Name = r.Name,
        Age = r.Age,
        x = r.x,
        y = r.y
    };
}

错误 对象引用未设置为对象的实例。

错误发生在该行

  x = r.Element("info")...

还有下一个。

【问题讨论】:

  • 您是否收到错误或警告?我没有看到问题(Object o = new Object(); 行的语法错误除外)。
  • 是的,它已被编辑。我不知道为什么。我再补充一下。
  • 是否存在info 没有xy 值的XML 节点?
  • 总是一样的。 X 和 Y 节点可以为空,但不能不存在。
  • 查看Jon's answer here。它描述了一种安全的空值检查方法。基本上像x = r.Element("info") != null ? r.Element("info").Element("x"), : null 这样的东西也可以工作。

标签: c# xml linq-to-xml


【解决方案1】:

您可以执行以下操作:

var query = from r in rootDocument.Descendants("result")
            select new
            {
                Name = (string)r.Element("name"),
                Age = (int?)r.Element("age"),
                x = (string)r.Elements("info").Elements("x").SingleOrDefault(),
                y = (string)r.Elements("info").Elements("x").SingleOrDefault(),
            };
var resultList = query.ToList();

注意事项:

  • 一旦您选择了具有原始值的XElement,您可以使用XElementexplicit casting operators 之一将元素转换为ac# 原始值,例如stringint?,如下所示:

    Name = (string)r.Element("name")
    Age = (int?)r.Element("age")
    
  • 您看到对象引用未设置为对象实例的事实异常表明元素意外丢失。如果&lt;result&gt; 元素之一缺少&lt;info&gt; 子元素,则很容易发生这种情况。表达式

    r.Elements("info").Elements("x")
    

    返回名为&lt;x&gt; 的子元素的所有 个子元素&lt;info&gt;。然后SingleOrDefault() 返回该序列的唯一元素,如果序列为空,则返回默认值。这可以防止出现&lt;info&gt; 丢失的情况。

  • 同样,如果缺少 &lt;age&gt; 元素,尝试将其强制转换为 int 将引发空引用异常,因为 int 是值类型。转换为 int? 会返回 null 而不是抛出异常。

  • 最终的ToList() 评估查询并在列表中返回结果。

示例fiddle

【讨论】:

  • 完美解释和采样。谢谢!
猜你喜欢
  • 1970-01-01
  • 2020-03-03
  • 2017-07-13
  • 1970-01-01
  • 2023-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
相关资源
最近更新 更多