Я пытаюсь отобразить некоторую дату из некоторого 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>
Несколько вещей:
если вы используете 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")
}
XLinq
, я думаю, что проблема «пропуска» целого элемента data
может не иметь отношения к коду, который вы пробовали изначально. Если бы он пытался проанализировать элемент data
отсутствует resource
, он должен был вызвать исключение, а не «пропускать» его.
XPath
для быстрого и простого извлечения данных, но вы должны показать нам формат XML.