Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing XML file with F# linq to XML

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?

like image 310
Enes Avatar asked Feb 22 '10 23:02

Enes


People also ask

How do I open an XML f file?

Just about every browser can open an XML file. In Chrome, just open a new tab and drag the XML file over. Alternatively, right click on the XML file and hover over "Open with" then click "Chrome". When you do, the file will open in a new tab.

How do I parse a special character in XML?

To include special characters inside XML files you must use the numeric character reference instead of that character. The numeric character reference must be UTF-8 because the supported encoding for XML files is defined in the prolog as encoding="UTF-8" and should not be changed.

How do you parse XML to string in Python?

There are two ways to parse the file using 'ElementTree' module. The first is by using the parse() function and the second is fromstring() function. The parse () function parses XML document which is supplied as a file whereas, fromstring parses XML when supplied as a string i.e within triple quotes.


1 Answers

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
like image 196
Tomas Petricek Avatar answered Oct 23 '22 05:10

Tomas Petricek