Parsing XML file with F# linq to XML

f#, linq-to-xml, xml

Solution

It would be useful if you could show some code that you tried - someone can then explain what is the problem, so you can learn more than when someone just posts code that works. Anyway, you'll need to reference some assemblies with the `System.Xml.Linq` and open the namespace first. In F# interactive, you can write it like this (in F# project, just use Add Reference dialog):

#r "System.Core.dll"
#r "System.Xml.Linq.dll"
open System.Xml.Linq

When using XLinq in F#, you need a simple utility function for converting strings to `XName` object (which represents an element/attribute name). There is an implicit conversion in C#, but this sadly doesn't work in F#.

let xn s = XName.Get(s)

Then you can load your XML document using the `XDocument` class and use `Element` method to get a single "parent" element. Then you can call `Elements` to get all nested "property" elements:

let xd = XDocument.Load("file.xml")
let props = xd.Element(xn "parent").Elements(xn "property")

Now you can search the elements to find the one element with the specified attribute value. For example using `Seq.tryFind` (which also allows you to handle the case when the element is not found):

let nameOpt = props |> Seq.tryFind (fun xe -> 
  xe.Attribute(xn "name").Value = "firstName")

Now, the value `nameOpt` is of type `option<XElement>` so you can pattern match on it to see if the element was found (e.g. `Some(el)`) or if it wasn't found (`None`).

EDIT: Another way to write this is to use sequence expressions and then just take the first element (this doesn't handle the case when element is not found):

let nameEl = 
  seq { for el in xd.Element(xn "parent").Elements(xn "property") do
          if xe.Attribute(xn "name").Value = "firstName" then yield xe }
  |> Seq.head

Problem

F# newbie I have 2 XML files in 2 folders `c:\root\a\file.xml` and `c:\root\b\file.xml` They have identical structure: ``` <parent> <property name="firstName">Jane</property> <property name="lastName">...</property> <property name="dateOfBirth">...</property>> </parent> ``` I need to chose the file which property node with name `firstName` has the value Jane. In F# (possibly by using `System.Xml.Linq`) I have tried several solutions but none working so far. Anyone willing to help?

Original source