softshipper
softshipper

Reputation: 34081

How to create record in match pattern

I want to write an application that read ip address from xml file. The file looks like

<range>
    <start>192.168.40.1</start>
    <end>192.168.50.255</end>
    <subnet>255.255.255.0</subnet>
    <gateway>192.168.50.1</gateway>
</range>

I create an records type to save the ip address

type Scope = { Start: IPAddress; End: IPAddress; Subnetmask: IPAddress; Gateway: IPAddress } 

I wrote a unit function, that output the ip's.

loc
            |> Seq.iter (fun e -> match e.Name.LocalName with
                                    |"start" -> printfn "Start %s" e.Value
                                    |"end" -> printfn "End %s" e.Value
                                    |"subnet" -> printfn "Subnet %s" e.Value
                                    |"gateway" -> printfn "Gateway %s" e.Value
                                    | _ -> ())

How can I return the scope records type instead of unit?

Upvotes: 0

Views: 87

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243061

As mentioned in the comments, the XML type provider makes this a lot easier. You can just point it at a sample file, it will infer the structur and let you read the file easily:

type RangeFile = XmlProvider<"sample.xml">
let range = RangeFile.Load("file-you-want-to-read.xml")

let scope = 
  { Start = IPAddress.Parse(range.Start)
    End = IPAddress.Parse(range.End)
    Subnetmask = IPAddress.Parse(range.Subnet)
    Gateway = IPAddress.Parse(range.Gateway) }

That said, you can certainly implement this yourself too. The code you wrote is a good start - there is a number of ways to do this, but in any case, you'll need to do some lookup based on the local name of the element (to find start, end, etc.).

One option is to load all the properties into a dictionary:

let lookup = 
   loc
   |> Seq.map (fun e -> e.Name.LocalName, IPAddress.Parse(e.Value)
   |> dict

Now you have a lookup table that contains IPAddress for each of the keys, so you can create Scope value using just:

let scope = 
  { Start = lookup.["start"]; End = lookup.["end"];
    Subnetmask = lookup.["subnet"]; Gateway = lookup.["gateway"] }

That said, the nice thing about the XML type provider is that it removes the need to do lookup based on string values and so you are less likely to make mistakes caused by typos.

Upvotes: 1

Related Questions