使用 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)
有没有更好的方法来做到这一点?
我还需要数据包中的 to
和 from
属性。
结合使用函数头中的模式匹配和折叠细节来提取您需要的一切。
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, ...}
元组,提取 Type
和 Details
。 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">>}]
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)
有没有更好的方法来做到这一点?
我还需要数据包中的 to
和 from
属性。
结合使用函数头中的模式匹配和折叠细节来提取您需要的一切。
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, ...}
元组,提取 Type
和 Details
。 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">>}]