Skip to content

Commit 701f00c

Browse files
committed
xmerl: Fix XPath substring-before, string-length, sum, round and number()
1 parent e2fd858 commit 701f00c

2 files changed

Lines changed: 26 additions & 11 deletions

File tree

lib/xmerl/src/xmerl_xpath_pred.erl

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,12 @@ contains(C, [A1, A2]) ->
508508
'substring-before'(C, [A1, A2]) ->
509509
S1 = mk_string(C, A1),
510510
S2 = mk_string(C, A2),
511-
Pos = string:str(S1, S2),
512-
?string(string:substr(S1, 1, Pos)).
511+
case string:str(S1, S2) of
512+
0 ->
513+
?string([]);
514+
Pos ->
515+
?string(string:substr(S1, 1, Pos - 1))
516+
end.
513517

514518
%% string: substring-after(string, string)
515519
'substring-after'(C, [A1, A2]) ->
@@ -536,10 +540,10 @@ substring(C, [A1, A2, A3]) ->
536540

537541
%% number: string-length(string?)
538542
'string-length'(C = #xmlContext{context_node = N}, []) ->
539-
length(mk_string(C, string_value(N)));
543+
?number(length(mk_string(C, string_value(N))));
540544

541545
'string-length'(C, [A]) ->
542-
length(mk_string(C, A)).
546+
?number(length(mk_string(C, A))).
543547

544548

545549
%% string: normalize-space(string?)
@@ -633,17 +637,17 @@ match_lang(_, _) ->
633637

634638
%% number: number(object)
635639
number(C = #xmlContext{context_node = N}, []) ->
636-
?number(mk_number(C, string(C, N)));
640+
?number(mk_number(C, string_value(N)));
637641
number(C, [Arg]) ->
638642
?number(mk_number(C, Arg)).
639643

640644

641645
sum(C, [Arg]) ->
642646
NS = mk_nodeset(C, Arg),
643-
lists:foldl(
644-
fun(N, Sum) ->
645-
Sum + mk_number(C, string(C, N))
646-
end, 0, NS).
647+
?number(lists:foldl(
648+
fun(N, Sum) ->
649+
Sum + mk_number(C, string_value(N))
650+
end, 0, NS)).
647651

648652
floor(C, [Arg]) ->
649653
Num = mk_number(C, Arg),
@@ -665,14 +669,14 @@ ceiling(C, [Arg]) ->
665669

666670

667671
round(C, [Arg]) ->
668-
case mk_number(C, Arg) of
672+
?number(case mk_number(C, Arg) of
669673
A when is_atom(A) ->
670674
A;
671675
N when is_integer(N) ->
672676
N;
673677
F when is_float(F) ->
674678
round(F)
675-
end.
679+
end).
676680

677681

678682
select_on_attribute([E = #xmlElement{attributes = Attrs}|T], K, V, Acc) ->

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,17 @@ functions() ->
286286
ok = Test(Doc,"/foo/bar[starts-with(name, 'X')]",[bar,bar]),
287287
ok = Test(Doc,"/foo/bar[value = string(1)]/value/text()",["1"]),
288288

289+
%% Regression tests: substring-before used to include the separator's
290+
%% first character (off-by-one); string-length and round returned bare
291+
%% numbers instead of #xmlObj{type=number}; and sum and number() (no
292+
%% args) called string/2 with a bare node, crashing on any non-empty
293+
%% node-set.
294+
ok = Test(Doc,"/foo/bar[substring-before(name, 'a') = 'Xp']",[bar]),
295+
ok = Test(Doc,"/foo/bar[string-length(name) = 3]",[bar]),
296+
ok = Test(Doc,"/foo/bar[round(value) = 2]",[bar]),
297+
ok = Test(Doc,"/foo[sum(bar/value) = 6]",[foo]),
298+
ok = Test(Doc,"/foo/bar/value[number() = 2]",[value]),
299+
289300

290301
{Doc2,_}= xmerl_scan:file("purchaseOrder.xml"),
291302
ok = Test(Doc2,"//*[starts-with(local-name(),'c')]",

0 commit comments

Comments
 (0)