我正在尝试解析XML文件的目录,然后在给定节点存在时选择特定属性的值。我无法理解以下F#导致的编译错误的原因。
open System
open System.IO
open System.Xml
open System.Xml.XPath
open System.Xml.Linq
let configRootDirectory = @"C:\dir"
let relativeProductDir = @"relDir"
let ExtractConfiguredCalculator (productConfigFile:string) =
let xmlNavigator = XPathDocument(productConfigFile).CreateNavigator()
let node = xmlNavigator.SelectSingleNode(@"Product/SupportedRisk/Risk[@type='PV']")
node.GetAttribute("methodology", "")
let configFile = Directory.GetFiles(Path.Combine(configRootDirectory, relativeProductDir), @"*.xml")
|> Seq.cast<string>
|> Seq.iter(fun configFileName -> ExtractConfiguredCalculator(configFileName))
|> Seq.filter(fun configuredCalculatorNode -> configuredCalculatorNode != null)
|> Seq.iter(fun calculator -> Console.WriteLine(calculator))
上面的代码片段来自我在LinqPad中尝试的代码。看到的错误信息如下所示。
This expression was expected to have type unit but here has type string
更新 试图获得更多f#-ish。如果可以改进,请建议。
let configFile =
Directory.GetFiles(Path.Combine(configRootDirectory, relativeProductDir), @"*.xml")
|> Seq.map(fun configFileName ->
let xmlNavigator = XPathDocument(configFileName).CreateNavigator()
let node = xmlNavigator.SelectSingleNode(@"Product/SupportedRisk/Risk[@type='PV']")
match node with
| null -> "PV not configured"
| _ ->
let attributeValue = node.GetAttribute("methodology", "")
match attributeValue with
| null -> "Calculator not configured"
| _ -> attributeValue)
|> Seq.iter (printfn "%s")
答案 0 :(得分:6)
您必须将第一个Seq.iter
更改为Seq.map
才能返回后续Seq.filter
所需的序列。
我有几条评论:
Seq.cast
是多余的,因为Directory.GetFiles
会返回string []
。Seq.map
和Seq.filter
在一起时,您可以随时将其替换为Seq.choose
。printfn
是一种比Console.WriteLine
更多的F#打印方式。以下是改进版本:
let configFile =
Directory.GetFiles(Path.Combine(configRootDirectory, relativeProductDir), @"*.xml")
|> Seq.choose (fun configFileName ->
let config = ExtractConfiguredCalculator(configFileName)
if config <> null then Some config else None)
|> Seq.iter (printfn "%s")
答案 1 :(得分:4)
您对[{1}}的第一次电话应该是Seq.iter
。 Seq.map
返回ExtractConfiguredCalculator
,但string
期望函数返回Seq.iter
。