richa_v
richa_v

Reputation: 129

Ejabberd Packet parsing using erlang

Ejabberd server receives packet like this:

  {xmlel,<<"message">>,[{<<"from">>,<<"user1@localhost/resource">>},{<<"to">>,<<"user2@localhost">>},{<<"xml:lang">>,<<"en">>},{<<"id">>,<<"947yW-9">>}],[{xmlcdata,<<">">>},{xmlel,<<"body">>,[],[{xmlcdata,<<"Helllo wassup!">>}]}]}

I want to fetch data from this packet. Needed data : Type, If the body has a certain parameter, say {<<"xml:lang">>,<<"en">>} I am doing the following operations:

  {_XMLEL, TYPE, DETAILS , _BODY} = Packet

This provides me the type : <<"message">> or <<"iq">> or <<"presence">>.

To check if DETAILS has {<<"xml:lang">>,<<"en">>} I do this:

 Has_Attribute=lists:member({<<"xml:lang">>,<<"en">>},DETAILS)

Is there any better way to do this? I also need the to and from attributes from the packet.

Upvotes: 1

Views: 380

Answers (1)

Steve Vinoski
Steve Vinoski

Reputation: 20004

Use a combination of pattern matching in the function head together with a fold over the details to extract everything you need.

The function below returns a list of key-value tuples, where the <<"type">> tuple is artificially created so the list is homogenous:

extract({xmlel, Type, Details, _}) ->
    [{<<"type">>,Type} |
     lists:foldl(fun(Key, Acc) ->
                         case lists:keyfind(Key, 1, Details) of
                             false -> Acc;
                             Pair -> [Pair|Acc]
                         end
                 end, [], [<<"from">>,<<"to">>,<<"xml:lang">>])];
extract(_) -> [].

The first clause matches the {xmlel, ...} tuple, extracting Type and Details. The return value consists of a list with head {<<"type">>,Type} followed by a tail formed from folding over the list of keys to be extracted from Details. The second clause matches anything not a {xmlel, ...} tuple and just returns the empty list.

Putting this function into a module named z and passing it your data:

1> z:extract({xzlel,<<"message">>,[{<<"from">>,<<"user1@localhost/resource">>},{<<"to">>,<<"user2@localhost">>},{<<"xml:lang">>,<<"en">>},{<<"id">>,<<"947yW-9">>}],[{xmlcdata,<<">">>},{xmlel,<<"body">>,[],[{xmlcdata,<<"Helllo wassup!">>}]}]}).
[{<<"type">>,<<"message">>},
 {<<"xml:lang">>,<<"en">>},
 {<<"to">>,<<"user2@localhost">>},
 {<<"from">>,<<"user1@localhost/resource">>}]

Upvotes: 2

Related Questions