XElement с LINQ Select и дополнительными элементами

1

Я пытаюсь отобразить некоторую дату из некоторого XML, который я получаю от внешней службы. Я использую XElement, и я пытаюсь использовать LINQ для получения моих данных.

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?

EDIT с примером 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>
  • 0
    Вы можете использовать XPath для быстрого и простого извлечения данных, но вы должны показать нам формат XML.
  • 0
    Да, конечно, я мог бы использовать XPath, но я хотел попробовать это с помощью LINQ.
Теги:
linq

1 ответ

1
Лучший ответ

Несколько вещей:

  • если вы используете Element(..), тогда результат может быть null. Это может привести к исключению нулевой ссылки, если в вашем пути отсутствуют элементы. Более элегантный способ справиться с этим будет заключаться в использовании последовательностей и возврате элемента, если он присутствует с помощью SingleOrDefault()

  • И XElement и XAttribute имеют кучу явных операторов преобразования типов, которые встроены. Это означает, что вы можете отличить string и другие примитивы. Поскольку string является ссылочным типом, он возвращает null если XObject 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")
}
  • 0
    Приветствия Чарльз. Я вставляю данные в путь перед выбором, и он выглядит чище. Однако, пробуя ваш код с использованием SingleOrDefault, вы получите только 2 записи из 3, которые я пробую. Оставив запись без ресурса.
  • 0
    Не могли бы вы включить образец XML-файла, который вы анализируете? Хотя я думаю, что я мог упростить код XLinq , я думаю, что проблема «пропуска» целого элемента data может не иметь отношения к коду, который вы пробовали изначально. Если бы он пытался проанализировать элемент data отсутствует resource , он должен был вызвать исключение, а не «пропускать» его.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню