Skip to content

Instantly share code, notes, and snippets.

@zambal
Forked from sasa1977/xmerl_demo.ex
Last active December 31, 2015 00:29
Show Gist options
  • Save zambal/7907924 to your computer and use it in GitHub Desktop.
Save zambal/7907924 to your computer and use it in GitHub Desktop.
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