Skip to content

Instantly share code, notes, and snippets.

@joshnuss
Last active August 29, 2015 14:04
Show Gist options
  • Save joshnuss/b160d35e4f6dfd554fd5 to your computer and use it in GitHub Desktop.
Save joshnuss/b160d35e4f6dfd554fd5 to your computer and use it in GitHub Desktop.
XML Builder for Elixir
# XML Builder - inspired by jimweirich's ruby builder
defmodule Builder do
def xml(elements) when is_list(elements),
do: Enum.map_join(elements, &xml/1)
def xml(element_name) when is_atom(element_name) or is_bitstring(element_name),
do: xml({element_name})
def xml({element_name}),
do: "<#{element_name}/>"
def xml({element_name, attrs}) when is_map(attrs),
do: "<#{element_name} #{build_attributes(attrs)}/>"
def xml({element_name, content}),
do: xml({element_name, %{}, content})
def xml({element_name, attrs, children}) when is_list(children),
do: xml({element_name, attrs, Enum.map_join(children, &xml/1)})
def xml({element_name, attrs, content}) when is_map(attrs) and map_size(attrs) == 0,
do: "<#{element_name}>#{content}</#{element_name}>"
def xml({element_name, attrs, content}),
do: "<#{element_name} #{build_attributes(attrs)}>#{content}</#{element_name}>"
defp build_attributes(attrs),
do: Enum.map_join(attrs, " ", fn {k,v} -> ~s/#{k}="#{v}"/ end)
end
IO.puts Builder.xml(:person)
#=> <person/>
IO.puts Builder.xml({:person, "Josh"})
#=> <person>Josh</person>
IO.puts Builder.xml({:person, %{location: "Montreal", occupation: "Developer"}})
#=> <person location="Montreal" occupation="Developer"/>
IO.puts Builder.xml({:person, %{location: "Montreal", occupation: "Developer"}, "Josh"})
#=> <person location="Montreal" occupation="Developer">Josh</person>
IO.puts Builder.xml({:person, [
{:name, "Josh"},
{:occupation, "Developer"}
]})
#=> <person><name>Josh</name><occupation>Developer</occupation></person>
IO.puts Builder.xml({:person, %{id: 1234}, [
{:name, "Josh"},
{:occupation, "Developer"}
]})
#=> <person id="1234"><name>Josh</name><occupation>Developer</occupation></person>
IO.puts Builder.xml([
{:fruit, "Apple"},
{:fruit, "Kiwi"},
{:fruit, "Strawberry"}
])
#=> <fruit>Apple</fruit><fruit>Kiwi</fruit><fruit>Strawberry</fruit>
# same as previous
IO.puts Builder.xml(
fruit: "Apple",
fruit: "Kiwi",
fruit: "Strawberry")
#=> <fruit>Apple</fruit><fruit>Kiwi</fruit><fruit>Strawberry</fruit>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment