为什么得到空列表

Why got empty list

我正在编写一个读取 xml 文件并添加到列表中的应用程序。代码如下所示:

open System.Net
open System.Collections.Generic
open System.Xml.Linq
open System

type IpRanges = {ipStart: IPAddress; ipEnd: IPAddress; subnet: IPAddress; mask: IPAddress}

type System.String with
    member s1.isEqual(s2: string) =
        System.String.Equals(s1, s2, System.StringComparison.CurrentCultureIgnoreCase)


let xname name = XName.Get name
let xattr (elem: XElement) (name:string) = elem.Attribute(xname name).Value

let loc (filename:string) (location:string) = 
    query {
        for doc in XDocument.Load(filename).Descendants(xname "location") do
        where ((xattr doc "name").isEqual(location))
        select doc
    }

let extractAddr (doc:seq<XElement>) = 
    let mutable startAddr:IPAddress = null
    let mutable endAddr:IPAddress = null
    let mutable subnet:IPAddress = null

    let list:List<IpRanges> = new List<IpRanges>()

    //let mutable mask = "0.0.0.0"

    let parseIP (addr:string) = IPAddress.Parse addr 

    for e in doc do
        match e.Name.LocalName with
         | "start" -> startAddr <- parseIP e.Value
         | "end" -> endAddr <- parseIP e.Value
         | "subnet" -> subnet <- parseIP e.Value
         | "mask" -> list.Add({ipStart = startAddr; ipEnd = endAddr; subnet = subnet; mask = parseIP(e.Value)}) |> ignore
         | _ -> ()

    // Return list
    list


[<EntryPoint>]
let main argv = 

    let location = (loc ("C:\Temp\file.xml") "location").Descendants(xname "range").Descendants()
                    |> extractAddr

    //let list = extractAddr location

    Console.ReadLine() |> ignore
    0 // return an integer exit code

执行我的代码后,列表

let list:List<IpRanges> = new List<IpRanges>()
为什么我在函数extractAddr中定义的

是空的? 通过调试按预期工作,除了这个

| "mask" -> list.Add({ipStart = startAddr; ipEnd = endAddr; subnet = subnet; mask = parseIP(e.Value)}) |> ignore

没有添加到列表中。 Xml结构

<?xml version="1.0" encoding="UTF-8"?>
<ip>
    <location name="test">

        <range>
            <start>192.20.10.1</start>
            <end>192.20.10.255</end>
            <subnet>255.255.255.0</subnet>
            <gateway>192.20.16.1</gateway>
        </range>sub

        <range>
            <start>192.20.12.1</start>
            <end>192.20.12.255</end>
            <subnet>255.255.255.0</subnet>
            <gateway>192.20.16.1</gateway>
        </range>
    </location>     

</ip>

XML 中没有 "mask" 元素,因此此模式永远不会匹配。 此外,我会将您的 extractAddr 函数更改为更像这样的 "XML structure proof"(如果没有名称为 elmname 的元素,则不会抛出异常):

let parseRangeElement (range: XElement) elmname = 
    let e = range.Element(xname elmname)
    if  e <> null then 
        match IPAddress.TryParse(e.Value) with
        | true, ip -> ip
        | _ -> null
    else null

let extractAddr (doc:seq<XElement>) =
    doc
    |> Seq.map (fun rngelm -> 
                    {
                    ipStart = parseRangeElement rngelm "start"
                    ipEnd = parseRangeElement rngelm "end" 
                    subnet = parseRangeElement rngelm "subnet" 
                    mask = parseRangeElement rngelm "gateway"
                    })
    |> List.ofSeq // if you really need list

[<EntryPoint>]
let main argv = 

    let location = (loc (xml) "test").Descendants(xname "range") 
                    |> extractAddr

    Console.ReadLine() |> ignore
    0 // return an integer exit code