Current section
Files
Jump to
Current section
Files
lib/fml.ex
defmodule FML do
def parse(document, init, mod) do
case :erlsom.parse_sax(document, {init, [], mod}, &handle_sax_event(&1, &2)) do
{:ok, {state, [], _}, _} -> {:ok, state}
error -> {:error, error}
end
end
defp handle_sax_event({:startElement, _, tag_name, prefix, attributes}, {state, stack, mod}) do
tag = build_tag(prefix, tag_name, attributes)
new_state = mod.on_start_element(tag, stack, state)
{new_state, [tag | stack], mod}
end
defp handle_sax_event({:characters, chars}, {state, stack, mod}) do
[{tag_name, attributes, nil} | stack] = stack
tag = {tag_name, attributes, to_string(chars)}
{state, [tag | stack], mod}
end
defp handle_sax_event({:endElement, _, _tag_name, _prefix}, {state, stack, mod}) do
[tag | stack] = stack
new_state = mod.on_end_element(tag, stack, state)
{new_state, stack, mod}
end
defp handle_sax_event(_event, {state, stack, mod}) do
{state, stack, mod}
end
defp build_tag([], tag_name, attributes) do
{tag_name, build_attributes(attributes), nil}
end
defp build_tag(prefix, tag_name, attributes) do
{{prefix, tag_name}, build_attributes(attributes), nil}
end
defp build_attributes(attributes) do
Enum.map(attributes, fn {:attribute, name, prefix, _, value} ->
{build_attribute_name(prefix, name), to_string(value)}
end)
end
defp build_attribute_name([], name), do: name
defp build_attribute_name(prefix, name), do: {prefix, name}
end