XElement with LINQ Select 和可选元素

本文关键字:元素 Select with LINQ XElement | 更新日期: 2023-09-27 18:32:33

我正在尝试显示从外部服务获得的某些XML中的某个日期。我正在使用 XElement,并尝试使用 LINQ select 来获取我的数据。

var xElem = XElement.Load(HttpUtility.UrlPathEncode(url));
var books = (from pubs in xElem.Elements("result")
             select new
             {
                 Id = (string)pubs.Element("data").Element("id"),
                 Title = (string)pubs.Element("data").Element("title"),
                 Year = (string)pubs.Element("data").Element("year"),
                 Resources = (string)pubs.Element("data")
                                         .Element("resource")
                                         .Element("url")
                                         .ElementValueNull(),
                 Authors= pubs.Element("data").Elements("person")
             }).ToList();
foreach (var book in books)
{
    // Put the string together with string builder....
    foreach (var person in book.Authors)
    {
        //Get the authors
    }
}

当然,我已经为ElementValueNull制作了类。

//This method is to handle if element is missing
public static string ElementValueNull(this XElement element)
{
    if (element != null)
        return element.Value;
    return "";
}
//This method is to handle if attribute is missing
public static string AttributeValueNull(this XElement element, string attributeName)
{
    if (element == null)
        return "";
    else
    {
        XAttribute attr = element.Attribute(attributeName);
        return attr == null ? "" : attr.Value;
    }
}

问题是带有其元素的资源标记并不总是存在。如果它不存在,它将跳过整个记录。有没有简单的方法可以使资源具有从我的类返回的空字符串,但仍使用 LINQ 选择添加记录?

使用 XML 进行编辑示例:

<?xml version="1.0" encoding="UTF-8"?>
<tester xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://tester.no/xmlSchema/xsd/tester.xsd">
  <generert>2014-12-01</generert>
  <result>
    <data>
      <id>297474</id>
      <person>
        <id>11690</id>
        <surname>Medel-Svensson</surname>
        <firstname>Ronnie</firstname>
      </person>
      <title>Title 1</title>
      <year>2009</year>
    </data>
  </result>
  <result>
    <data>
      <id>807059</id>
      <person>
        <id>11690</id>
        <surname>Bronskimlet</surname>
        <firstname>Hallstein</firstname>
      </person>
      <person>
        <id>328009</id>
        <surname>Kroksleiven</surname>
        <firstname>Jostein</firstname>
      </person>
      <person>
        <id>328010</id>
        <surname>Gassolini</surname>
        <firstname>Ruffino</firstname>
      </person>
      <person>
        <id>327990</id>
        <surname>von Schnellfahrer</surname>
        <firstname>Heinrich</firstname>
      </person>
      <title>Title 2</title>
      <year>2010</year>
      <resource>
        <type>
          <code>TEXT</code>
        </type>
        <url>http://www.example.com/</url>
      </resource>
    </data>
  </result>
  <result>
    <data>
      <id>1164653</id>
      <person>
        <id>11690</id>
        <surname>Bergsprekken</surname>
        <firstname>Mysil</firstname>
      </person>
      <title>Title 3</title>
      <year>2014</year>
      <resource>
        <type>
          <code>FULLTEKST</code>
        </type>
        <url>http://www.example.com/</url>
      </resource>
    </data>
  </result>
</tester>

XElement with LINQ Select 和可选元素

有几件事:

  • 如果使用 Element(..) ,则结果可能是 null 。 如果路径中缺少元素,这可能会导致空引用异常。 处理此问题的更优雅方法是使用序列并返回一个元素(如果存在),请使用 SingleOrDefault()

  • XElementXAttribute 都内置了一堆显式类型转换运算符。 这意味着您可以转换为string和各种其他基元。 由于字符串是引用类型,如果XObject为 null,它将返回 null。 在这种情况下,int等值类型会引发异常,但int?不会。

考虑到这一点,这样的事情应该可以解决您的问题。 请注意,由于"数据"是所有人共有的,因此您可以将其放在初始选择器中:

from pubs in xElem.Elements("result").Elements("data")
select new
{
    Id = (string)pubs.Element("id"),
    Title = (string)pubs.Element("title"),
    Year = (string)pubs.Element("year"),
    Resources = (string)pubs.Elements("resource")
                            .Elements("url")
                            .SingleOrDefault(),
    Authors= pubs.Elements("person")
}