我正在尝试解析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))
Run Code Online (Sandbox Code Playgroud)
上面的代码片段来自我在LinqPad中尝试的代码.看到的错误信息如下.
This expression was expected to have type unit but here has type string
Run Code Online (Sandbox Code Playgroud)
更新 尝试获得更多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")
Run Code Online (Sandbox Code Playgroud)
你必须改变第一Seq.iter,以Seq.map返回其通过随后要求的顺序Seq.filter.
我有几条评论:
Seq.cast因为Directory.GetFiles返回是多余的string [].Seq.map和Seq.filter在一起时,你总是可以替换它们Seq.choose.printfn是比F#更多的印刷方式Console.WriteLine.这是一个改进版本:
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")
Run Code Online (Sandbox Code Playgroud)