C# проверьте наличие элемента при использовании LINQ to XML

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

XML:

<?xml version="1.0" encoding="utf-8" ?>
<customers>
  <customer>
    <id>1</id>
    <name>Blah-face</name>
    <Type>1</Type>
  </customer>
  <customer>
    <id>2</id>
    <name>Blah-face-2</name>
    <Type>2</Type>
  </customer>
  <customer>
    <id>3</id>
    <name>Blah-face-3</name>
    <Type>1</Type>
    <SuperType>1</SuperType>
  </customer>
</customers>

C#:

XDocument linquee = XDocument.Load(path);

var superType = (from c in linquee.Descendants("customer")
                 where (c.Element("SuperType").Value == "1")
                 select c).ToList();

это приводит к нулевой ошибке - нужно ли добавлять элемент "SuperType" к каждому клиенту перед ним с нулевым значением, или есть обходной путь, который означал бы, что мне не нужно это делать?

Ура!

6 ответов


попробуйте это:

var superType = (from c in from c in linquee.Descendants("customer")
                 where (string) c.Element("SuperType") == "1"
                 select c).ToList();

в основном, если вы бросили null XElement ссылка string, вы получите нулевую ссылку (которую вы можете сравнить с "1").

альтернативой было бы бросить к int? который (IIRC) вернет null int? значение, если элемент отсутствует, но go bang, если он присутствует, но не числовой:

var superType = (from c in from c in linquee.Descendants("customer")
                 where (int?) c.Element("SuperType") == 1
                 select c).ToList();

вы должны иметь возможность просто добавить проверку на null

where c.Element("SuperType") != null 
&& [your other criteria]

вы пробовали проверить, если SuperType элемент существует, прежде чем пытаться прочитать его?

...
where (c.Element("SuperType") != null && c.Element("SuperType").Value == "1")
...

Я бы сделал так:

var superType = linquee.Descendants("customer").
    Where(c => c.Element("SuperType") != null 
        && c.Element("SuperType").Value == "1");

также должен быть в состоянии очистить этот вид вещей с расширениями, что-то вроде..

public string Element_valStr(XElement xElm, string xName)
{
    if (xElm.Element(xName) == null) return string.empty;
    return xElm.Element(xName).Value;
}

а потом просто:

var superType = (from c in linquee.Descendants("customer")  
                  where (c.Element_valStr("SuperType") == "1")
                  select c).ToList();

Я нашел хорошее решение, используя Any () в сочетании с условным оператором:

result = entry.Elements(ArbitraryElement).Any() ? (entry.Element(ArbitraryElement).Attributes(ArbitraryAttribute).Any() ? entry.Element(ArbitraryElement).Attribute(ArbitraryAttribute).Value : "-1") : "-1"

трюк заключается в использовании элементов () вместе с любым (), чтобы проверить, существует ли элемент (то же самое для атрибутов ())

Итак, для этого примера это будет что-то вроде этого:

var superType = from c in linquee.Descendants("customer")  
                select c.Elements("SuperType").Any() ? c.Element("SuperType").Value : "0";