Compare commits

...

2 Commits

4 changed files with 41 additions and 17 deletions

View File

@ -23,7 +23,13 @@ defmodule FeedParser do
""" """
@spec parse(data :: String.t(), content_type :: String.t(), parsers :: [module()]) :: @spec parse(data :: String.t(), content_type :: String.t(), parsers :: [module()]) ::
{:ok, feed :: FeedParser.Feed.t()} | {:error, reason :: String.t()} {:ok, feed :: FeedParser.Feed.t()} | {:error, reason :: String.t()}
def parse(data, content_type, parsers \\ @default_parsers) when is_binary(data) do def parse(data, content_type, parsers \\ @default_parsers)
def parse(nil, _, _) do
{:error, "no data"}
end
def parse(data, content_type, parsers) when is_binary(data) do
parsers parsers
|> Enum.reduce_while(false, fn parser, acc -> |> Enum.reduce_while(false, fn parser, acc ->
case parser.accepts(data, content_type) do case parser.accepts(data, content_type) do

View File

@ -12,15 +12,22 @@ defmodule FeedParser.Parser.Atom do
def accepts(data, content_type) do def accepts(data, content_type) do
case content_type do case content_type do
"application/atom+xml" -> "application/atom+xml" ->
{true, XML.parse(data)} case XML.parse(data) do
{:error, _} -> false
{:ok, doc} -> {true, doc}
end
_ when content_type in ["text/xml", "application/xml"] -> _ when content_type in ["text/xml", "application/xml"] ->
doc = XML.parse(data) case XML.parse(data) do
{:error, _} ->
false
if XML.xmlElement(doc, :name) == :feed do {:ok, doc} ->
{true, doc} if XML.xmlElement(doc, :name) == :feed do
else {true, doc}
false else
false
end
end end
_ -> _ ->

View File

@ -12,15 +12,22 @@ defmodule FeedParser.Parser.RSS2 do
def accepts(data, content_type) do def accepts(data, content_type) do
cond do cond do
content_type in ["application/rss+xml", "text/rss+xml"] -> content_type in ["application/rss+xml", "text/rss+xml"] ->
{true, XML.parse(data)} case XML.parse(data) do
{:error, _} -> false
{:ok, doc} -> {true, doc}
end
content_type in ["text/xml", "application/xml"] -> content_type in ["text/xml", "application/xml"] ->
doc = XML.parse(data) case XML.parse(data) do
{:error, _} ->
false
if XML.xmlElement(doc, :name) == :rss do {:ok, doc} ->
{true, doc} if XML.xmlElement(doc, :name) == :rss do
else {true, doc}
false else
false
end
end end
true -> true ->

View File

@ -9,12 +9,16 @@ defmodule FeedParser.XML do
defrecord :xmlAttribute, extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl") defrecord :xmlAttribute, extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl")
defrecord :xmlText, extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl") defrecord :xmlText, extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl")
@spec parse(data :: String.t()) :: tuple() @spec parse(data :: String.t()) :: {:ok, tuple()} | {:error, String.t()}
def parse(data) do def parse(data) do
{doc, _} = {doc, _} =
data try do
|> :binary.bin_to_list() data
|> :xmerl_scan.string() |> :binary.bin_to_list()
|> :xmerl_scan.string()
catch
:exit, reason -> {:error, "parsing XML failed: #{inspect(reason)}"}
end
doc doc
end end