带有LINQ Select和可选元素的XElement

时间:2014-12-01 12:47:03

标签: c# xml linq

我试图从外部服务获得的某些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>

1 个答案:

答案 0 :(得分:1)

有几件事:

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

  • 返回元素(如果存在)
  • XElementXAttribute都内置了一堆显式类型转换运算符。这意味着您可以转换为string和其他各种基元。由于string是引用类型,如果null为null,它将返回XObject。在这种情况下,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")
}