1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
%%%----------------------------------------------------------------------
%%% File : xml.erl
%%% Author : Alexey Shchepin <alexey@sevcom.net>
%%% Purpose : XML utils
%%% Created : 20 Nov 2002 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(xml).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-export([element_to_string/1,
crypt/1,
remove_cdata/1,
get_cdata/1, get_tag_cdata/1,
get_attr/2, get_attr_s/2,
get_tag_attr/2, get_tag_attr_s/2,
get_subtag/2, get_subtag_cdata/2,
get_path_s/2,
replace_tag_attr/3]).
%% XML CDATA bigger than this will be enclosed in CDATA XML "tag"
-define(CDATA_BINARY_THRESHOLD, 50).
element_to_string(El) ->
case El of
{xmlelement, Name, Attrs, Els} ->
if
Els /= [] ->
[$<, Name, attrs_to_list(Attrs), $>,
[element_to_string(E) || E <- Els],
$<, $/, Name, $>];
true ->
[$<, Name, attrs_to_list(Attrs), $/, $>]
end;
%% We do not crypt CDATA binary, but we enclose it in XML CDATA
%% if they are long enough to be worth it.
{xmlcdata, CData} when binary(CData), size(CData) > ?CDATA_BINARY_THRESHOLD ->
CDATA1 = <<"<![CDATA[">>,
CDATA2 = <<"]]>">>,
concat_binary([CDATA1, CData, CDATA2]);
%% We crypt list and short binaries (implies a conversion to
%% list).
{xmlcdata, CData} ->
crypt(CData)
end.
attrs_to_list(Attrs) ->
[attr_to_list(A) || A <- Attrs].
attr_to_list({Name, Value}) ->
[$\s, crypt(Name), $=, $', crypt(Value), $'].
crypt(S) when is_list(S) ->
[case C of
$& -> "&";
$< -> "<";
$> -> ">";
$" -> """;
$' -> "'";
_ -> C
end || C <- S];
crypt(S) when is_binary(S) ->
crypt(binary_to_list(S)).
remove_cdata_p({xmlelement, _Name, _Attrs, _Els}) -> true;
remove_cdata_p(_) -> false.
remove_cdata(L) -> [E || E <- L, remove_cdata_p(E)].
get_cdata(L) ->
binary_to_list(list_to_binary(get_cdata(L, ""))).
get_cdata([{xmlcdata, CData} | L], S) ->
get_cdata(L, [S, CData]);
get_cdata([_ | L], S) ->
get_cdata(L, S);
get_cdata([], S) ->
S.
get_tag_cdata({xmlelement, _Name, _Attrs, Els}) ->
get_cdata(Els).
get_attr(AttrName, Attrs) ->
case lists:keysearch(AttrName, 1, Attrs) of
{value, {_, Val}} ->
{value, Val};
_ ->
false
end.
get_attr_s(AttrName, Attrs) ->
case lists:keysearch(AttrName, 1, Attrs) of
{value, {_, Val}} ->
Val;
_ ->
""
end.
get_tag_attr(AttrName, {xmlelement, _Name, Attrs, _Els}) ->
get_attr(AttrName, Attrs).
get_tag_attr_s(AttrName, {xmlelement, _Name, Attrs, _Els}) ->
get_attr_s(AttrName, Attrs).
get_subtag({xmlelement, _, _, Els}, Name) ->
get_subtag1(Els, Name).
get_subtag1([El | Els], Name) ->
case El of
{xmlelement, Name, _, _} ->
El;
_ ->
get_subtag1(Els, Name)
end;
get_subtag1([], _) ->
false.
get_subtag_cdata(Tag, Name) ->
case get_subtag(Tag, Name) of
false ->
"";
Subtag ->
get_tag_cdata(Subtag)
end.
get_path_s(El, []) ->
El;
get_path_s(El, [{elem, Name} | Path]) ->
case get_subtag(El, Name) of
false ->
"";
SubEl ->
get_path_s(SubEl, Path)
end;
get_path_s(El, [{attr, Name}]) ->
get_tag_attr_s(Name, El);
get_path_s(El, [cdata]) ->
get_tag_cdata(El).
replace_tag_attr(Attr, Value, {xmlelement, Name, Attrs, Els}) ->
Attrs1 = lists:keydelete(Attr, 1, Attrs),
Attrs2 = [{Attr, Value} | Attrs1],
{xmlelement, Name, Attrs2, Els}.
|