diff --git a/lib/last_fm/session.ex b/lib/last_fm/session.ex new file mode 100644 index 00000000..2148b275 --- /dev/null +++ b/lib/last_fm/session.ex @@ -0,0 +1,62 @@ +defmodule LastFm.Session do + require Record + + defstruct [:name, :key, :pro] + + Record.defrecord( + :xmlAttribute, + Record.extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl") + ) + + Record.defrecord(:xmlText, Record.extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl")) + + def parse(xml_string) do + doc = scan(xml_string) + + name = + doc + |> first("//lfm/session/name") + |> text() + + key = + doc + |> first("//lfm/session/key") + |> text() + + subscriber = + doc + |> first("//lfm/session/subscriber") + |> text() + + %__MODULE__{ + name: name, + key: key, + pro: subscriber == "1" + } + end + + defp scan(xml_string) do + {doc, []} = + xml_string + |> :binary.bin_to_list() + |> :xmerl_scan.string(quiet: true) + + doc + end + + defp first(node, path), do: node |> xpath(path) |> take_one + + defp take_one([head | _]), do: head + defp take_one(_), do: nil + + defp xpath(nil, _), do: [] + + defp xpath(node, path) do + :xmerl_xpath.string(to_charlist(path), node) + end + + def text(node), do: node |> xpath(~c"./text()") |> extract_text + + defp extract_text([xmlText(value: value)]), do: List.to_string(value) + defp extract_text(_x), do: nil +end diff --git a/mix.exs b/mix.exs index 5749326a..99898cee 100644 --- a/mix.exs +++ b/mix.exs @@ -20,7 +20,7 @@ defmodule MusicLibrary.MixProject do def application do [ mod: {MusicLibrary.Application, []}, - extra_applications: [:logger, :runtime_tools] + extra_applications: [:logger, :runtime_tools, :xmerl] ] end diff --git a/test/last_fm/session_test.exs b/test/last_fm/session_test.exs new file mode 100644 index 00000000..e235d0c1 --- /dev/null +++ b/test/last_fm/session_test.exs @@ -0,0 +1,24 @@ +defmodule LastFm.SessionTest do + use ExUnit.Case, async: true + + alias LastFm.Session + + @xml """ + + + + cloud8421 + super-secret + 1 + + + """ + + test "parse/1" do + assert %Session{ + name: "cloud8421", + key: "super-secret", + pro: true + } == Session.parse(@xml) + end +end