Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve the XML generation: prolog optional, using [] instead of :empty #57

Merged
merged 3 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/saxy.ex
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ defmodule Saxy do
iex> import Saxy.XML
iex> element = element("person", [gender: "female"], "Alice")
{"person", [{"gender", "female"}], [{:characters, "Alice"}]}
iex> Saxy.encode!(element, [])
iex> Saxy.encode!(element, [version: "1.0"])
"<?xml version=\"1.0\"?><person gender=\"female\">Alice</person>"

See `Saxy.XML` for more XML building APIs.
Expand All @@ -100,7 +100,7 @@ defmodule Saxy do
iex> john = %Person{gender: :male, name: "John"}
iex> import Saxy.XML
iex> root = element("people", [], [jack, john])
iex> Saxy.encode!(root, [])
iex> Saxy.encode!(root, [version: "1.0"])
"<?xml version=\"1.0\"?><people><person gender=\"male\">Jack</person><person gender=\"male\">John</person></people>"

"""
Expand Down
34 changes: 33 additions & 1 deletion lib/saxy/encoder.ex
Original file line number Diff line number Diff line change
@@ -1,13 +1,45 @@
defmodule Saxy.Encoder do
@moduledoc false

@doc """
Encode data into a iodata list (merge between list and binary data).

Example:
iex> Saxy.Encoder.encode_to_iodata({"foo", [], []})
[[[60, "foo"], 47, 62]]

iex> Saxy.Encoder.encode_to_iodata({"foo", [{"id", "10"}], []})
[[[60, "foo", 32, "id", 61, 34, "10", 34], 47, 62]]
"""
def encode_to_iodata(root, prolog \\ nil)

def encode_to_iodata(root, nil) do
[element(root)]
end

def encode_to_iodata(root, prolog) do
prolog = prolog(prolog)
element = element(root)

[prolog | element]
end

@doc """
Encode data into a XML string representation.

Example:
iex> Saxy.Encoder.encode_to_binary({"foo", [], []})
"<foo/>"

