diff options
Diffstat (limited to 'src/web/xmpp_json.erl')
-rw-r--r-- | src/web/xmpp_json.erl | 691 |
1 files changed, 373 insertions, 318 deletions
diff --git a/src/web/xmpp_json.erl b/src/web/xmpp_json.erl index 6fae2ab08..258d573cc 100644 --- a/src/web/xmpp_json.erl +++ b/src/web/xmpp_json.erl @@ -1,8 +1,8 @@ %%%---------------------------------------------------------------------- %%% File : xmpp_json.erl %%% Author : Eric Cestari <ecestari@process-one.net> -%%% Purpose : Converts {xmlelement,Name, A, Sub} to/from JSON as per protoxep -%%% Created : 09-20-2010 +%%% Purpose : Converts {xmlelement,Name, A, Sub} to/from JSON as per protoxep +%%% Created : 09-20-2010 %%% %%% %%% ejabberd, Copyright (C) 2002-2010 ProcessOne @@ -22,341 +22,396 @@ %%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA %%% 02111-1307 USA --module (xmpp_json). +-module(xmpp_json). -export([to_json/1, from_json/1]). +-include("jlib.hrl"). - %%% FROM JSON TO XML -from_json({struct, [{<<"stream">>, _Attr}]=Elems}) -> - parse_start(Elems); - -from_json({struct, Elems}) -> - {xmlstreamelement, hd(from_json2({struct, Elems}))}. - -from_json2({struct, Elems}) -> - lists:map(fun parse_json/1, Elems). - -parse_start([{BinName, {struct, JAttrs}}]) -> - Name = binary_to_list(BinName), - {FullName, Attrs} = lists:foldl( - fun({<<"xml">>, {struct, XML}}, {N, Attrs}) -> - XmlAttrs = parse_json_special_attrs("xml", XML), - {N, lists:merge(Attrs, XmlAttrs)}; - ({<<"xmlns">>, {struct, XMLNS}}, {N, Attrs}) -> - XmlNsAttrs = parse_json_special_attrs("xmlns", XMLNS), - {N, lists:merge(Attrs, XmlNsAttrs)}; - ({<<"$$">>, BaseNS}, {N, Attrs})-> - {binary_to_list(BaseNS)++":"++N, Attrs}; - ({Key, Value}, {N, Attrs})-> - {N, [{ib2tol(Key), ib2tol(Value)}|Attrs]} - end, {Name, []}, JAttrs), - {xmlstreamstart, FullName, Attrs}. - -parse_json({Name, CData}) when is_binary(CData)-> - {xmlelement, binary_to_list(Name), [], [{xmlcdata, CData}]}; - -parse_json({Name, CDatas}) when is_list(CDatas)-> - lists:map(fun(CData)-> - {xmlelement, binary_to_list(Name), [], [{xmlcdata, CData}]} - end, CDatas); - -parse_json({BinName, {struct, JAttrs}}) -> - Name = binary_to_list(BinName), - {FullName, Attrs, SubEls} = lists:foldl( - fun({<<"$">>, Cdata}, {N, Attrs, _SubEls}) when is_binary(Cdata)-> - {N, Attrs, [{xmlcdata, Cdata}]}; - ({<<"$">>, {struct, Elems}}, {N, Attrs, _SubEls}) -> - SE = lists:map(fun parse_json/1, Elems), - {N, Attrs, lists:flatten(SE)}; % due to 4.2.3.3 - ({<<"xml">>, {struct, XML}}, {N, Attrs, SubEls}) -> - XmlAttrs = parse_json_special_attrs("xml", XML), - {N, lists:merge(Attrs, XmlAttrs), SubEls}; - ({<<"xmlns">>, {struct, XMLNS}}, {N, Attrs, SubEls}) -> - XmlNsAttrs = parse_json_special_attrs("xmlns", XMLNS), - {N, lists:merge(Attrs, XmlNsAttrs), SubEls}; - ({Key, {struct, []}}, {N, Attrs, SubEls})-> - {N, Attrs, [{xmlelement, ib2tol(Key), [], []}|SubEls]}; - ({Key, Value}, {N, Attrs, SubEls})-> - {N, [{binary_to_list(Key), ib2tol(Value)}|Attrs], SubEls} - end, {Name, [], []}, JAttrs), - {xmlelement, FullName, Attrs, SubEls}. - -parse_json_special_attrs(Prefix, XMLNS)-> - lists:reverse(lists:map( - fun({<<"$">>, Value})-> - {Prefix, ib2tol(Value)}; - ({<<"@",NS/binary>>, Value})-> - {Prefix ++ ":"++binary_to_list(NS), ib2tol(Value)} - end, XMLNS)). - -%%% FROM XML TO JSON -to_json({xmlstreamelement, XMLElement})-> - to_json(XMLElement); -to_json({xmlelement, _Name, [], []})-> - {struct, []}; -to_json({xmlelement, Name, [], [{xmlcdata, Cdata}]})-> - {SName, JsonAttrs2} = parse_namespace(Name, []), - {struct, [{SName, Cdata}|JsonAttrs2]}; -to_json({xmlstreamstart, Name, Attrs})-> - JsonAttrs = parse_attrs(Attrs), - {SName, Members2} = parse_namespace(Name, JsonAttrs), - {struct, [{SName, {struct, Members2}}]}; -to_json({xmlelement, Name, Attrs, SubEls})-> - JsonAttrs = parse_attrs(Attrs), - Members = case parse_subels(SubEls) of - [] -> - JsonAttrs; - [Elem] -> - [{<<"$">>,Elem}|JsonAttrs]; - Elems -> - [{<<"$">>,Elems}|JsonAttrs] - end, - {SName, Members2} = parse_namespace(Name, Members), - {struct, [{SName, {struct, Members2}}]}. - -parse_namespace(Name, AttrsList)-> - {l2b(Name), AttrsList}. - -parse_subels([{xmlcdata, Cdata}])-> - l2b(Cdata); -parse_subels([])-> - []; -parse_subels(SubEls)-> - {struct, lists:reverse(lists:foldl( - fun({xmlelement, SName, [], [{xmlcdata, UCdata}]}, Acc)-> - Cdata = l2b(UCdata), - Name = l2b(SName), - case lists:keyfind(Name, 1, Acc) of - {Name, PrevCdata} when is_binary(PrevCdata) -> - Acc1 = lists:keydelete(Name, 1, Acc), - [{Name,[PrevCdata, Cdata]} | Acc1]; - {Name, CDatas} when is_list(CDatas) -> - Acc1 = lists:keydelete(Name, 1, Acc), - [{Name,lists:append(CDatas, [Cdata])} | Acc1]; - _ -> - [{Name, Cdata}| Acc] - end; - ({xmlelement, SName, _, _} = Elem, Acc) -> - E = case to_json(Elem) of %TODO There could be a better way to iterate - {struct, [{_, ToKeep}]} -> ToKeep; - {struct, []} = Empty -> Empty - end, - [{l2b(SName), E}|Acc]; - ({xmlcdata,<<"\n">>}, Acc) -> - Acc - end,[], SubEls))}. - - -parse_attrs(XmlAttrs)-> - {Normal, XMLNS} = lists:foldl( - fun({"xmlns", NS}, {Attrs, XMLNS}) -> - {Attrs,[{<<"$">>, l2b(NS)}| XMLNS]}; - ({"xmlns:" ++ Short, NS}, {Attrs, XMLNS})-> - AttrName = iolist_to_binary([<<"@">>,l2b(Short)]), - {Attrs,[{AttrName, list_to_binary(NS)}| XMLNS]}; - ({"xml:" ++ Short, Val}, {Attrs, XMLNS})-> - % TODO currently tolerates only one xml:* attr per element - AttrName = iolist_to_binary([<<"@">>,l2b(Short)]), - {[{<<"xml">>,{struct, [{AttrName, l2b(Val)}]}}|Attrs], XMLNS}; - ({K, V}, {Attrs, XMLNS})-> - {[{l2b(K), l2b(V)}|Attrs], XMLNS} - end,{[], []}, XmlAttrs), - - case XMLNS of - [{<<"$">>, NS}]-> - [{<<"xmlns">>, NS}|Normal]; - []-> - Normal; - _ -> - [{<<"xmlns">>,{struct, XMLNS} }| Normal] - end. - -l2b(List) when is_list(List) -> list_to_binary(List); -l2b(Bin) when is_binary(Bin) -> Bin. - -ib2tol(Bin) when is_binary(Bin) -> binary_to_list(Bin ); -ib2tol(Integer) when is_integer(Integer) -> integer_to_list(Integer); -ib2tol(List) when is_list(List) -> List. +from_json({[{<<"stream">>, _Attr}] = Elems}) -> + parse_start(Elems); +from_json({Elems}) -> + {xmlstreamelement, hd(from_json2({Elems}))}. + +from_json2({Elems}) -> + lists:map(fun parse_json/1, Elems). + +parse_start([{BinName, {JAttrs}}]) -> + Name = (BinName), + {FullName, Attrs} = lists:foldl(fun ({<<"xml">>, + {XML}}, + {N, Attrs}) -> + XmlAttrs = + parse_json_special_attrs(<<"xml">>, + XML), + {N, lists:merge(Attrs, XmlAttrs)}; + ({<<"xmlns">>, {XMLNS}}, + {N, Attrs}) -> + XmlNsAttrs = + parse_json_special_attrs(<<"xmlns">>, + XMLNS), + {N, lists:merge(Attrs, XmlNsAttrs)}; + ({<<"$$">>, BaseNS}, {N, Attrs}) -> + {<<((BaseNS))/binary, ":", + N/binary>>, + Attrs}; + ({Key, Value}, {N, Attrs}) -> + {N, + [{ib2tol(Key), ib2tol(Value)} + | Attrs]} + end, + {Name, []}, JAttrs), + {xmlstreamstart, FullName, Attrs}. + +parse_json({Name, CData}) when is_binary(CData) -> + #xmlel{name = (Name), attrs = [], + children = [{xmlcdata, CData}]}; +parse_json({Name, CDatas}) when is_list(CDatas) -> + lists:map(fun (CData) -> + #xmlel{name = (Name), attrs = [], + children = [{xmlcdata, CData}]} + end, + CDatas); +parse_json({BinName, {JAttrs}}) -> + Name = (BinName), + {FullName, Attrs, SubEls} = lists:foldl(fun ({<<"$">>, + Cdata}, + {N, Attrs, _SubEls}) + when is_binary(Cdata) -> + {N, Attrs, + [{xmlcdata, Cdata}]}; + ({<<"$">>, {Elems}}, + {N, Attrs, _SubEls}) -> + SE = + lists:map(fun parse_json/1, + Elems), + {N, Attrs, + lists:flatten(SE)}; + ({<<"xml">>, {XML}}, + {N, Attrs, SubEls}) -> + XmlAttrs = + parse_json_special_attrs(<<"xml">>, + XML), + {N, + lists:merge(Attrs, + XmlAttrs), + SubEls}; + ({<<"xmlns">>, {XMLNS}}, + {N, Attrs, SubEls}) -> + XmlNsAttrs = + parse_json_special_attrs(<<"xmlns">>, + XMLNS), + {N, + lists:merge(Attrs, + XmlNsAttrs), + SubEls}; + ({Key, {[]}}, + {N, Attrs, SubEls}) -> + {N, Attrs, + [#xmlel{name = ib2tol(Key), + attrs = [], + children = []} + | SubEls]}; + ({Key, Value}, + {N, Attrs, SubEls}) -> + {N, + [{(Key), ib2tol(Value)} + | Attrs], + SubEls} + end, + {Name, [], []}, JAttrs), + #xmlel{name = FullName, attrs = Attrs, + children = SubEls}. + +parse_json_special_attrs(Prefix, XMLNS) -> + lists:reverse(lists:map(fun ({<<"$">>, Value}) -> + {Prefix, ib2tol(Value)}; + ({<<"@", NS/binary>>, Value}) -> + {<<Prefix/binary, ":", ((NS))/binary>>, + ib2tol(Value)} + end, + XMLNS)). + +to_json({xmlstreamelement, XMLElement}) -> + to_json(XMLElement); +to_json(#xmlel{attrs = [], children = []}) -> + {[]}; +to_json(#xmlel{name = Name, attrs = [], + children = [{xmlcdata, Cdata}]}) -> + {SName, JsonAttrs2} = parse_namespace(Name, []), + {[{SName, Cdata} | JsonAttrs2]}; +to_json({xmlstreamstart, Name, Attrs}) -> + JsonAttrs = parse_attrs(Attrs), + {SName, Members2} = parse_namespace(Name, JsonAttrs), + {[{SName, {Members2}}]}; +to_json(#xmlel{name = Name, attrs = Attrs, + children = SubEls}) -> + JsonAttrs = parse_attrs(Attrs), + Members = case parse_subels(SubEls) of + [] -> JsonAttrs; + Elems -> [{<<"$">>, Elems} | JsonAttrs] + end, + {SName, Members2} = parse_namespace(Name, Members), + {[{SName, {Members2}}]}. + +parse_namespace(Name, AttrsList) -> + {Name, AttrsList}. + +parse_subels([{xmlcdata, Cdata}]) -> Cdata; +parse_subels([]) -> []; +parse_subels(SubEls) -> + {lists:reverse(lists:foldl(fun (#xmlel{name = SName, + attrs = [], + children = [{xmlcdata, UCdata}]}, + Acc) -> + Cdata = UCdata, + Name = SName, + case lists:keyfind(Name, 1, Acc) of + {Name, PrevCdata} + when is_binary(PrevCdata) -> + Acc1 = lists:keydelete(Name, 1, + Acc), + [{Name, [PrevCdata, Cdata]} + | Acc1]; + {Name, CDatas} + when is_list(CDatas) -> + Acc1 = lists:keydelete(Name, 1, + Acc), + [{Name, + lists:append(CDatas, [Cdata])} + | Acc1]; + _ -> [{Name, Cdata} | Acc] + end; + (#xmlel{name = SName} = Elem, Acc) -> + E = case to_json(Elem) of + {[{_, ToKeep}]} -> ToKeep; + {[]} = Empty -> Empty + end, + [{SName, E} | Acc]; + ({xmlcdata, <<"\n">>}, Acc) -> Acc + end, + [], SubEls))}. + +parse_attrs(XmlAttrs) -> + {Normal, XMLNS} = lists:foldl(fun ({<<"xmlns">>, NS}, + {Attrs, XMLNS}) -> + {Attrs, [{<<"$">>, NS} | XMLNS]}; + ({<<"xmlns:", Short/binary>>, NS}, + {Attrs, XMLNS}) -> + AttrName = <<$@, Short/binary>>, + {Attrs, + [{AttrName, NS} + | XMLNS]}; + ({<<"xml:", Short/binary>>, Val}, + {Attrs, XMLNS}) -> + AttrName = <<$@, Short/binary>>, + {[{<<"xml">>, + {[{AttrName, Val}]}} + | Attrs], + XMLNS}; + ({K, V}, {Attrs, XMLNS}) -> + {[{K, V} | Attrs], XMLNS} + end, + {[], []}, XmlAttrs), + case XMLNS of + [{<<"$">>, NS}] -> [{<<"xmlns">>, NS} | Normal]; + [] -> Normal; + _ -> [{<<"xmlns">>, {XMLNS}} | Normal] + end. + +ib2tol(Bin) when is_binary(Bin) -> Bin; +ib2tol(Integer) when is_integer(Integer) -> + jlib:integer_to_binary(Integer). %% %% Tests %% erlc -DTEST web/xmpp_json.erl && erl -pa web/ -run xmpp_json test -run init stop -noshell -include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). -% 4.2.3.1 Tag with text value -to_text_value_test()-> - In = {xmlstreamelement, {xmlelement, "tag", [], [{xmlcdata, <<"txt-value">>}]}}, - Out = {struct, [{<<"tag">>, <<"txt-value">>}]}, - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - -% 4.2.3.2 Tag with recursive tags -to_tag_with_recursive_tags_test()-> - In = {xmlstreamelement, {xmlelement, "tag", [], - [{xmlelement,"tag2",[], [{xmlcdata, <<"txt-value">>}]}, - {xmlelement,"tag3",[], [ - {xmlelement,"tag4",[], [{xmlcdata, <<"txt2-value">>}]}]}]}}, - Out = {struct, [{<<"tag">>, - {struct, [{<<"$">>, - {struct, [ - {<<"tag2">>,<<"txt-value">>}, - {<<"tag3">>,{struct, [{<<"$">>,{struct, [{<<"tag4">>,<<"txt2-value">>}]}}]}} - ]} - }]} - }] - }, - %io:format("~n~p", [list_to_binary(mochijson2:encode(to_json(In)))]), - io:format("~n~p", [from_json(Out)]), - io:format("~n~p", [to_json(In)]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - -% 4.2.3.3 Multiple text value tags as array -multiple_text_value_tags_as_array_test()-> - In = {xmlstreamelement, {xmlelement, "tag", [], [ - {xmlelement,"tag2",[], [ - {xmlcdata, <<"txt-value">>}]}, - {xmlelement,"tag2",[], [ - {xmlcdata, <<"txt-value2">>}]}]}}, - Out = {struct, [{<<"tag">>, - {struct, [{<<"$">>, - {struct, [{<<"tag2">>, - [<<"txt-value">>, <<"txt-value2">>]}]} - }]} - }] - }, - io:format("~p~n", [to_json(In)]), - io:format("~p~n", [from_json(Out)]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - -% 4.2.3.4 Tag with attribute, no value +to_text_value_test() -> + In = {xmlstreamelement, + #xmlel{name = <<"tag">>, attrs = [], + children = [{xmlcdata, <<"txt-value">>}]}}, + Out = {[{<<"tag">>, <<"txt-value">>}]}, + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + +to_tag_with_recursive_tags_test() -> + In = {xmlstreamelement, + #xmlel{name = <<"tag">>, attrs = [], + children = + [#xmlel{name = <<"tag2">>, attrs = [], + children = [{xmlcdata, <<"txt-value">>}]}, + #xmlel{name = <<"tag3">>, attrs = [], + children = + [#xmlel{name = <<"tag4">>, attrs = [], + children = + [{xmlcdata, + <<"txt2-value">>}]}]}]}}, + Out = {[{<<"tag">>, + {[{<<"$">>, + {[{<<"tag2">>, <<"txt-value">>}, + {<<"tag3">>, + {[{<<"$">>, + {[{<<"tag4">>, <<"txt2-value">>}]}}]}}]}}]}}]}, + io:format("~n~p", [from_json(Out)]), + io:format("~n~p", [to_json(In)]), + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + +multiple_text_value_tags_as_array_test() -> + In = {xmlstreamelement, + #xmlel{name = <<"tag">>, attrs = [], + children = + [#xmlel{name = <<"tag2">>, attrs = [], + children = [{xmlcdata, <<"txt-value">>}]}, + #xmlel{name = <<"tag2">>, attrs = [], + children = [{xmlcdata, <<"txt-value2">>}]}]}}, + Out = {[{<<"tag">>, + {[{<<"$">>, + {[{<<"tag2">>, + [<<"txt-value">>, <<"txt-value2">>]}]}}]}}]}, + io:format("~p~n", [to_json(In)]), + io:format("~p~n", [from_json(Out)]), + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + tag_attr_no_value_test() -> - In = {xmlstreamelement, {xmlelement, "tag", [{"attr", "attr-value"}], []}}, - Out = {struct, [{<<"tag">>, {struct, [ - {<<"attr">>,<<"attr-value">>} - ]}}]}, - io:format("~p", [list_to_binary(mochijson2:encode(to_json(In)))]), - io:format("~p", [from_json(Out)]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - + In = {xmlstreamelement, + #xmlel{name = <<"tag">>, + attrs = [{<<"attr">>, <<"attr-value">>}], + children = []}}, + Out = {[{<<"tag">>, + {[{<<"attr">>, <<"attr-value">>}]}}]}, + io:format("~s", [jiffy:encode(to_json(In))]), + io:format("~p", [from_json(Out)]), + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + % 4.2.3.5 Tag with multiple attributes as array, no value % Not wellformed XML. % 4.2.3.6 Tags as array with unique attributes, no value +tag_with_namespace_no_value_test() -> + In = {xmlstreamelement, + #xmlel{name = <<"tag">>, + attrs = [{<<"xmlns:ns">>, <<"ns-value">>}], + children = []}}, + Out = {[{<<"tag">>, + {[{<<"xmlns">>, + {[{<<"@ns">>, <<"ns-value">>}]}}]}}]}, + io:format("~s", [jiffy:encode(to_json(In))]), + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + +two_namespaces_tag_no_value_test() -> + In = {xmlstreamelement, + #xmlel{name = <<"tag">>, + attrs = + [{<<"xmlns:ns">>, <<"ns-value">>}, + {<<"xmlns">>, <<"root-value">>}], + children = []}}, + Out = {[{<<"tag">>, + {[{<<"xmlns">>, + {[{<<"$">>, <<"root-value">>}, + {<<"@ns">>, <<"ns-value">>}]}}]}}]}, + io:format("~s", [jiffy:encode(to_json(In))]), + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + +namespaced_tag_no_value_test() -> + In = {xmlstreamelement, + #xmlel{name = <<"ns:tag">>, + attrs = [{<<"attr">>, <<"attr-value">>}], + children = []}}, + Out = {[{<<"ns:tag">>, + {[{<<"attr">>, <<"attr-value">>}]}}]}, + io:format("~s", [jiffy:encode(to_json(In))]), + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). -% 4.2.3.7 Tag with namespace attribute, no value -tag_with_namespace_no_value_test()-> - In = {xmlstreamelement, {xmlelement, "tag", [{"xmlns:ns", "ns-value"}], []}}, - Out = {struct, [{<<"tag">>, {struct, [ - {<<"xmlns">>,{struct, [{<<"@ns">>, <<"ns-value">>}]}} - ]}}]}, - io:format("~p", [list_to_binary(mochijson2:encode(to_json(In)))]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - - -% 4.2.3.8 Tag with many attributes to namespace, no value -two_namespaces_tag_no_value_test()-> - In = {xmlstreamelement,{xmlelement, "tag", [{"xmlns:ns", "ns-value"}, - {"xmlns", "root-value"}], []}}, - Out = {struct, [{<<"tag">>, {struct, [ - {<<"xmlns">>,{struct, [ - {<<"$">>, <<"root-value">>}, - {<<"@ns">>, <<"ns-value">>}]}} - ]}}]}, - io:format("~p", [list_to_binary(mochijson2:encode(to_json(In)))]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - -% 4.2.3.9 Tag with namespace attribute, no value -% Removed namespace handling. More complex on both sides. -namespaced_tag_no_value_test()-> - In = {xmlstreamelement,{xmlelement, "ns:tag", [{"attr", "attr-value"}], []}}, - Out = {struct, [{<<"ns:tag">>, {struct, [ - {<<"attr">>,<<"attr-value">>} - ]}}]}, - io:format("~p", [list_to_binary(mochijson2:encode(to_json(In)))]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - -% 4.2.3.10 Tag with attribute and text value -tag_with_attribute_and_value_test()-> - In = {xmlstreamelement,{xmlelement, "tag", [{"attr", "attr-value"}], - [{xmlcdata, <<"txt-value">>}]}}, - Out = {struct, [{<<"tag">>, {struct, [ - {<<"$">>, <<"txt-value">>}, - {<<"attr">>,<<"attr-value">>} - ]}}]}, - %io:format("~p", [list_to_binary(mochijson2:encode(to_json(In)))]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - -% 4.2.3.11 Namespace tag with attribute and text value -% Removed namespace handling. More complex on both sides -namespaced_tag_with_value_test()-> - In = {xmlstreamelement,{xmlelement, "ns:tag", [{"attr", "attr-value"}], [{xmlcdata, <<"txt-value">>}]}}, - Out = {struct, [{<<"ns:tag">>, {struct, [ - {<<"$">>,<<"txt-value">>}, - {<<"attr">>,<<"attr-value">>} - ]}}]}, - io:format("~p", [list_to_binary(mochijson2:encode(to_json(In)))]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - -xml_lang_attr_test()-> - In = {xmlstreamelement,{xmlelement, "tag", [{"xml:lang", "en"}], []}}, - Out = {struct, [{<<"tag">>, {struct, [ - {<<"xml">>,{struct,[{<<"@lang">>,<<"en">>}]}} - ]}}]}, - io:format("~p", [list_to_binary(mochijson2:encode(to_json(In)))]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - -xmlns_tag_with_value_test()-> - Out = {struct,[{<<"response">>, - {struct,[{<<"$">>,<<"dXNlcm5hbWU9I">>}, - {<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}]}} - ]}, - Out2 = {struct,[{<<"response">>, - {struct,[{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}, - {<<"$">>,<<"dXNlcm5hbWU9I">>} - ]}} - ]}, - In = {xmlstreamelement,{xmlelement,"response", - [{"xmlns","urn:ietf:params:xml:ns:xmpp-sasl"}], - [{xmlcdata, <<"dXNlcm5hbWU9I">>}]}}, - io:format("~p", [list_to_binary(mochijson2:encode(to_json(In)))]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)), - ?assertEqual(In, from_json(Out2)). - -no_attr_no_value_test()-> - In = {xmlstreamelement, {xmlelement,"failure", - [{"xmlns","urn:ietf:params:xml:ns:xmpp-sasl"}], - [{xmlelement,"not-authorized",[],[]}]}}, - Out = {struct, [{<<"failure">>,{struct, [ - {<<"$">>, {struct, [{<<"not-authorized">>, {struct, []}}]}}, - {<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>} - ]}}]}, - io:format("~p", [list_to_binary(mochijson2:encode(to_json(In)))]), +tag_with_attribute_and_value_test() -> + In = {xmlstreamelement, + #xmlel{name = <<"tag">>, + attrs = [{<<"attr">>, <<"attr-value">>}], + children = [{xmlcdata, <<"txt-value">>}]}}, + Out = {[{<<"tag">>, + {[{<<"$">>, <<"txt-value">>}, + {<<"attr">>, <<"attr-value">>}]}}]}, + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + +namespaced_tag_with_value_test() -> + In = {xmlstreamelement, + #xmlel{name = <<"ns:tag">>, + attrs = [{<<"attr">>, <<"attr-value">>}], + children = [{xmlcdata, <<"txt-value">>}]}}, + Out = {[{<<"ns:tag">>, + {[{<<"$">>, <<"txt-value">>}, + {<<"attr">>, <<"attr-value">>}]}}]}, + io:format("~s", [jiffy:encode(to_json(In))]), + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + +xml_lang_attr_test() -> + In = {xmlstreamelement, + #xmlel{name = <<"tag">>, + attrs = [{<<"xml:lang">>, <<"en">>}], children = []}}, + Out = {[{<<"tag">>, + {[{<<"xml">>, {[{<<"@lang">>, <<"en">>}]}}]}}]}, + io:format("~s", [jiffy:encode(to_json(In))]), + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + +xmlns_tag_with_value_test() -> + Out = {[{<<"response">>, + {[{<<"$">>, <<"dXNlcm5hbWU9I">>}, + {<<"xmlns">>, + <<"urn:ietf:params:xml:ns:xmpp-sasl">>}]}}]}, + Out2 = {[{<<"response">>, + {[{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}, + {<<"$">>, <<"dXNlcm5hbWU9I">>}]}}]}, + In = {xmlstreamelement, + #xmlel{name = <<"response">>, + attrs = + [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}], + children = [{xmlcdata, <<"dXNlcm5hbWU9I">>}]}}, + io:format("~s", [jiffy:encode(to_json(In))]), + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))), + ?assertEqual(In, (from_json(Out2))). + +no_attr_no_value_test() -> + In = {xmlstreamelement, + #xmlel{name = <<"failure">>, + attrs = + [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-sasl">>}], + children = + [#xmlel{name = <<"not-authorized">>, attrs = [], + children = []}]}}, + Out = {[{<<"failure">>, + {[{<<"$">>, + {[{<<"not-authorized">>, {[]}}]}}, + {<<"xmlns">>, + <<"urn:ietf:params:xml:ns:xmpp-sasl">>}]}}]}, + io:format("~s", [jiffy:encode(to_json(In))]), io:format("~p~n", [to_json(In)]), io:format("~p~n", [from_json(Out)]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). - -xmlstream_test()-> - In = {xmlstreamstart, "stream", [{"xml:lang", "en"}]}, - Out = {struct, [{<<"stream">>, {struct, [ - {<<"xml">>,{struct,[{<<"@lang">>,<<"en">>}]}} - ]}}]}, - io:format("~p", [list_to_binary(mochijson2:encode(to_json(In)))]), - ?assertEqual(Out, to_json(In)), - ?assertEqual(In, from_json(Out)). --endif.
\ No newline at end of file + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + +xmlstream_test() -> + In = {xmlstreamstart, <<"stream">>, + [{<<"xml:lang">>, <<"en">>}]}, + Out = {[{<<"stream">>, + {[{<<"xml">>, {[{<<"@lang">>, <<"en">>}]}}]}}]}, + io:format("~s", [jiffy:encode(to_json(In))]), + ?assertEqual(Out, (to_json(In))), + ?assertEqual(In, (from_json(Out))). + +-endif. |