使用erlang进行Ejabberd数据包解析

时间:2015-09-21 10:02:11

标签: erlang ejabberd

Ejabberd服务器收到这样的数据包:

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

我想从此数据包中获取数据。 需要的数据:类型,如果正文有某个参数,请说{<<"xml:lang">>,<<"en">>} 我正在做以下操作:

  {_XMLEL, TYPE, DETAILS , _BODY} = Packet

这为我提供了类型:<<"message">><<"iq">><<"presence">>

检查DETAILS是否有{<<"xml:lang">>,<<"en">>}我这样做:

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

有没有更好的方法呢? 我还需要数据包中的tofrom属性。

1 个答案:

答案 0 :(得分:2)

在功能头中使用模式匹配的组合以及折叠细节以提取您需要的所有内容。

下面的函数返回一个键值元组列表,其中<<"type">>元组是人为创建的,因此列表是同质的:

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(_) -> [].

第一个子句与{xmlel, ...}元组匹配,提取TypeDetails。返回值包含一个头部{<<"type">>,Type}的列表,后面是一个尾部,该尾部是通过折叠要从Details中提取的键列表形成的。第二个子句匹配任何不是{xmlel, ...}元组的东西,只返回空列表。

将此函数放入名为z的模块中并将其传递给您的数据:

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">>}]