-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
defmodule Exmerl do | ||
@moduledoc ~s""" | ||
Exmerl is an Elixir wrapper around xmerl_*. | ||
Currently not very much is supported, only parsing | ||
xml into elixir data, and selecting elements through Xpath | ||
expressions. | ||
""" | ||
|
||
@typedoc "The parsed XML document" | ||
@type document :: term | ||
|
||
@typedoc "Rest" | ||
@type rest :: [term] | ||
|
||
@typedoc "keys for option lists" | ||
@type key :: atom | ||
|
||
@typedoc "values for option lists" | ||
@type value :: term | ||
|
||
@doc ~s""" | ||
Parses xml from a file. See http://www.erlang.org/doc/man/xmerl_scan.html | ||
for a description of the available options | ||
""" | ||
@spec from_file(String.t, [{key, value}]) :: {document, rest} | ||
def from_file(fname, opts \\ []) do | ||
:xmerl_scan.file(fname, opts) | ||
end | ||
|
||
@doc ~s""" | ||
Parses xml from a string. See http://www.erlang.org/doc/man/xmerl_scan.html | ||
for a description of the available options | ||
""" | ||
@spec from_string(String.t, [{key, value}]) :: {document, rest} | ||
def from_string(str, opts \\ []) do | ||
:xmerl_scan.string(to_char_list(str), opts) | ||
end | ||
|
||
@doc ~s""" | ||
Tries to guess wether the first argument is a filename or not, and calls the | ||
appropriate function. See http://www.erlang.org/doc/man/xmerl_scan.html | ||
for a description of the available options | ||
""" | ||
@spec parse(String.t, [{key, value}]) :: {document, rest} | ||
def parse(string_or_fname, opts \\ []) do | ||
if File.exists?(string_or_fname) do | ||
from_file(string_or_fname, opts) | ||
else | ||
from_string(string_or_fname, opts) | ||
end | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
defmodule Exmerl.XPath do | ||
@moduledoc ~s""" | ||
Select xml elements by an XPath selector | ||
Currently only provides one function, `find/2,3,5` | ||
""" | ||
|
||
@typedoc "xml document" | ||
@type document :: term | ||
|
||
@typedoc "Rest" | ||
@type rest :: [term] | ||
|
||
@typedoc "xml element" | ||
@type element :: term | ||
|
||
@typedoc "key for option list" | ||
@type key :: atom | ||
|
||
@typedoc "value for option list" | ||
@type value :: term | ||
|
||
@typedoc "xpath string" | ||
@type xpath_string :: String.t | ||
|
||
@typedoc "xpath result" | ||
@type xpath_result :: term | ||
|
||
@doc ~s""" | ||
Select one or more XML elements using an XPath expression | ||
An alternate form of this allows `{document, rest}` to be passed in | ||
as the first parameter, and returns it along with the xpath result, | ||
for easy piping from Exmerl.parse calls. | ||
Example: | ||
iex(1)> Exmerl.parse("my_xml_file.xml") |> Exmerl.XPath.find("//somenode") | ||
{ | ||
# this is the actual result from the .find call | ||
[ ... ], | ||
# this is the `rest` result from the .parse call | ||
[ ... ] | ||
} | ||
iex(2)> | ||
""" | ||
@spec find(document, xpath_string, [{key, value}]) :: xpath_result | ||
def find(doc, str, opts \\ []) | ||
|
||
@spec find({document, rest}, xpath_string, [{key, value}]) :: {xpath_result, rest} | ||
def find({doc, rest}, str, opts) do | ||
{:xmerl_xpath.string(to_char_list(str), doc, opts), rest} | ||
end | ||
|
||
def find(doc, str, opts) do | ||
:xmerl_xpath.string(to_char_list(str), doc, opts) | ||
end | ||
|
||
@doc ~s""" | ||
Same as http://www.erlang.org/doc/man/xmerl_xpath.html#string-5, | ||
except for rearranging of the function parameters to allow piping. | ||
""" | ||
def find(doc, str, node, parents, opts \\ []) | ||
|
||
def find({doc, rest}, str, node, parents, opts) do | ||
{:xmerl_xpath.string(to_char_list(str), node, parents, doc, opts), rest} | ||
end | ||
|
||
def find(doc, str, node, parents, opts) do | ||
:xmerl_xpath.string(to_char_list(str), node, parents, doc, opts) | ||
end | ||
|
||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
defmodule ExmerlTest do | ||
use ExUnit.Case | ||
import PathHelpers | ||
import TestHelpers | ||
|
||
test "parse basic file" do | ||
resultpath = to_char_list(Path.dirname __DIR__) | ||
{document, _} = Exmerl.parse(File.read!(fixture_path("justroot.xml"))) | ||
assert document == {:xmlElement, :rootnode, :rootnode, [], {:xmlNamespace, [], []}, [], 1, [], | ||
[{:xmlText, [rootnode: 1], 1, [], '\n', :text}], | ||
[], | ||
resultpath, :undeclared} | ||
end | ||
|
||
test "parse file" do | ||
{document, _} = Exmerl.from_file(fixture_path("test.xml")) | ||
assert document == result("/test/fixtures") | ||
end | ||
|
||
test "parse string" do | ||
doc = File.read!(fixture_path("test.xml")) | ||
{document, _} = Exmerl.from_string(doc) | ||
assert document == result("", char_list: true) | ||
end | ||
|
||
test "parse method given filename" do | ||
{document, _} = Exmerl.parse(fixture_path("test.xml")) | ||
assert document == result("/test/fixtures") | ||
end | ||
|
||
test "parse method given string" do | ||
doc = File.read!(fixture_path("test.xml")) | ||
{document, _} = Exmerl.parse(doc) | ||
assert document == result("", char_list: true) | ||
end | ||
end |