时间:2019-05-17 标签:c#linqtoxmlqueryhelp

发布于 2024-10-01 00:35:17 字数 1256 浏览 2 评论 0原文

让我们假设一个名为 data.xml 的 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 错误,因为并非所有记录都具有所有字段。 在定义要应用的条件之前,如何测试当前记录是否具有给定元素?前任。记录[@ID=3]没有简历。

提前致谢

Lets assume a xml file named data.xml with following content:

<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>

I need to search all records where any of these fields (id, name, resume or specs) contains a given value. I've created this code

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
     };

This code throws an error of NullReference since not all records have all fields.
How can i test if current record has a given element before i define a condition to apply? Ex. Record[@ID=3] has no resume.

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

木格 2024-10-08 00:35:17

您可以编写如下所示的扩展方法:

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) || ...

You can write an extension method which is like bellow:

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);
    }
}

and use it as below:

IEnumerable<ProductRecord> results = from obj in DOC.Descendants("record")
                                                 where
                                            obj.Element("id").GetValue().XMLContains(valueToSearch) || ...
喜爱纠缠 2024-10-08 00:35:17

您收到 NullReferenceException 是因为您尝试访问每个 record 中不存在的某些节点的值,例如 specs。在调用 .Value 之前,您需要检查 obj.Element("specs") != null 是否为空。

作为替代方案,您可以使用 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')]");

You are getting a NullReferenceException because you are trying to access the value of some nodes that don't exist for each record like specs. You need to check whether obj.Element("specs") != null before calling .Value on it.

As an alternative you could use 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')]");
双马尾 2024-10-08 00:35:17

首先,我很惊讶它没有崩溃,因为您没有使用命名空间。也许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
};

First I'm amazed that it's not crashing because you're not using the Namespace. Maybe c#4.0 has bypassed this?

Anyway try

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

That is:

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
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文