基于属性名称/值对创建通用xml linq搜索

时间:2017-05-08 18:26:31

标签: c# xml linq

我正在处理一组函数,其中一个是解析XML文件,并返回与我所拥有的基于属性的条件匹配的元素。

这是我必须使用的XML示例:

 <rs:insert>
<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;
        }
    }

我在vElementQuery的where子句中遇到错误:

  

仅分配,调用,增量,减量,等待和新对象   表达式可以用作语句

简单来说,我会根据Inst和Event进行查询,但偶尔我也需要基于hostname和Eventtype。

基本上,我不知道我需要匹配多少属性条件,所以我想将它们作为列表或数组添加,认为KeyValuePair会很有用,因为它给了我我需要的名称和比较(价值)。

感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

Where需要一个谓词:一个e(在这种情况下为XElement)并返回bool的函数。

相反,您尝试返回SearchCriteria.ForEach()的结果,返回void。它所做的就是迭代集合并为每个项目调用void lambda。因此,您不能将它用作谓词的主体。修复此问题后,这将是您的下一个问题,但同样的修复工具会解决这两个问题。

.Where(e => 
    SearchCriteria.ForEach(sc => 
        e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper()
    )
)

由于ForEach返回void,因此需要返回void的lambda。函数体必须是一个声明。在lambda中,如果返回类型不是void,并且正文是表达式,则返回该表达式的结果 - 将其称为隐式返回语句。但是这里的返回值是无效的 - 由the parameter type of ForEach确定:

public void ForEach(
    Action<T> action
)

Action<T>有一个参数,没有返回类型。无论编译器使用什么推理规则,都会假设你正在尝试编写一个void lambda,而不是你试图给ForEach一个谓词。

这是你给它的lambda的主体:

e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper()

如果没有编译器在其前面提供隐式return,那么这不是一个声明。这是一种表达方式。作为声明,它不是合法的C#。尝试编译:

1 != 2;

同样的错误。 C或Perl不会关心,但C#会这样做。

我认为您可能需要Any而不是ForEach

.Where(e => 
    SearchCriteria.Any(sc => 
        e.Attribute(sc.Key).Value.ToUpper() == sc.Value.ToUpper()
    )
)

也就是说,返回任何搜索条件与其任何属性匹配的任何eAny获取谓词并返回bool,修复这两个错误。