Friday 22 February 2013

Erlang, record and Erlsom with XSD for XML goodness

Below is a simple example which should get you up and running quickly with Erlsom. Grab a copy of Erlsom from Willemdj's github if you need to.

This is our XML, note.xml:

  Tove
  Jani
  Reminder
  Don't forget me this weekend!

With that, head over to xmlforasp.net to get our XSD file. Copy/paste note.xml and select "Separate Complex Types" which worked for me.

This is what our XSD should look like, note.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="note" type="noteType" />
  <xsd:complexType name="noteType">
    <xsd:sequence>
      <xsd:element name="to" type="xsd:string" />
      <xsd:element name="from" type="xsd:string" />
      <xsd:element name="heading" type="xsd:string" />
      <xsd:element name="mbody" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

Watch out for the encoding bit as xmlforasp.net will give you utf-16 and Erlsom supports only utf-8.

Next from Erlang CLI, we'll create our hrl file:
erlsom:write_xsd_hrl_file("note.xsd","note.hrl").
Which should generate the note.hrl file and look like this:
-record('noteType', {anyAttribs, 'to', 'from', 'heading', 'mbody'}).
Let's load the note.hrl file:
rr("note.hrl").
Load the note.xml file:
{ok, Xml} = file:read_file("note.xml"). 
[noteType]

Compile the note.xsd file:
{ok, Model} = erlsom:compile_xsd_file("note.xsd").
{ok,{model,[{type,'_document',sequence.............

And save the xml variables to our record:
{ok, Note = #noteType{}, _} = erlsom:scan(Xml, Model).
{ok,{model,[{type,'_document',sequence..............

Check the record:
Note.
#noteType{anyAttribs = [],to = "Tove",from = "Jani"......

Check again:
Note#noteType.from.
"Jani"
If you're building an OTP app and following OTP convention then, note.xml and note.xsd should go in the "priv" folder in your project root folder. You can then call the file like this:
Load priv_dir (replace 'note' with your project name) -
privdir() -> code:priv_dir(note).
Load XSD file names
note_xsd() -> filename:join([privdir(), "note.xsd"]).
If you get stuck, post your questions here or on Google+ and I'll try to help you out.