开发者

change between 'and' and 'or' filter in linq-to-xml in c#

开发者 https://www.devze.com 2023-03-11 20:46 出处:网络
Is it possible to set the filter constraints to \'OR\' in linq-to-xml? I iterate through an array in order to filter desired values like 开发者_运维百科this:

Is it possible to set the filter constraints to 'OR' in linq-to-xml? I iterate through an array in order to filter desired values like 开发者_运维百科this:

XElement root = XElement.Load(fileName);
IEnumerable<XElement> selectedElements = root.Elements("OrderNum").Elements("Job");

for (int i = 1; i < chkBx.Count(); i++)
{
    if (chkBx[i].Checked == true)
    {
        string element = "Diameter";
        string match = chkBx[i].Text;
        selectedElements = selectedElements.Where(el => (string)el.Parent.Element(element) == match);
    }
}

Now the filter will kinda be linked together with an 'AND' statement. What if i want to select an element that statisfy any of these filter conditions?


var filters = chkBx.Where(r => r.Checked).Select(r => r.Text).ToList();
selectedElements = selectedElements.Where(r =>
      filters.Contains((string)r.Parent.Element(element)))


You have three options, depending on the scenario:

  • you could .Union the queries each time (which could make for a lot of overhead, I suspect)
  • you could build a custom expression (lots of work, and not really a good fit for LINQ to Objects)
  • you could build a HashSet<string> of the matches (my preferred option)

i.e.

HashSet<string> matches = new HashSet<string>();

// this next bit can probably be simplified, perhaps using LINQ;
// left alone as it is orthogonal
for (int i = 1; i < chkBx.Count(); i++)   
 {
        if (chkBx[i].Checked == true)
        {
            string element = "Diameter";
            matches .Add(chkBx[i].Text);
        }
    }

var selectedElements = selectedElements.Where(el =>
      matches.Contains((string)el.Parent.Element(element)));


You can do this in two ways, one way is to build the expression using expression trees (necessary for IQueryable situations). But since you're querying an in-memory model you can maintain a list of predicates and use the Any extension to do the filtering.

var predicates = new List<Func<XElement, bool>>();

for (int i = 1; i < chkBx.Count(); i++)
{
    if (chkBx[i].Checked)
    {
        var match = chkBx[i].Text;
        predicates.Add(el => (string)el.Parent.Element("Diameter") == match)
    }
}

selectedElements = selectedElements.Where(el => predicates.Any(p => p(el)));
0

精彩评论

暂无评论...
验证码 换一张
取 消