Packages
floki
0.0.3
0.38.4
0.38.3
0.38.2
0.38.1
0.38.0
0.37.1
0.37.0
0.36.3
0.36.2
0.36.1
0.36.0
0.35.4
0.35.3
0.35.2
0.35.1
0.35.0
0.34.3
0.34.2
0.34.1
0.34.0
0.33.1
0.33.0
0.32.1
0.32.0
0.31.0
0.30.1
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.1
0.23.0
0.22.0
0.21.0
0.20.4
0.20.3
0.20.2
0.20.1
0.20.0
0.19.3
0.19.2
0.19.1
0.19.0
0.18.1
0.18.0
0.17.2
0.17.1
0.17.0
0.16.0
0.15.0
0.14.0
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.0
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.0
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.1
0.1.0
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
Floki is a simple HTML parser that enables search for nodes using CSS selectors.
Current section
Files
Jump to
Current section
Files
lib/floki.ex
defmodule Floki do
def parse(html) do
:mochiweb_html.parse(html)
end
def find(html, selector) when is_binary(html) do
parse(html)
|> find(selector)
end
def find(html_tree, "." <> class) do
find_by_selector(class, html_tree, &class_matcher/3, [])
|> Enum.reverse
end
def find(html_tree, "#" <> id) do
find_by_selector(id, html_tree, &id_matcher/3, [])
|> List.first
end
def find(html_tree, tag_name) do
find_by_selector(tag_name, html_tree, &tag_matcher/3, [])
|> Enum.reverse
end
def attribute(html, selector, attribute_name) do
html
|> find(selector)
|> get_attribute_values(attribute_name)
end
def attribute(elements, attribute_name) do
elements
|> get_attribute_values(attribute_name)
end
defp class_match?(attributes, class) do
attribute_match?(attributes, "class", class)
end
defp attribute_match?(attributes, attribute_name, value) do
Enum.find(attributes, fn(attribute) ->
{ attr_name, attr_value } = attribute
attr_name == attribute_name && String.contains?(attr_value, value)
end)
end
defp find_by_selector(_selector, {}, _, acc), do: acc
defp find_by_selector(_selector, [], _, acc), do: acc
defp find_by_selector(_selector, tree, _, acc) when is_binary(tree), do: acc
defp find_by_selector(selector, [h|t], matcher, acc) do
acc = find_by_selector(selector, h, matcher, acc)
find_by_selector(selector, t, matcher, acc)
end
defp find_by_selector(_selector, { :comment, _comment }, _, acc), do: acc
defp find_by_selector(selector, node, matcher, acc) when is_tuple(node) do
{ _, _, child_node } = node
acc = matcher.(selector, node, acc)
find_by_selector(selector, child_node, matcher, acc)
end
defp get_attribute_values(elements, attr_name) do
Enum.map(elements, fn(el) ->
{ _name, attributes, _childs } = el
attribute_match?(attributes, attr_name, "")
end)
|> Enum.reject(fn(x) -> is_nil(x) end)
|> Enum.map(fn({_attr_name, value}) -> value end)
end
defp class_matcher(selector, node, acc) do
{ _, attributes, _ } = node
if class_match?(attributes, selector) do
acc = [node|acc]
end
acc
end
defp tag_matcher(tag_name, node, acc) do
{ tag, _, _ } = node
if tag == tag_name do
acc = [node|acc]
end
acc
end
defp id_matcher(id, node, acc) do
{ _, attributes, _ } = node
if attribute_match?(attributes, "id", id) do
acc = [node|acc]
end
acc
end
end