Skip to content

Commit 86be6c5

Browse files
committed
Rename get_all_subtags/2 to get_subtags/2, add try_subtags/2 and document them
1 parent 472ed4e commit 86be6c5

File tree

3 files changed

+68
-34
lines changed

3 files changed

+68
-34
lines changed

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,9 @@ to work with them:
153153
- `sub_els`: [get_els/1](doc/API.md#get_els1) and [set_els/2](doc/API.md#set_els2) can be used;
154154
additional functions to work with subtags directly are:
155155
[set_subtag/2](doc/API.md#set_subtag2), [get_subtag/2](doc/API.md#get_subtag2),
156-
[remove_subtag/2](doc/API.md#remove_subtag2), [has_subtag/2](doc/API.md#has_subtag2),
157-
[try_subtag/2](doc/API.md#try_subtag2) and [append_subtags/2](doc/API.md#append_subtags2).
156+
[get_subtags/2](doc/API.md#get_subtags2), [try_subtag/2](doc/API.md#try_subtag2),
157+
[try_subtags/2](doc/API.md#try_subtags2), [remove_subtag/2](doc/API.md#remove_subtag2),
158+
[has_subtag/2](doc/API.md#has_subtag2), and [append_subtags/2](doc/API.md#append_subtags2).
158159
- `meta`: this field is intended for attaching arbitrary Erlang terms to
159160
stanzas; the field is represented by a `map()` and can be manipulated
160161
using standard [maps](http://erlang.org/doc/man/maps.html) module, but

doc/API.md

+36-22
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ The following functions are exported from `xmpp` module:
2929
- [get_els/1](#get_els1)
3030
- [set_els/2](#set_els2)
3131
- [get_subtag/2](#get_subtag2)
32+
- [get_subtags/2](#get_subtags2)
3233
- [try_subtag/2](#try_subtag2)
34+
- [try_subtags/2](#try_subtags2)
3335
- [set_subtag/2](#set_subtag2)
3436
- [remove_subtag/2](#remove_subtag2)
3537
- [has_subtag/2](#has_subtag2)
@@ -225,7 +227,7 @@ during lazy decoding only top-level element is decoded.
225227

226228
**Example 2**: full decoding
227229
```erlang
228-
> xmpp:decode(El, <<"jabber:client">>, []).
230+
> xmpp:decode(El, <<"jabber:client">>, []).
229231
#message{id = <<>>,type = normal,lang = <<>>,
230232
from = undefined,to = undefined,subject = [],body = [],
231233
thread = undefined,
@@ -240,15 +242,15 @@ sub-elements (`<foo/>` in our case) remain untouched.
240242

241243
**Example 3**: no namespace is provided and `El` doesn't possess any
242244
```erlang
243-
> xmpp:decode(El, <<>>, []).
245+
> xmpp:decode(El, <<>>, []).
244246
** exception error: {xmpp_codec,{missing_tag_xmlns,<<"message">>}}
245247
in function xmpp_codec:decode/3 (src/xmpp_codec.erl, line 16)
246248
```
247249
It is safe to apply the function to `xmpp_element()`:
248250

249251
**Example 4**: double decoding
250252
```erlang
251-
> xmpp:decode(xmpp:decode(El, <<"jabber:client">>, [])).
253+
> xmpp:decode(xmpp:decode(El, <<"jabber:client">>, [])).
252254
#message{id = <<>>,type = normal,lang = <<>>,
253255
from = undefined,to = undefined,subject = [],body = [],
254256
thread = undefined,
@@ -389,7 +391,7 @@ of an `xmlel()` element.
389391

390392
**Example 1**: obtaining `type` of `presence()`
391393
```erlang
392-
> xmpp:get_type(#presence{}).
394+
> xmpp:get_type(#presence{}).
393395
available
394396
```
395397
**Example 2**: obtaining `type` of `xmlel()`
@@ -408,7 +410,7 @@ Sets `type` field of a `stanza()`.
408410

409411
**Example 1**: setting `type` field of `message()`
410412
```erlang
411-
> xmpp:set_type(#message{}, chat).
413+
> xmpp:set_type(#message{}, chat).
412414
#message{id = <<>>,type = chat,lang = <<>>,from = undefined,
413415
to = undefined,subject = [],body = [],thread = undefined,
414416
sub_els = [],meta = #{}}
@@ -456,7 +458,7 @@ Returns a value of `from` field of a `stanza()`.
456458

457459
**Example 1**: obtaining `from` of `message()`
458460
```erlang
459-
> xmpp:get_from(#message{from = jid:decode(<<"user@server/resource">>)}).
461+
> xmpp:get_from(#message{from = jid:decode(<<"user@server/resource">>)}).
460462
#jid{user = <<"user">>,server = <<"server">>,
461463
resource = <<"resource">>,luser = <<"user">>,
462464
lserver = <<"server">>,lresource = <<"resource">>}
@@ -500,7 +502,7 @@ Returns a value of `to` field of a `stanza()`.
500502

501503
**Example 1**: obtaining `to` of `message()`
502504
```erlang
503-
> xmpp:get_to(#message{to = jid:decode(<<"user@server/resource">>)}).
505+
> xmpp:get_to(#message{to = jid:decode(<<"user@server/resource">>)}).
504506
#jid{user = <<"user">>,server = <<"server">>,
505507
resource = <<"resource">>,luser = <<"user">>,
506508
lserver = <<"server">>,lresource = <<"resource">>}
@@ -532,7 +534,7 @@ Sets `to` field of a `stanza()`.
532534
```
533535
**Example 2**: removing `to` value from `iq()`
534536
```erlang
535-
> xmpp:set_to(#iq{to = jid:decode(<<"user@server/resource">>)}, undefined).
537+
> xmpp:set_to(#iq{to = jid:decode(<<"user@server/resource">>)}, undefined).
536538
#iq{id = <<>>,type = undefined,lang = <<>>,from = undefined,
537539
to = undefined,sub_els = [],meta = #{}}
538540
```
@@ -668,6 +670,12 @@ as show in the following example.
668670
#ping{}
669671
```
670672

673+
## get_subtags/2
674+
```erlang
675+
-spec get_subtags(Stanza :: stanza(), Tag :: xmpp_element()) -> [xmpp_element()].
676+
```
677+
Same as `get_subtag/2`, but returns all elements matching `Tag`, preserving their original order.
678+
671679
## try_subtag/2
672680
```erlang
673681
-spec try_subtag(Stanza :: stanza(), Tag :: xmpp_element()) -> xmpp_element() | false.
@@ -689,6 +697,12 @@ false
689697
** exception error: {xmpp_codec,{missing_attr,<<"id">>,<<"iq">>, <<"jabber:client">>}}
690698
```
691699

700+
## try_subtags/2
701+
```erlang
702+
-spec try_subtags(Stanza :: stanza(), Tag :: xmpp_element()) -> [xmpp_element()].
703+
```
704+
Same as `try_subtag/2`, but returns all elements matching `Tag`, preserving their original order.
705+
692706
## set_subtag/2
693707
```erlang
694708
-spec set_subtag(Stanza :: iq(), Tag :: xmpp_element()) -> iq();
@@ -963,7 +977,7 @@ metadata of `Stanza`.
963977

964978
**Example 1**: sets new key in metadata
965979
```erlang
966-
> xmpp:put_meta(#presence{}, foo, bar).
980+
> xmpp:put_meta(#presence{}, foo, bar).
967981
#presence{id = <<>>,type = available,lang = <<>>,
968982
from = undefined,to = undefined,show = undefined,
969983
status = [],priority = undefined,sub_els = [],
@@ -995,7 +1009,7 @@ Fails with `{badkey,Key}` exception if no value is associated with `Key`.
9951009
```
9961010
**Example 2**: updating non-existing key
9971011
```erlang
998-
> xmpp:update_meta(#presence{}, foo, bar).
1012+
> xmpp:update_meta(#presence{}, foo, bar).
9991013
** exception error: {badkey,foo}
10001014
...
10011015
```
@@ -1009,7 +1023,7 @@ metadata of `Stanza`.
10091023

10101024
**Example 1**: removing value by key
10111025
```erlang
1012-
> xmpp:del_meta(#presence{meta = #{foo => bar}}, foo).
1026+
> xmpp:del_meta(#presence{meta = #{foo => bar}}, foo).
10131027
#presence{id = <<>>,type = available,lang = <<>>,
10141028
from = undefined,to = undefined,show = undefined,
10151029
status = [],priority = undefined,sub_els = [],meta = #{}}
@@ -1061,12 +1075,12 @@ true
10611075
```
10621076
**Example 2**: the tag is unknown
10631077
```erlang
1064-
> xmpp:is_known_tag(#xmlel{name = <<"foo">>, attrs = [{<<"xmlns">>,<<"bar">>}]}).
1078+
> xmpp:is_known_tag(#xmlel{name = <<"foo">>, attrs = [{<<"xmlns">>,<<"bar">>}]}).
10651079
false
10661080
```
10671081
**Example 3**: the element lacks namespace, so it's always unknown
10681082
```erlang
1069-
> xmpp:is_known_tag(#xmlel{name = <<"x">>}).
1083+
> xmpp:is_known_tag(#xmlel{name = <<"x">>}).
10701084
false
10711085
```
10721086
**Example 4**: the element lacks namespace, but we assume it's within 'jabber:server' namespace
@@ -1083,7 +1097,7 @@ Returns namespace of `xmpp_element()` or `xmlel()` element.
10831097

10841098
**Example 1**: obtaining namespace of `xmpp_element()`
10851099
```erlang
1086-
> xmpp:get_ns(#disco_info{}).
1100+
> xmpp:get_ns(#disco_info{}).
10871101
<<"http://jabber.org/protocol/disco#info">>
10881102
```
10891103
**Example 2**: obtaining namespace of `xmlel()` element
@@ -1129,7 +1143,7 @@ Creates from `IQ` an `iq()` of type `result` with empty sub-elements.
11291143
**Example 2**: trying to create a result of a result
11301144
```erlang
11311145
> xmpp:make_iq_result(#iq{type = result, id = <<"1">>}).
1132-
** exception error: no function clause matching
1146+
** exception error: no function clause matching
11331147
```
11341148

11351149
## make_iq_result/2
@@ -1154,7 +1168,7 @@ Creates from `IQ` an `iq()` of type `result` with sub-elements set to `[El]`.
11541168
**Example 2**: trying to create a result of a result
11551169
```erlang
11561170
> xmpp:make_iq_result(#iq{type = result, id = <<"1">>}, #disco_items{}).
1157-
** exception error: no function clause matching
1171+
** exception error: no function clause matching
11581172
```
11591173

11601174
## make_error/2
@@ -1180,7 +1194,7 @@ Constructs `stanza()` of type `error` from `Stanza`.
11801194
**Example 2**: trying to create an error from an error
11811195
```erlang
11821196
> xmpp:make_error(#presence{type = error}, xmpp:err_bad_request()).
1183-
** exception error: no function clause matching
1197+
** exception error: no function clause matching
11841198
```
11851199

11861200
## get_error/1
@@ -1205,7 +1219,7 @@ if not found of if decoding has failed.
12051219
```
12061220
**Example 2**: no `stanza_error()` element found
12071221
```erlang
1208-
> xmpp:get_error(#message{}).
1222+
> xmpp:get_error(#message{}).
12091223
undefined
12101224
```
12111225

@@ -1220,7 +1234,7 @@ or [decode/3](#decode3).
12201234
```erlang
12211235
> try xmpp:decode(#xmlel{name = <<"foo">>})
12221236
catch _:{xmpp_codec, Reason} -> xmpp:format_error(Reason)
1223-
end.
1237+
end.
12241238
<<"Unknown tag <foo/> qualified by namespace 'jabber:client'">>
12251239
> try xmpp:decode(#xmlel{name = <<"iq">>})
12261240
catch _:{xmpp_codec, Reason} -> xmpp:format_error(Reason)
@@ -1334,7 +1348,7 @@ Pretty printer for XMPP elements.
13341348

13351349
**Example**:
13361350
```erlang
1337-
> S = xmpp:pp(#sm_a{h = 10, xmlns = <<"urn:xmpp:sm:3">>}).
1351+
> S = xmpp:pp(#sm_a{h = 10, xmlns = <<"urn:xmpp:sm:3">>}).
13381352
["#sm_a",123,
13391353
[["h"," = ",49,48],
13401354
44,
@@ -2166,7 +2180,7 @@ a valid timestamp.
21662180
```
21672181
**Example 3**: decoding failure - not even remotely a timestamp
21682182
```erlang
2169-
> xmpp_util:decode_timestamp(<<"sd324klsjdpsdf">>).
2183+
> xmpp_util:decode_timestamp(<<"sd324klsjdpsdf">>).
21702184
** exception error: {bad_timestamp,<<"sd324klsjdpsdf">>}
21712185
...
21722186
```
@@ -2421,7 +2435,7 @@ Returns `error` if stringprep has failed.
24212435
```
24222436
**Example 3**: stringprep failure
24232437
```erlang
2424-
> jid:tolower({<<"@">>, <<"Server">>, <<"Resource">>}).
2438+
> jid:tolower({<<"@">>, <<"Server">>, <<"Resource">>}).
24252439
error
24262440
```
24272441

src/xmpp.erl

+29-10
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
append_subtags/2, prep_lang/1, register_codec/1, unregister_codec/1,
4545
set_tr_callback/1, format_stanza_error/1, format_stanza_error/2,
4646
format_stream_error/1, format_stream_error/2, format_sasl_error/1,
47-
format_sasl_error/2, set_config/1, get_config/0, get_all_subtags/2]).
47+
format_sasl_error/2, set_config/1, get_config/0, get_subtags/2,
48+
try_subtags/2]).
4849

4950
%% XMPP errors
5051
-export([err_bad_request/0, err_bad_request/2,
@@ -462,27 +463,27 @@ get_subtag([El|Els], TagName, XMLNS, TopXMLNS) ->
462463
get_subtag([], _, _, _) ->
463464
false.
464465

465-
-spec get_all_subtags(xmpp_element(), xmpp_element()) -> [xmpp_element()].
466-
get_all_subtags(Pkt, Tag) ->
466+
-spec get_subtags(xmpp_element(), xmpp_element()) -> [xmpp_element()].
467+
get_subtags(Pkt, Tag) ->
467468
Els = get_els(Pkt),
468469
TopXMLNS = xmpp_codec:get_ns(Pkt),
469470
TagName = xmpp_codec:get_name(Tag),
470471
XMLNS = xmpp_codec:get_ns(Tag),
471-
get_all_subtags(Els, TagName, XMLNS, TopXMLNS, []).
472+
get_subtags(Els, TagName, XMLNS, TopXMLNS, []).
472473

473-
get_all_subtags([El|Els], TagName, XMLNS, TopXMLNS, Acc) ->
474+
get_subtags([El|Els], TagName, XMLNS, TopXMLNS, Acc) ->
474475
case match_tag(El, TagName, XMLNS, TopXMLNS) of
475476
true ->
476477
try
477-
get_all_subtags(Els, TagName, XMLNS, TopXMLNS, [decode(El) | Acc])
478+
get_subtags(Els, TagName, XMLNS, TopXMLNS, [decode(El) | Acc])
478479
catch _:{xmpp_codec, _Why} ->
479-
get_all_subtags(Els, TagName, XMLNS, TopXMLNS, Acc)
480+
get_subtags(Els, TagName, XMLNS, TopXMLNS, Acc)
480481
end;
481482
false ->
482-
get_all_subtags(Els, TagName, XMLNS, TopXMLNS, Acc)
483+
get_subtags(Els, TagName, XMLNS, TopXMLNS, Acc)
483484
end;
484-
get_all_subtags([], _, _, _, Acc) ->
485-
Acc.
485+
get_subtags([], _, _, _, Acc) ->
486+
lists:reverse(Acc).
486487

487488
-spec try_subtag(xmpp_element(), xmpp_element()) -> xmpp_element() | false.
488489
try_subtag(Pkt, Tag) ->
@@ -502,6 +503,24 @@ try_subtag([El|Els], TagName, XMLNS, TopXMLNS) ->
502503
try_subtag([], _, _, _) ->
503504
false.
504505

506+
-spec try_subtags(xmpp_element(), xmpp_element()) -> [xmpp_element()].
507+
try_subtags(Pkt, Tag) ->
508+
Els = get_els(Pkt),
509+
TopXMLNS = xmpp_codec:get_ns(Pkt),
510+
TagName = xmpp_codec:get_name(Tag),
511+
XMLNS = xmpp_codec:get_ns(Tag),
512+
try_subtags(Els, TagName, XMLNS, TopXMLNS, []).
513+
514+
try_subtags([El|Els], TagName, XMLNS, TopXMLNS, Acc) ->
515+
case match_tag(El, TagName, XMLNS, TopXMLNS) of
516+
true ->
517+
try_subtags(Els, TagName, XMLNS, TopXMLNS, [decode(El) | Acc]);
518+
false ->
519+
try_subtags(Els, TagName, XMLNS, TopXMLNS, Acc)
520+
end;
521+
try_subtags([], _, _, _, Acc) ->
522+
lists:reverse(Acc).
523+
505524
-spec remove_subtag(xmpp_element(), xmpp_element()) -> xmpp_element().
506525
remove_subtag(Pkt, Tag) ->
507526
Els = get_els(Pkt),

0 commit comments

Comments
 (0)