I have a set of functions I'm working on, and one of them is to parse an XML file, and return the elements that match to the attribute-based conditions that I have.
This is a sample of the XML I have to use:
<z:row Inst='AM5001' Event='EventA' HostName='HostA' EventType='NORMAL' TXID='0000003327'/>
<z:row Inst='AM5001' Event='EventB' HostName='HostB' EventType='NORMAL' TXID='0000011173'/>
<z:row Inst='AM4067' Event='EventA' HostName='HostA' EventType='NORMAL' TXID='0000011175'/>
<z:row Inst='AM5546' Event='EventC' HostName='HostC' EventType='NORMAL' TXID='0000011177'/>
<z:row Inst='AM4567' Event='EventQ' HostName='HostD' EventType='NORMAL' TXID='0000011593'/>
internal protected IEnumerable<XElement> GetElement(XDocument oXMLDoc
, List<KeyValuePair<string, string>> SearchCriteria)
var vElementQuery = oXMLDoc.Elements()
.Where(e => SearchCriteria.ForEach(sc => e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper()))
.Select(e => e);
foreach (var xElement in vElementQuery)
yield return xElement;
Only assignment, call, increment, decrement, await, and new object
expressions can be used as a statement
Where requires a predicate: A function that takes an
XElement in this case) and returns a
Instead, you're trying to return the result of
SearchCriteria.ForEach(), which returns
void. All it does is iterate over the collection and call a
void lambda for each item. So you can't use it as the body of a predicate. That would be your next problem after you fix this one, but the same fix takes care of both.
.Where(e => SearchCriteria.ForEach(sc => e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper() ) )
void, it takes a lambda that returns
void. The body of a function must be a statement. In a lambda, if the return type isn't
void, and the body is an expression, the result of that expression is returned -- call it an implicit return statement. But here the return value is void -- that's established by the parameter type of
public void ForEach( Action<T> action )
Action<T> has one parameter and no return type. And whatever inference rules the compiler uses result in it assuming that you're trying to write a void lambda, rather than that you're trying to give
ForEach a predicate.
Here's the body of the lambda you're giving it:
e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper()
Without the compiler supplying an implicit
return in front of it, that's not a statement. It's an expression. As a statement, it's not legal C#. Try compiling this:
1 != 2;
Same error. C or Perl wouldn't care but C# does.
I think you might want
Any instead of
.Where(e => SearchCriteria.Any(sc => e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper() ) )
That is to say, return any
e where any of the search criteria matches any of its attributes.
Any takes a predicate and returns
bool, fixing both errors.