"To give a sense of what programming in Boomerang is like, we will define the lens implementing the transformations between XML and CSV composers shown above.
First we define a lens c that handles a single <composer> element. It uses a number of functions defined in our XML library, as well as primtives for copying (copy) and deleting (del) strings, and for concatenating lenses (.).
let c : lens =
Xml.elt NL2 "composer"
begin
Xml.simple_elt NL4 "name"
(copy [A-Za-z ]+ . ins ", ") .
Xml.attr2_elt_no_kids NL4 "years"
"birth" (copy NUMBER . ins "-")
"death" (copy NUMBER) .
Xml.simple_elt NL4 "nationality" (del [A-Za-z]+)
end
Using c, we then define a lens that handles a top-level <composers> element, enclosing a list of <composers>. This lens is defined using the features already described, a primitive for inserting a string (ins), as well as union (|) and Kleene star. let cs : lens =
Xml.elt NL0 "composers"
begin
copy EPSILON |
c . (ins newline . c)*
end
..."Update: Okay, so putting spaces around it ( * ) works. But the asterisk in question was inside parens without spaces.
Some formalisms would certainly be nice though..it's easy to think that you've transformed data well only to find holes in your methods later.
"get" abstract info from a concrete version;
"put" new abstract info into a concrete version, returning a new concrete version;
"create" a new concrete version from abstract info, presumably filling in extra details with defaults.
The running example in their tutorial is a database of information about composers. The "concrete" version is an XML file. The "abstract" version is something more compact, one entry per line, which omits the nationality data in the XML file.