使用 F# 如何访问与文档不具有相同命名空间的元素?

Using F# how do I access an element that doesn't have the same namespace as the document?

这是我第一次尝试 F#,我知道我仍然需要阅读很多东西而且我会的,但是这些挑战帮助我理解接下来我会更好地阅读的部分,到目前为止我设法解决了一些问题第一次挑战,请耐心等待......

xml 文档如下所示:

<BuildCollection xmlns="http://schemas.datacontract.org/2004/07/BuildModels" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    ...
    <PostEvents xmlns:a="http://schemas.datacontract.org/2004/07/BuildModels.Events">
        <a:EventBase i:type="a:ExternalProcess">
            <a:Description>Structuring assemblies</a:Description>           

如何访问以 "a:......." 开头的元素?

在 C# 中我会这样做:

foreach (var postBuildEventElement in 
    document
        .Root.Element(ns + "PostEvents")
        .Elements()
        .Where(_ => _.Name.LocalName == "EventBase"))

到目前为止,在 F# 中我有这个:

module PostBuildInstructions

open System.Xml.Linq
open System.Linq

let xn s = XName.Get(s)

let PostBuildInstructions (xdoc: System.Xml.Linq.XDocument) =
    xdoc.Root.Elements(xn "PostEvents").Elements().Where(e => e.)

let ExecutePostBuildInstructions buildDescriptor =
    let "I need to enumerate the post build events here"

在 "main" 代码块中,我从这个开始:(我关注第 6 行这个问题)

open Log

[<EntryPoint>]
let main argv = 
    TryLogArgs argv
    ReadPostBuildInstructions |> ExecutePostBuildInstructions
    log "Press enter to exit"
    System.Console.ReadLine() |> ignore
    0 // return an integer exit code

您对 xn 函数的使用与 C# 版本中的使用不同。您的 xn 函数 returns 没有关联名称空间的名称。但是,您处理的是命名空间中的名称,您应该生成这样的名称。

您的 C# 版本理想情况下应如下所示:

XNamespace ns = "http://schemas.datacontract.org/2004/07/BuildModels";
XNamespace a = "http://schemas.datacontract.org/2004/07/BuildModels.Events";
var query = doc.Root
    .Elements(ns + "PostEvents")
    .Elements(a + "EventBase");

F# 版本应该差别不大:

let ns = XNamespace.Get("http://schemas.datacontract.org/2004/07/BuildModels")
let a = XNamespace.Get("http://schemas.datacontract.org/2004/07/BuildModels.Events")
let query = doc.Root.Elements(ns + "PostEvents").Elements(a + "EventBase")

但您可能希望将它们保留为函数调用。只需确保为函数关联了正确的命名空间即可。

let xn n = XName.Get(n)
let ns n = XName.Get(n, "http://schemas.datacontract.org/2004/07/BuildModels")
let a n = XName.Get(n, "http://schemas.datacontract.org/2004/07/BuildModels.Events")
let query = doc.Root.Elements(ns "PostEvents").Elements(a "EventBase")