-
-
Save zambal/7907924 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defrecord :xmlAttribute, Record.extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl") | |
defrecord :xmlText, Record.extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl") | |
defrecord XmlNode, element: nil do | |
def from_string(xml_string, options // [quiet: true]) do | |
{doc, []} = | |
xml_string | |
|> to_unicode_char_list | |
|> :xmerl_scan.string(options) | |
from_element(doc) | |
end | |
defp from_element(element), do: __MODULE__.new(element: element) | |
defmacrop empty_node, do: __MODULE__[element: nil] | |
def all(node, path) do | |
lc child_element inlist xpath(node, path) do | |
from_element(child_element) | |
end | |
end | |
def first(node, path), do: node |> xpath(path) |> take_one |> from_element | |
defp take_one([head | _]), do: head | |
defp take_one(_), do: nil | |
def node_name(empty_node()), do: nil | |
def node_name(node), do: elem(node.element, 1) | |
def attr(node, name), do: node |> xpath('./@#{name}') |> extract_attr | |
defp extract_attr([:xmlAttribute[value: value]]), do: to_unicode_binary(value) | |
defp extract_attr(_), do: nil | |
def text(node), do: node |> xpath('./text()') |> extract_text | |
defp extract_text([:xmlText[value: value]]), do: to_unicode_binary(value) | |
defp extract_text(_), do: nil | |
defp xpath(empty_node(), _), do: [] | |
defp xpath(node, path) do | |
:xmerl_xpath.string(to_char_list(path), node.element) | |
end | |
defp to_unicode_binary(list) when is_list(list), do: :unicode.characters_to_binary(list) | |
defp to_unicode_binary(any), do: to_string(any) | |
defp to_unicode_char_list(input) do | |
:unicode.characters_to_list(input, :utf8) | |
end | |
end | |
doc = XmlNode.from_string(%s(<?xml version="1.0" encoding="UTF-8"?> | |
<root> | |
<child id="1">Saša</child> | |
<child id="2">Jurić</child> | |
</root> | |
)) | |
Enum.each(XmlNode.all(doc, "//child"), fn(node) -> | |
IO.puts "#{XmlNode.node_name(node)} id=#{XmlNode.attr(node, "id")} text=#{XmlNode.text(node)}" | |
end) | |
IO.puts( | |
doc | |
|> XmlNode.first("//child[@id='2']") | |
|> XmlNode.text | |
) | |
IO.puts( | |
doc | |
|> XmlNode.first("//child[@id='3']") | |
|> XmlNode.text | |
) | |
IO.puts( | |
doc | |
|> XmlNode.first("//root") | |
|> XmlNode.first("child[@id='1']") | |
|> XmlNode.text | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment