Избегание воздействия NullReferenceException при использовании LINQ to XML - PullRequest
3 голосов
/ 28 ноября 2010

Я использую цепочку обращений к методу XElement.Element(), чтобы детализировать XML-документ и извлечь значение атрибута:

XElement root = ...;
XNamespace ns = "...";
var firstName = 
  root
    .Element(ns + "Employee")
    .Element(ns + "Identity")
    .Element(ns + "Name")
    .Attribute(ns + "FirstName");

Однако, поскольку входящий документ не был проверен схемой, возможно, что искаженный документ вызовет NullReferenceException, если какой-либо из ожидаемых промежуточных элементов не существует.

Есть ли способ избежать этого риска при сохранении краткости кода?

Я могу обернуть приведенный выше код в обработчик для NullReferenceException, однако это кажется неправильным и также не будет конкретно указывать, где произошел сбой. Создание информационного сообщения об ошибке может быть ручным, утомительным, подверженным ошибкам и опасным для обслуживания.

Должен ли я вместо этого использовать XPath , чтобы я мог проверить нулевой возврат и затем легко создать сообщение об ошибке, указывающее, что выражение XPath не может быть разрешено?

Ответы [ 2 ]

7 голосов
/ 28 ноября 2010

Один из вариантов - использовать Elements() вместо Element() - что приведет к пустой последовательности, если элемент не найден.Используя методы расширения в Расширения , вы можете перейти от последовательности элементов к последовательности элементов - и то же самое для атрибутов.Итак:

var firstName = 
  root
    .Elements(ns + "Employee")
    .Elements(ns + "Identity")
    .Elements(ns + "Name")
    .Attributes(ns + "FirstName")
    .FirstOrDefault();

Там есть разница между двумя фрагментами, имейте в виду - это найдет первый соответствующий атрибут, даже если он прибывает из (скажем) первого элемента Name в пределахтретий элемент Identity во втором элементе Employee.Это может или не может быть проблемой для вас.

(Просто чтобы проверить, действительно ли вам нужно пространство имен для атрибута? В отличие от элементов, атрибуты не наследуют пространство имен «по умолчанию». Это более редкое для использованияатрибуты в пространствах имен, чем в элементах.)

1 голос
/ 28 ноября 2010

Вы можете определить метод расширения en, чтобы обернуть нулевое обнаружение.Примерно так, например:

public static class XmlExtender
{
   public static XAttribute AttributeOrDefault(this XElement el, XName name, string defValue)
   {
      var v = el.Attribute(name);
      return v == null ? new XAttribute(name, defValue) : v;
   }

   public static string AttributeValue(this XElement el, XName name, string defValue)
   {
      var v = el.Attribute(name);
      return v == null ? defValue : v.Value;
   }
}

, который затем можно использовать так:

var firstName = root.ELement("elname")
                    .AttributeOrDefault("attrName", "N/A").Value;

или вот так:

var firstName = root.Element("elname")
                    .AttributeValue("attrName", "N/A");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...