Skip to content

Commit e2fd858

Browse files
committed
xmerl: Fix XPath relational operators <, <= and >=
1 parent 5d651b9 commit e2fd858

3 files changed

Lines changed: 38 additions & 4 deletions

File tree

lib/xmerl/src/xmerl_xpath_pred.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,15 +166,15 @@ comp_expr('>', E1, E2, C) ->
166166
comp_expr('<', E1, E2, C) ->
167167
N1 = expr(E1,C),
168168
N2 = expr(E2,C),
169-
?boolean(compare_ineq_format(N1,N2,C) > compare_ineq_format(N2,N1,C));
169+
?boolean(compare_ineq_format(N1,N2,C) < compare_ineq_format(N2,N1,C));
170170
comp_expr('>=', E1, E2, C) ->
171171
N1 = expr(E1,C),
172172
N2 = expr(E2,C),
173-
?boolean(compare_ineq_format(N1,N2,C) > compare_ineq_format(N2,N1,C));
173+
?boolean(compare_ineq_format(N1,N2,C) >= compare_ineq_format(N2,N1,C));
174174
comp_expr('<=', E1, E2, C) ->
175175
N1 = expr(E1,C),
176176
N2 = expr(E2,C),
177-
?boolean(compare_ineq_format(N1,N2,C) > compare_ineq_format(N2,N1,C));
177+
?boolean(compare_ineq_format(N1,N2,C) =< compare_ineq_format(N2,N1,C));
178178
comp_expr('=', E1, E2, C) ->
179179
N1 = expr(E1,C),
180180
N2 = expr(E2,C),

lib/xmerl/test/xmerl_SUITE.erl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
all() ->
4646
[doctests,
4747
{group, cpd_tests}, xpath_text1, xpath_main,
48-
xpath_abbreviated_syntax, xpath_functions, xpath_namespaces,
48+
xpath_abbreviated_syntax, xpath_functions, xpath_relational,
49+
xpath_namespaces,
4950
{group, misc}, {group, eventp_tests},
5051
{group, ticket_tests}, {group, app_test},
5152
{group, appup_test}, {group, format_test}].
@@ -192,6 +193,10 @@ xpath_functions(Config) ->
192193
file:set_cwd(filename:join(datadir(Config),xpath)),
193194
ok = xpath_abbrev:functions().
194195

196+
xpath_relational(Config) ->
197+
file:set_cwd(filename:join(datadir(Config),xpath)),
198+
ok = xpath_abbrev:relational_operators().
199+
195200
xpath_namespaces(Config) ->
196201
file:set_cwd(filename:join(datadir(Config),xpath)),
197202
ok = xpath_abbrev:namespaces().

lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
-module(xpath_abbrev).
99

1010
-export([test/0, check_node_set/2, ticket_6873/0, ticket_7496/0, functions/0]).
11+
-export([relational_operators/0]).
1112
-export([namespaces/0]).
1213

1314
-include_lib("common_test/include/ct.hrl").
@@ -218,6 +219,34 @@ ticket_7496() ->
218219
ok = Test(Doc3,"//*[starts-with(local-name(),'p')]",
219220
[parent,pet,pet]).
220221

222+
%% Regression test for the relational operators '<', '<=' and '>='.
223+
%% These three clauses of xmerl_xpath_pred:comp_expr/4 each carried the
224+
%% body of '>' (a copy-paste error), so every one evaluated as 'a > b'.
225+
%% The cases below fail on the buggy code (each selects [e,f] / [] instead
226+
%% of the expected node sets) and pass once the operators are correct.
227+
relational_operators() ->
228+
Test = fun(Doc, XPath, Exp) ->
229+
Result = xmerl_xpath:string(XPath, Doc),
230+
Exp = [Name || #xmlElement{name = Name} <- Result],
231+
ok
232+
end,
233+
{Doc,_} = xmerl_scan:string("<a><b/><c/><d/><e/><f/></a>"),
234+
235+
%% Relational predicates over position() (number vs number).
236+
ok = Test(Doc, "/a/*[position() < 3]", [b, c]),
237+
ok = Test(Doc, "/a/*[position() <= 3]", [b, c, d]),
238+
ok = Test(Doc, "/a/*[position() >= 3]", [d, e, f]),
239+
ok = Test(Doc, "/a/*[position() > 3]", [e, f]),
240+
241+
%% Constant relational predicates, independent of position(): each is a
242+
%% boolean that is true, so it selects every child.
243+
All = [b, c, d, e, f],
244+
ok = Test(Doc, "/a/*[2 < 3]", All),
245+
ok = Test(Doc, "/a/*[3 <= 3]", All),
246+
ok = Test(Doc, "/a/*[3 >= 3]", All),
247+
ok = Test(Doc, "/a/*[3 > 2]", All),
248+
ok.
249+
221250

222251
functions() ->
223252
Test = fun(Doc, XPath, Exp) ->

0 commit comments

Comments
 (0)