2010-11-07 3 views
1

Давайте предположим, что файл XML с именем data.xml с следующим содержанием:C# LINQ к XML-запроса помощи

<root> 
<record> 
<id>1</id> 
<name>test 1</name> 
<resume>this is the resume</resume> 
<specs>these are the specs</specs> 
</record> 
<record> 
<id>2</id> 
<name>test 2</name> 
<resume>this is the resume 2</resume> 
</record> 
<record> 
<id>3</id> 
<name>test 3</name> 
<specs>these are the specs 3</specs> 
</record> 
</root> 

Мне нужно найти все записи, в которых любое из этих полей (ID, имя, резюме или спецификации) содержит заданное значение. Я создал этот код

XDocument DOC = XDocument.Load("data.xml"); 
IEnumerable<ProductRecord> results = from obj in DOC.Descendants("record") 
    where 
obj.Element("id").Value.Contains(valueToSearch) || 
obj.Element("name").Value.Contains(valueToSearch) || 
obj.Element("resume").Value.Contains(valueToSearch) || 
obj.Element("specs").Value.Contains(valueToSearch) 
    select new ProductRecord { 
ID = obj.Element("id").Value, 
Name = obj.Element("name").Value, 
Resume = obj.Element("resume").Value, 
Specs = obj.Element("specs").Value 
    }; 

Этот код выдает ошибку NullReference, так как не все записи имеют все поля. Как проверить, имеет ли текущая запись данный элемент, прежде чем я определяю условие для применения? Ex. Запись [@ ID = 3] не имеет резюме.

Заранее спасибо

ответ

0

Вы можете написать метод расширения, который, как ниже:

public static class XMLExtension 
{ 
    public static string GetValue(this XElement input) 
    { 
     if (input != null) 
      return input.Value; 
     return null; 
    } 

    public static bool XMLContains(this string input, string value) 
    { 
     if (string.IsNullOrEmpty(input)) 
      return false; 
     return input.Contains(value); 
    } 
} 

и использовать его, как показано ниже:

IEnumerable<ProductRecord> results = from obj in DOC.Descendants("record") 
               where 
              obj.Element("id").GetValue().XMLContains(valueToSearch) || ... 
+0

Большое спасибо! – adaoss

0

Вы получаете NullReferenceException, потому что вы пытаетесь получить доступ к значению некоторых узлов, которые не существуют для каждого recordspecs как. Вы должны проверить, obj.Element("specs") != null перед вызовом .Value на нем.

В качестве альтернативы вы можете использовать XPath:

var doc = XDocument.Load("test.xml"); 
var records = doc.XPathSelectElements("//record[contains(id, '2') or contains(name, 'test') or contains(resume, 'res') or contains(specs, 'spe')]"); 
0

Сначала я удивлен, что это не сбой, потому что вы не используете пространство имен. Может быть, C# 4.0 обошел это?

Во всяком случае попробуйте

obj.Descendants("id").Any() ? root.Element("id").Value : null 

То есть:

select new ProductRecord { 
    ID = obj.Descendants("id").Any() ? root.Element("id").Value : null, 
    Name = obj.Descendants("name").Any() ? root.Element("name").Value : null, 
    Resume = obj.Descendants("resume").Any() ? root.Element("resume").Value : null 
    Specs = obj.Descendants("specs").Any() ? root.Element("specs").Value : null 
}; 
+0

проблема не в select, я обошел это с помощью этого кода Specs = (string) obj.Element ("Specs") ?? "N/A". Основная проблема заключается в том, где clause ... – adaoss

+0

Попробуйте использовать ту же логику? (строка) obj.Element ("Specs") ?? правда. Как будто если объект не существует, вы хотите принять его как истинный вариант для этой записи. – Kamal