Xml in Erlang
-module(xml_example).
-export([main/0]).
-record(plant, {id, name, origin}).
main() ->
Coffee = #plant{id = 27, name = "Coffee", origin = ["Ethiopia", "Brazil"]},
% Emit XML representing our plant
{ok, CoffeeXml} = xmerl:export_simple([to_simple_form(Coffee)], xmerl_xml, [{indent, 2}]),
io:format("~s~n", [CoffeeXml]),
% To add a generic XML header to the output, prepend it explicitly
XmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>~n",
io:format(XmlHeader ++ CoffeeXml),
% Parse XML back into a data structure
{ParsedPlant, _} = xmerl_scan:string(CoffeeXml),
ParsedRecord = from_simple_form(ParsedPlant),
io:format("Plant id=~p, name=~p, origin=~p~n", [ParsedRecord#plant.id, ParsedRecord#plant.name, ParsedRecord#plant.origin]),
Tomato = #plant{id = 81, name = "Tomato", origin = ["Mexico", "California"]},
% Create a nesting structure
Nesting = {nesting, [], [
{parent, [], [
{child, [], [
to_simple_form(Coffee),
to_simple_form(Tomato)
]}
]}
]},
{ok, NestingXml} = xmerl:export_simple([Nesting], xmerl_xml, [{indent, 2}]),
io:format("~s~n", [NestingXml]).
to_simple_form(#plant{id = Id, name = Name, origin = Origin}) ->
{plant, [{id, integer_to_list(Id)}], [
{name, [], [Name]},
[{origin, [], [O]} || O <- Origin]
]}.
from_simple_form({plant, Attrs, Content}) ->
Id = list_to_integer(proplists:get_value(id, Attrs)),
Name = extract_content(name, Content),
Origin = [extract_content(origin, C) || {origin, _, _} = C <- Content],
#plant{id = Id, name = Name, origin = Origin}.
extract_content(Tag, Content) ->
case lists:keyfind(Tag, 1, Content) of
{Tag, _, [Value]} -> Value;
_ -> undefined
end.
This Erlang code demonstrates XML processing using the built-in xmerl
library. Here’s a breakdown of the key points:
We define a
plant
record to represent our data structure.The
to_simple_form/1
function converts our record to a simple form thatxmerl
can process.We use
xmerl:export_simple/3
to convert our data structure to XML.To parse XML back into our data structure, we use
xmerl_scan:string/1
and then convert the parsed structure back to our record withfrom_simple_form/1
.We demonstrate nesting by creating a more complex structure with multiple plants.
The
extract_content/2
helper function is used to extract content from the parsed XML structure.
To run this program, save it as xml_example.erl
and use the Erlang shell:
$ erl
1> c(xml_example).
{ok,xml_example}
2> xml_example:main().
This will output the XML representations and the parsed data structure.
Note that Erlang’s approach to XML processing is quite different from other languages. It uses a simple form representation of XML that consists of tuples and lists. This approach can be more verbose but offers great flexibility in handling XML data.