繁体   English   中英

包含 Linq 到 XML Where 子句中的功能

[英]Contains functionality in Linq to XML Where Clause

我在 Linq 到 XML 的 where 子句的它的功能似乎类似于字符串 function 中的“==”not 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";

现在发生的情况是,如果 Query 完美运行

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

尝试这个:

_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区分大小写。 因此,对“视频”的检查不会与带有大写字母“V”的“视频”匹配。 要忽略大小写,您可以使用String.IndexOf这种方式:

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

您正在检查数组_filters是否具有值为"videos mission critial document advertising"的元素(不是这种情况),而不是"videos mission critial document advertising"是否包含_filters中的任何元素。

尝试这个:

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

问题是您对Contains方法的工作方式做出了错误的假设。 (另请参阅String.Contains()文档如果“序列包含特定元素”,则 contains 方法返回 true。在您描述的示例中, _filters数组和itemtype文本都包含字符串videos ,但彼此都不包含。更合适的测试是使用以下扩展方法:

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) ,它类似但专门针对String.Contains方法而不是Enumerable.Contains扩展。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM