包含 Linq to XMLWhere 子句中的功能

发布于 2024-11-13 10:25:39 字数 1104 浏览 2 评论 0原文

我在使用 Linq to XML 中的 where 子句的 .Contains() 函数时遇到意外行为。它的功能似乎类似于字符串函数中的“==”而不是 Contains() 。

示例:

var q = from sr in SearchResults.Descendants("Result")
    where _filters.Contains((string)sr.Element("itemtype"))
    orderby (string)sr.Element("ipitemtype") ascending
    select new SearchItem
    {
        //Create Object
        ID = (string)sr.Element("blabla"),
    }

_filters 是字符串列表。假设它包含 3 个值:

_filters[0] = "videos";
_filters[1] = "documents";
_filters[2] = "cat pictures";

则查询可以正常工作

<itemtype>videos</itemtype> 

现在发生的情况是,如果是 XML 节点,

。但是,如果节点是

<itemtype>videos mission critical document advertising</itemtype>, 

IEnumerable 返回空白,这对我来说意味着操作数的功能类似于“==”而不是“Contains()”。

知道我做错了什么吗?

dtb 的获胜答案:

替换

where _filters.Contains((string)sr.Element("itemtype"))

where _filters.Any(filter => ((string)sr.Element("itemtype")).Contains(filter))

I'm having unexpected behavior with the .Contains() function of the where clause in Linq to XML. It seems to be functioning like "==" not Contains() in the string function.

Example:

var q = from sr in SearchResults.Descendants("Result")
    where _filters.Contains((string)sr.Element("itemtype"))
    orderby (string)sr.Element("ipitemtype") ascending
    select new SearchItem
    {
        //Create Object
        ID = (string)sr.Element("blabla"),
    }

_filters is a list of strings. Let's say it contains 3 values:

_filters[0] = "videos";
_filters[1] = "documents";
_filters[2] = "cat pictures";

What happens now, is that the Query works perfectly if

<itemtype>videos</itemtype> 

is the XML node.

However, if the node is

<itemtype>videos mission critical document advertising</itemtype>, 

the IEnumerable returns blank, which to me says the operand is functioning like "==" not "Contains()".

Any idea what I'm doing wrong?

Winning answer from dtb:

replace

where _filters.Contains((string)sr.Element("itemtype"))

with

where _filters.Any(filter => ((string)sr.Element("itemtype")).Contains(filter))

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

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

发布评论

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

评论(3

丿*梦醉红颜 2024-11-20 10:25:39

试试这个:

_filters.Any(s => ((string)sr.Element("itemtype") ?? "").Contains(s))

通过这种方式,您可以检查元素的值是否包含 _filters 中的任何字符串。使用 null 合并运算符可确保当 itemtype 节点不存在时不会抛出 NullReferenceException,因为它被替换为空字符串。

另一种方法是使用 let 并过滤掉空值:

var q = from sr in SearchResults.Descendants("Result")
        let itemtype = (string)sr.Element("itemtype")
        where itemtype != null &&
              _filters.Any(filter => itemtype.Contains(filter))
        orderby (string)sr.Element("ipitemtype") ascending
        select new SearchItem
        {
            //Create Object
            ID = (string)sr.Element("blabla")
        }

请注意,String.Contains 区分大小写。因此,对“videos”的检查不会与大写“V”的“Videos”匹配。要忽略大小写,您可以按以下方式使用 String.IndexOf

_filters.Any(filter => itemtype.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) >= 0)

Try this:

_filters.Any(s => ((string)sr.Element("itemtype") ?? "").Contains(s))

This way you're checking that the element's value contains any of the strings in _filters. The use of the null coalescing operator ensures a NullReferenceException isn't thrown when the itemtype node doesn't exist since it is replaced with an empty string.

The other approach is to use let and filter out the nulls:

var q = from sr in SearchResults.Descendants("Result")
        let itemtype = (string)sr.Element("itemtype")
        where itemtype != null &&
              _filters.Any(filter => itemtype.Contains(filter))
        orderby (string)sr.Element("ipitemtype") ascending
        select new SearchItem
        {
            //Create Object
            ID = (string)sr.Element("blabla")
        }

Note that String.Contains is case sensitive. So a check for "videos" won't match on "Videos" with a capital "V". To ignore case you can use String.IndexOf in this manner:

_filters.Any(filter => itemtype.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) >= 0)
梓梦 2024-11-20 10:25:39

您正在检查数组_filters是否有一个值为“videos Mission Critical Document Advertising”的元素(事实并非如此),而不是如果“videos任务关键文档广告” 包含 _filters 中的任何元素。

试试这个:

where _filters.Any(filter => ((string)sr.Element("itemtype")).Contains(filter))

You are checking if the array _filters has an element with the value "videos mission critial document advertising" (which is not the case), rather than if "videos mission critial document advertising" contains any of the elements in _filters.

Try this:

where _filters.Any(filter => ((string)sr.Element("itemtype")).Contains(filter))
女中豪杰 2024-11-20 10:25:39

问题是您对 包含方法有效。 (另请参阅 String.Contains() 文档< /a> 如果“序列包含特定元素”,则 contains 方法返回 true 在您描述的示例中,_filters 数组和 itemtype 文本都包含字符串 <。 code>video,但两者都不包含彼此。更合适的测试是使用以下扩展方法:

public static class ContainsAnyExtension
{
    public static bool ContainsAny<T>(this IEnumerable<T> enumerable, params T[] elements)
    {
        if(enumerable == null) throw new ArgumentNullException("enumerable");
        if(!enumerable.Any() || elements.Length == 0) return false;
        foreach(var element in elements){
           if(enumerable.Contains(element)){
               return true;
           }
        }
        return false;
    }
}

因此,正确的 LINQ 查询将是:

var q = from sr in SearchResults.Descendants("Result")
        where ((string)sr.Element("itemtype")).ContainsAny(_filters)
        orderby ((string)sr.Element("ipitemtype")) ascending
        select new SearchItem
        {
            ID = sr.Element("blabla").Value
        };

查看这篇文章也可能会有所帮助:如何使用 LINQ Contains(string[]) 而不是 Contains(string)< /a>,它类似,但专门针对 String.Contains 方法而不是 Enumerable.Contains 扩展。

The problem is that you are making false assumptions about the way the Contains method works. (Also see the String.Contains() documentation The contains method returns true if "a sequence contains a specific element". In the example you described, both the _filters array and the itemtype text contains the string videos, but neither contain each other. A more appropriate test would be to use the following extension method:

public static class ContainsAnyExtension
{
    public static bool ContainsAny<T>(this IEnumerable<T> enumerable, params T[] elements)
    {
        if(enumerable == null) throw new ArgumentNullException("enumerable");
        if(!enumerable.Any() || elements.Length == 0) return false;
        foreach(var element in elements){
           if(enumerable.Contains(element)){
               return true;
           }
        }
        return false;
    }
}

So, your correct LINQ query would be:

var q = from sr in SearchResults.Descendants("Result")
        where ((string)sr.Element("itemtype")).ContainsAny(_filters)
        orderby ((string)sr.Element("ipitemtype")) ascending
        select new SearchItem
        {
            ID = sr.Element("blabla").Value
        };

It may also be helpful to review this post: How do I use LINQ Contains(string[]) instead of Contains(string), which is similar but specifically targets the String.Contains method instead of the Enumerable.Contains extension.

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