c # linq to xml help help - PullRequest
       10

c # linq to xml help help

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

Предположим, что xml-файл с именем data.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>

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

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] не имеет резюме.

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

Ответы [ 3 ]

0 голосов
/ 07 ноября 2010

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

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 голосов
/ 07 ноября 2010

Во-первых, я поражен тем, что он не падает, потому что вы не используете пространство имен.Может быть, 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 голосов
/ 07 ноября 2010

Вы получаете исключение NullReferenceException, поскольку пытаетесь получить доступ к значению некоторых узлов, которые не существуют для каждого record, например specs. Вам нужно проверить, есть ли 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')]");
...