1%% xpath_functions.erl 2%% @author Pablo Polvorin 3%% @doc Some core xpath functions that can be used in xpath expressions 4%% created on 2008-05-07 5-module(mochiweb_xpath_functions). 6 7-export([lookup_function/1]). 8 9 10%% Default functions. 11%% The format is: {FunctionName, fun(), FunctionSignature} 12%% WildCard argspec must be the last spec in list. 13%% 14%% @type FunctionName = atom() 15%% @type FunctionSignature = [XPathArgSpec] 16%% @type XPathArgSpec = XPathType | WildCardArgSpec 17%% @type WildCardArgSpec = {'*', XPathType} 18%% @type XPathType = node_set | string | number | boolean 19%% 20%% The engine is responsable of calling the function with 21%% the correct arguments, given the function signature. 22-spec lookup_function(atom()) -> mochiweb_xpath:xpath_fun_spec() | false. 23lookup_function('last') -> 24 {'last',fun last/2,[]}; 25lookup_function('position') -> 26 {'position',fun position/2,[]}; 27lookup_function('count') -> 28 {'count',fun count/2,[node_set]}; 29lookup_function('concat') -> 30 {'concat',fun concat/2,[{'*', string}]}; 31lookup_function('name') -> 32 {'name',fun 'name'/2,[node_set]}; 33lookup_function('starts-with') -> 34 {'starts-with', fun 'starts-with'/2,[string,string]}; 35lookup_function('contains') -> 36 {'contains', fun 'contains'/2,[string,string]}; 37lookup_function('substring') -> 38 {'substring', fun substring/2,[string,number,number]}; 39lookup_function('sum') -> 40 {'sum', fun sum/2,[node_set]}; 41lookup_function('string-length') -> 42 {'string-length', fun 'string-length'/2,[string]}; 43lookup_function('not') -> 44 {'not', fun x_not/2, [boolean]}; 45lookup_function('string') -> 46 {'string', fun 'string'/2, [node_set]}; 47lookup_function(_) -> 48 false. 49 50%% @doc Function: boolean last() 51%% The position function returns the position of the current node 52last({ctx, _, _, _, Position, Size} = _Ctx, []) -> 53 Position =:= Size. 54 55%% @doc Function: number position() 56%% The position function returns the position of the current node 57position({ctx, _, _, _, Position, _} = _Ctx, []) -> 58 Position. 59 60%% @doc Function: number count(node-set) 61%% The count function returns the number of nodes in the 62%% argument node-set. 63count(_Ctx,[NodeList]) -> 64 length(NodeList). 65 66%% @doc Function: concat(binary, binary, ...) 67%% Concatenate string arguments (variable length) 68concat(_Ctx, BinariesList) -> 69 %% list_to_binary() 70 << <<Str/binary>> || Str <- BinariesList>>. 71 72%% @doc Function: string name(node-set?) 73'name'(_Ctx,[[{Tag,_,_,_}|_]]) -> 74 Tag. 75 76%% @doc Function: boolean starts-with(string, string) 77%% The starts-with function returns true if the first argument string 78%% starts with the second argument string, and otherwise returns false. 79'starts-with'(_Ctx,[Left,Right]) -> 80 Size = size(Right), 81 case Left of 82 <<Right:Size/binary,_/binary>> -> true; 83 _ -> false 84 end. 85 86%% @doc Function: checks that Where contains What 87contains(_Ctx,[Where, What]) -> 88 case binary:match(Where, [What]) of 89 nomatch -> 90 false; 91 {_, _} -> 92 true 93 end. 94 95%% @doc Function: string substring(string, number, number?) 96%% The substring function returns the substring of the first argument 97%% starting at the position specified in the second argument with length 98%% specified in the third argument 99substring(_Ctx,[String,Start,Length]) when is_binary(String)-> 100 Before = Start -1, 101 After = size(String) - Before - Length, 102 case (Start + Length) =< size(String) of 103 true -> 104 <<_:Before/binary,R:Length/binary,_:After/binary>> = String, 105 R; 106 false -> 107 <<>> 108 end. 109 110%% @doc Function: number sum(node-set) 111%% The sum function returns the sum, for each node in the argument 112%% node-set, of the result of converting the string-values of the node 113%% to a number. 114sum(_Ctx,[Values]) -> 115 lists:sum([mochiweb_xpath_utils:number_value(V) || V <- Values]). 116 117%% @doc Function: number string-length(string?) 118%% The string-length returns the number of characters in the string 119%% TODO: this isn't true: currently it returns the number of bytes 120%% in the string, that isn't the same 121'string-length'(_Ctx,[String]) -> 122 size(String). 123 124%% @doc Function: string string(node_set) 125%% 126%% The sum function returns the string representation of the 127%% nodes in a node-set. This is different from text() in that 128%% it concatenates each bit of the text in the node along with the text in 129%% any children nodes along the way, in order. 130%% Note: this differs from normal xpath in that it returns a list of strings, one 131%% for each node in the node set, as opposed to just the first node. 132'string'(_Ctx, [NodeList]) -> 133 lists:map(fun({_Elem, _Attr, Children,_Pos}) -> concat_child_text(Children, []) end, NodeList). 134 135concat_child_text([], Result) -> 136 list_to_binary(lists:reverse(Result)); 137concat_child_text([{_,_,Children,_} | Rest], Result) -> 138 concat_child_text(Rest, [concat_child_text(Children, []) | Result]); 139concat_child_text([X | Rest], Result) -> 140 concat_child_text(Rest, [X | Result]). 141 142x_not(_Ctx, [Bool]) -> 143 not Bool. 144