Use erlang XMPP library from Elixir
First, records used in erlang XMPP library are defined in ./include/*.hrl. We need to import them into Elixir like this:
defmodule A do
require Record
Record.defrecord :jid, Record.extract(:jid, from: "deps/xmpp/include/jid.hrl")
Record.defrecord :presence, Record.extract(:presence, from: "deps/xmpp/include/xmpp_codec.hrl") end
Then you will have a A.jid record in Elixir matching the same one in erlang. To use erlang function, it is easy to call something like this:
user = "user@localhost/home"
x = :jid.decode(user)
Logger.info(inspect x)
It is easier to construct a jid like this:
iex > j = :jid.make({"user", "localhost", "home"})
{:jid, "user", "localhost", "home", "user", "localhost", "home"}
iex > j.encode()
"user@localhost/home"
Let’s try some xml:
iex(9)> p = "<presence type='unavailable' to='xmpp@localhost/home' from='user@localhost'/>"
"<presence type='unavailable' to='xmpp@localhost/home' from='user@localhost'/>"
iex(10)> f = :fxml_stream.parse_element(p)
{:xmlel, "presence",
[
{"type", "unavailable"},
{"to", "xmpp@localhost/home"},
{"from", "user@localhost"}
], []}
iex(11)> :xmpp.decode(f)
{:presence, "", :unavailable, "",
{:jid, "user", "localhost", "", "user", "localhost", ""},
{:jid, "xmpp", "localhost", "home", "xmpp",
"localhost", "home"}, :undefined, [],
:undefined, [], %{}}
It is necessary to parse raw XML first by fast_xml, then fed into erlang xmpp library, which turns everything into erlang xmpp records.
Create new XML like this
iex > unavailable = {:presence, "", :unavailable, "", nil, nil, :undefined, [], :undefined, [], %{}}
{:presence, "", :unavailable, "", nil, nil, :undefined, [], :undefined, [], %{}}
iex > presence = unavailable |> :xmpp.set_from(:jid.decode("user@server/resource")) |> :xmpp.set_to(:jid.decode("xmpp
@server/resource"))
{:presence, "", :unavailable, "",
{:jid, "user", "server", "resource", "user", "server", "resource"},
{:jid, "xmpp", "server", "resource", "xmpp", "server", "resource"}, :undefined,
[], :undefined, [], %{}}
iex > xlm = :xmpp.encode(presence)
{:xmlel, "presence",
[
{"to", "xmpp@server/resource"},
{"from", "user@server/resource"},
{"type", "unavailable"},
{"xmlns", "jabber:client"}
], []}
iex > :fxml.element_to_binary(xlm)
"<presence to='xmpp@server/resource' from='user@server/resource' type='unavailable' xmlns='jabber:client'/>"
In such way, we can have XML ready to send to server.
There are still some other issues. For example, it would to be nice to have a better way to create new Record without type-in all fields. Retrieving value by field name of record would be nice than using elem as tuple. But I cannot find good solutions yet.