Xml in F#
Here’s the translation of the XML example from Go to F#:
open System
open System.Xml.Serialization
open System.IO
// Plant will be mapped to XML. We use attributes to specify
// XML serialization details. The XmlRoot attribute dictates
// the name of the XML element representing this type.
[<XmlRoot("plant")>]
type Plant = {
[<XmlAttribute("id")>]
Id: int
[<XmlElement("name")>]
Name: string
[<XmlArray("origin")>]
Origin: string[]
}
// ToString method for Plant
let plantToString (p: Plant) =
sprintf "Plant id=%d, name=%s, origin=[%s]" p.Id p.Name (String.Join("; ", p.Origin))
[<EntryPoint>]
let main argv =
let coffee = { Id = 27; Name = "Coffee"; Origin = [| "Ethiopia"; "Brazil" |] }
// Emit XML representing our plant; using XmlSerializer
// to produce a more human-readable output.
let serializer = new XmlSerializer(typeof<Plant>)
use writer = new StringWriter()
serializer.Serialize(writer, coffee)
let xmlOutput = writer.ToString()
printfn "%s" xmlOutput
// To add a generic XML header to the output, prepend it explicitly.
printfn "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n%s" xmlOutput
// Use XmlSerializer to parse a stream of bytes with XML
// into a data structure.
use reader = new StringReader(xmlOutput)
let deserializedPlant = serializer.Deserialize(reader) :?> Plant
printfn "%s" (plantToString deserializedPlant)
let tomato = { Id = 81; Name = "Tomato"; Origin = [| "Mexico"; "California" |] }
// The XmlArrayItem attribute tells the serializer to nest all
// plants under <parent><child>...</child></parent>
[<XmlRoot("nesting")>]
type Nesting = {
[<XmlArray("parent")>]
[<XmlArrayItem("child")>]
Plants: Plant[]
}
let nesting = { Plants = [| coffee; tomato |] }
use writer = new StringWriter()
let nestingSerializer = new XmlSerializer(typeof<Nesting>)
nestingSerializer.Serialize(writer, nesting)
printfn "%s" (writer.ToString())
0
This F# code demonstrates XML serialization and deserialization using the System.Xml.Serialization
namespace. Here’s a breakdown of the key points:
We define a
Plant
record type with XML attributes to control serialization.The
plantToString
function provides a string representation of aPlant
.In the
main
function, we create acoffee
instance and serialize it to XML.We demonstrate how to add an XML header to the output.
We then deserialize the XML back into a
Plant
instance.A
Nesting
type is defined to show how to create nested XML structures.Finally, we create a
Nesting
instance with bothcoffee
andtomato
plants and serialize it to XML.
To run this program, save it as a .fs
file and compile it using the F# compiler (fsc). Then run the resulting executable.
Note that F# uses attributes (like [<XmlRoot>]
) instead of struct tags to control XML serialization. The XmlSerializer
class is used for both serialization and deserialization, which is similar to the encoding/xml
package in Go.