使用 erlang 解析 Ejabberd 数据包

Ejabberd Packet parsing using erlang

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 属性。

结合使用函数头中的模式匹配和折叠细节来提取您需要的一切。

return下面的函数是一个键值元组列表,其中 <<"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。 return 值由一个列表组成,头部 {<<"type">>,Type} 后跟一个尾部,该尾部由折叠要从 Details 中提取的键列表形成。第二个子句匹配任何不是 {xmlel, ...} 元组的东西,只是 return 空列表。

将此函数放入名为 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">>}]