iex> Saxy.Encoder.encode_to_binary({"foo", [{"id", "10"}], []})
"<foo id=\\"10\\"/>"
"""
def encode_to_binary(root, prolog \\ nil) do
root
|> encode_to_iodata(prolog)
|> IO.iodata_to_binary()
end

defp prolog(%Saxy.Prolog{} = prolog) do
['<?xml', version(prolog.version), encoding(prolog.encoding), standalone(prolog.standalone), '?>']
end
Expand All @@ -34,7 +66,7 @@ defmodule Saxy.Encoder do
[?\s, 'standalone', ?=, ?", "yes", ?"]
end

defp element({tag_name, attributes, :empty}) do
defp element({tag_name, attributes, []}) do
qcam marked this conversation as resolved.
Show resolved Hide resolved
[start_tag(tag_name, attributes), ?/, ?>]
end

Expand Down
2 changes: 1 addition & 1 deletion lib/saxy/xml.ex
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ defmodule Saxy.XML do
{
to_string(name),
attributes(attributes),
:empty
[]
}
end

Expand Down
12 changes: 6 additions & 6 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%{
"earmark": {:hex, :earmark, "1.2.5", "4d21980d5d2862a2e13ec3c49ad9ad783ffc7ca5769cf6ff891a4553fbaae761", [:mix], [], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.19.1", "519bb9c19526ca51d326c060cb1778d4a9056b190086a8c6c115828eaccea6cf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.7", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"makeup": {:hex, :makeup, "0.5.1", "966c5c2296da272d42f1de178c1d135e432662eca795d6dc12e5e8787514edf7", [:mix], [{:nimble_parsec, "~> 0.2.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
"makeup_elixir": {:hex, :makeup_elixir, "0.8.0", "1204a2f5b4f181775a0e456154830524cf2207cf4f9112215c05e0b76e4eca8b", [:mix], [{:makeup, "~> 0.5.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 0.2.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
"nimble_parsec": {:hex, :nimble_parsec, "0.2.2", "d526b23bdceb04c7ad15b33c57c4526bf5f50aaa70c7c141b4b4624555c68259", [:mix], [], "hexpm"},
"stream_data": {:hex, :stream_data, "0.4.2", "fa86b78c88ec4eaa482c0891350fcc23f19a79059a687760ddcf8680aac2799b", [:mix], [], "hexpm"},
"earmark": {:hex, :earmark, "1.2.5", "4d21980d5d2862a2e13ec3c49ad9ad783ffc7ca5769cf6ff891a4553fbaae761", [:mix], [], "hexpm", "c57508ddad47dfb8038ca6de1e616e66e9b87313220ac5d9817bc4a4dc2257b9"},
"ex_doc": {:hex, :ex_doc, "0.19.1", "519bb9c19526ca51d326c060cb1778d4a9056b190086a8c6c115828eaccea6cf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.7", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "dc87f778d8260da0189a622f62790f6202af72f2f3dee6e78d91a18dd2fcd137"},
"makeup": {:hex, :makeup, "0.5.1", "966c5c2296da272d42f1de178c1d135e432662eca795d6dc12e5e8787514edf7", [:mix], [{:nimble_parsec, "~> 0.2.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "259748a45dfcf5f49765a7c29c9594791c82de23e22d7a3e6e59533fe8e8935b"},
"makeup_elixir": {:hex, :makeup_elixir, "0.8.0", "1204a2f5b4f181775a0e456154830524cf2207cf4f9112215c05e0b76e4eca8b", [:mix], [{:makeup, "~> 0.5.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 0.2.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "393d17c5a648e3b30522b2a4743bd1dc3533e1227c8c2823ebe8c3a8e5be5913"},
"nimble_parsec": {:hex, :nimble_parsec, "0.2.2", "d526b23bdceb04c7ad15b33c57c4526bf5f50aaa70c7c141b4b4624555c68259", [:mix], [], "hexpm", "4ababf5c44164f161872704e1cfbecab3935fdebec66c72905abaad0e6e5cef6"},
"stream_data": {:hex, :stream_data, "0.4.2", "fa86b78c88ec4eaa482c0891350fcc23f19a79059a687760ddcf8680aac2799b", [:mix], [], "hexpm", "54d6bf6f1e5e27fbf4a7784a2bffbb993446d0efd079debca0f27bf859c0d1cf"},
}
28 changes: 14 additions & 14 deletions test/saxy/encoder_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ defmodule Saxy.EncoderTest do
document = {
"person",
[{"first_name", "John"}, {"last_name", "Doe"}],
:empty
[]
}

xml = encode(document)
xml = encode(document, version: "1.0")

assert xml == ~s(<?xml version="1.0"?><person first_name="John" last_name="Doe"/>)
end
Expand All @@ -22,22 +22,22 @@ defmodule Saxy.EncoderTest do
content
}

xml = encode(document)
xml = encode(document, version: "1.0")

assert xml == ~s(<?xml version="1.0"?><person first_name="John" last_name="Doe">Hello my name is John Doe</person>)
end

test "encodes attributes with escapable characters" do
xml = encode({"person", [{"first_name", "&'\"<>"}], []})

assert xml == ~s(<?xml version="1.0"?><person first_name="&amp;&apos;&quot;&lt;&gt;"></person>)
assert xml == ~s(<person first_name="&amp;&apos;&quot;&lt;&gt;"/>)
end

test "encodes CDATA" do
children = [{:cdata, "Tom & Jerry"}]

document = {"person", [], children}
xml = encode(document)
xml = encode(document, version: "1.0")

assert xml == ~s(<?xml version="1.0"?><person><![CDATA[Tom & Jerry]]></person>)
end
Expand All @@ -48,7 +48,7 @@ defmodule Saxy.EncoderTest do
]

document = {"movie", [], content}
xml = encode(document)
xml = encode(document, version: "1.0")

assert xml == ~s(<?xml version="1.0"?><movie>Tom &amp; Jerry</movie>)
end
Expand All @@ -61,7 +61,7 @@ defmodule Saxy.EncoderTest do
]

document = {"movie", [], content}
xml = encode(document)
xml = encode(document, [])

assert xml == ~s(<?xml version="1.0"?><movie>&foo;&x3C;&x60;</movie>)
end
Expand All @@ -75,7 +75,7 @@ defmodule Saxy.EncoderTest do
document = {"movie", [], content}
xml = encode(document)

assert xml == ~s(<?xml version="1.0"?><movie><!--This is obviously a comment--><!--A+, A, A- --></movie>)
assert xml == ~s(<movie><!--This is obviously a comment--><!--A+, A, A- --></movie>)
end

test "encodes processing instruction" do
Expand All @@ -84,22 +84,22 @@ defmodule Saxy.EncoderTest do
]

document = {"movie", [], content}
xml = encode(document)
xml = encode(document, version: "1.0")

assert xml == ~s(<?xml version="1.0"?><movie><?xml-stylesheet type="text/xsl" href="style.xsl"?></movie>)
end

test "encodes nested element" do
children = [
{"address", [{"street", "foo"}, {"city", "bar"}], :empty},
{"address", [{"street", "foo"}, {"city", "bar"}], []},
{"gender", [], [{:characters, "male"}]}
]

document = {"person", [{"first_name", "John"}, {"last_name", "Doe"}], children}
xml = encode(document)

assert xml ==
~s(<?xml version="1.0"?><person first_name="John" last_name="Doe"><address street="foo" city="bar"/><gender>male</gender></person>)
~s(<person first_name="John" last_name="Doe"><address street="foo" city="bar"/><gender>male</gender></person>)
end

test "integration with builder" do
Expand All @@ -120,7 +120,7 @@ defmodule Saxy.EncoderTest do
xml =
:rss
|> element([version: "2.0"], items)
|> encode([])
|> encode(version: "1.0")

expected = """
<?xml version="1.0"?>
Expand Down Expand Up @@ -158,10 +158,10 @@ defmodule Saxy.EncoderTest do

