我正在学习F#并且遇到了一个问题,谷歌搜索对我没什么帮助。
我有一个带有XmlNodes的Xml文档,它是使用Xpath选择的。我已经过滤了属性,属性集合可以从Seq返回。但是,当我返回属性值而不是属性时,编译期间会显示以下错误
This expression was expected to have type
'a option
but here has type
string
下面给出了代码段
let doc = new System.Xml.XmlDocument() in
doc.LoadXml xml;
doc.SelectNodes "//*[local-name()='SingleSignOnService']"
|> Seq.cast<System.Xml.XmlNode>
|> Seq.collect (fun node -> node.Attributes |> Seq.cast<System.Xml.XmlAttribute>)
|> Seq.filter (fun attr -> attr.Name.Equals("Binding",StringComparison.OrdinalIgnoreCase))
|> Seq.choose(fun attr -> attr.Value)
请建议我正确的方法。
修改
这是我在Mr.Marklam的帮助下形成的解决方案。希望这会有助于其他任何人
let doc = new System.Xml.XmlDocument() in
doc.LoadXml xml;
doc.SelectNodes "//*[local-name()='SingleSignOnService']"
|> Seq.cast<System.Xml.XmlNode>
|> Seq.collect (fun node -> node.Attributes |> Seq.cast<System.Xml.XmlAttribute> |> Seq.filter (fun attr -> attr.Name.Equals("Binding",StringComparison.OrdinalIgnoreCase)))
|> Seq.choose (fun attr -> if (attr.Name.Equals("Binding",StringComparison.OrdinalIgnoreCase)) then Some attr.Value else None)
答案 0 :(得分:4)
如果您想使用Seq.choose
删除任何null
属性值,则应将attr.Value
转换为string option
。
最简单的方法是通过Option.ofObj
,即
|> Seq.filter (fun attr -> attr.Name.Equals("Binding",StringComparison.OrdinalIgnoreCase)
|> Seq.choose(fun attr -> attr.Value |> Option.ofObj)
但是如果您知道该值永远不为null,则可以使用
|> Seq.choose (fun attr -> if attr.Name.Equals("Binding",StringComparison.OrdinalIgnoreCase)) then Some attr.Value else None)
答案 1 :(得分:3)
我认为Linq扩展方法存在一些混淆。
map(fun attr -> attr.Value)
是Select(attr => attr.Value)
choose
只是Where(option => option.HasValue).Select(option => option.Value)
以下是C#/ Linq中的更多内容
collect
是SelectMany
find
是First
fold
是Aggregate
singleton
是Enumerable.Return