Packages

An XML-RPC parser/formatter for Elixir, with full support for datatype mapping!

Current section

Files

Jump to
weebo lib xml_interface.ex
Raw

lib/xml_interface.ex

defmodule Weebo.XMLInterface do
@moduledoc false
@type xml_element :: {:xmlElement,any,any,any,any,any,any,any,maybe_improper_list(),any,any,any}
@type xml_text :: {:xmlText,any,any,any,any,any,any,any,maybe_improper_list(),any,any,any}
require Record
Record.defrecord :xmlElement, Record.extract(:xmlElement, from_lib: "xmerl/include/xmerl.hrl")
Record.defrecord :xmlAttribute, Record.extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl")
Record.defrecord :xmlText, Record.extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl")
@spec parse(String.t, Keyword.t) :: xml_element
def parse(xml_string, options \\ [quiet: true]) when is_binary(xml_string) do
{doc, []} = xml_string
|> :binary.bin_to_list
|> :xmerl_scan.string(options)
doc
end
@spec export(xml_element) :: String.t
def export(xml) do
List.flatten(:xmerl.export([xml], :xmerl_xml)) |> List.to_string
end
@spec from_tree(Weebo.xml_tree) :: xml_element
def from_tree({elem, children}) do
content = Enum.map children, fn(child) ->
if is_bitstring(child) do
xmlText(value: child)
else
from_tree(child)
end
end
xmlElement(name: elem, content: content)
end
@spec to_tree(xml_element) :: Weebo.xml_tree
def to_tree(xml) do
node = {element_name(xml), []}
to_tree(element_value(xml), node)
end
@spec to_tree(String.t, Weebo.xml_tree) :: Weebo.xml_tree
def to_tree(string, {name, children}) when is_binary(string) do
to_tree([], {name, children ++ [string]})
end
@spec to_tree(list, Weebo.xml_tree) :: Weebo.xml_tree
def to_tree([], tree), do: tree
def to_tree([head|tail], {name, children}) do
new_node = cond do
Record.is_record(head, :xmlText) ->
element_value(head)
true ->
to_tree(element_value(head), {element_name(head), []})
end
cond do
is_binary(new_node) and String.strip(new_node)|>String.length == 0 ->
to_tree(tail, {name, children})
true ->
to_tree(tail, {name, children ++ [new_node]})
end
end
@spec element_name(xml_element) :: atom
def element_name(xmlElement(name: name)), do: name
@spec element_value(xml_element) :: String.t | list
def element_value(xmlElement(content: [xmlText(value: value)])), do: to_string(value)
def element_value(xmlElement(content: list)) when is_list(list), do: list
@spec element_value(xml_text) :: String.t
def element_value(xmlText(value: value)), do: to_string(value)
end