xml = "<?xml version=\"1.0\"?>" <> xml

assert encode(document) == xml
assert encode(document, version: "1.0") == xml
end

defp encode(document, prolog \\ []) do
defp encode(document, prolog \\ nil) do
document
|> Saxy.Encoder.encode_to_iodata(prolog)
|> IO.iodata_to_binary()
Expand Down
8 changes: 4 additions & 4 deletions test/saxy/xml_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ defmodule Saxy.XMLTest do

describe "empty_element/2" do
test "generates empty element in simple form" do
assert empty_element("foo", []) == {"foo", [], :empty}
assert empty_element(:foo, []) == {"foo", [], :empty}
assert empty_element("foo", []) == {"foo", [], []}
assert empty_element(:foo, []) == {"foo", [], []}

assert empty_element("foo", a: 1) == {"foo", [{"a", "1"}], :empty}
assert empty_element("foo", %{"a" => 1}) == {"foo", [{"a", "1"}], :empty}
assert empty_element("foo", a: 1) == {"foo", [{"a", "1"}], []}
assert empty_element("foo", %{"a" => 1}) == {"foo", [{"a", "1"}], []}
end
end

Expand Down
5 changes: 3 additions & 2 deletions test/saxy_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ defmodule SaxyTest do
}

doctest Saxy
doctest Saxy.Encoder

test "parse_string/3 parses a XML document binary" do
data = File.read!("./test/support/fixture/food.xml")
Expand Down Expand Up @@ -272,7 +273,7 @@ defmodule SaxyTest do

test "encodes XML document into string" do
root = element("foo", [], "foo")
assert Saxy.encode!(root) == ~s(<?xml version="1.0"?><foo>foo</foo>)
assert Saxy.encode!(root, version: "1.0") == ~s(<?xml version="1.0"?><foo>foo</foo>)
end
end

Expand All @@ -281,7 +282,7 @@ defmodule SaxyTest do

test "encodes XML document into IO data" do
root = element("foo", [], "foo")
assert xml = Saxy.encode_to_iodata!(root)
assert xml = Saxy.encode_to_iodata!(root, version: "1.0")
assert is_list(xml)
assert IO.iodata_to_binary(xml) == ~s(<?xml version="1.0"?><foo>foo</foo>)
end
Expand Down