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