1%% @author Pablo Polvorin 2%% @doc Compile XPath expressions. 3%% This module uses the xpath parser of xmerl.. that interface isn't documented 4%% so could change between OTP versions.. its know to work with OTP R12B2 5%% created on 2008-05-07 6-module(mochiweb_xpath_parser). 7 8-export([compile_xpath/1]). 9 10%% Return a compiled XPath expression 11compile_xpath(XPathString) -> 12 {ok,XPath} = xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens(XPathString)), 13 simplify(XPath). 14 15 16 17%% @doc Utility functions to convert between the *internal* representation of 18% xpath expressions used in xmerl(using lists and atoms), to a 19% representation using only binaries, to match the way in 20% which the mochiweb html parser represents data 21simplify({path, union, {Path1, Path2}})-> 22 %% "expr1 | expr2 | expr3" 23 {path, union, {simplify(Path1), simplify(Path2)}}; 24simplify({path,Type,Path}) -> 25 {path,Type,simplify_path(Path)}; 26simplify({comp,Comp,A,B}) -> 27 {comp,Comp,simplify(A),simplify(B)}; 28simplify({literal,L}) -> 29 {literal,list_to_binary(L)}; 30simplify({number,N}) -> 31 {number,N}; 32simplify({negative, Smth}) -> 33 {negative, simplify(Smth)}; 34simplify({bool, Comp, A, B}) -> 35 {bool, Comp, simplify(A), simplify(B)}; 36simplify({function_call,Fun,Args}) -> 37 {function_call,Fun,lists:map(fun simplify/1,Args)}; 38simplify({arith, Op, Arg1, Arg2}) -> 39 {arith, Op, simplify(Arg1), simplify(Arg2)}. 40 41 42simplify_path({step,{Axis,NodeTest,Predicates}}) -> 43 {step,{Axis, 44 simplify_node_test(NodeTest), 45 simplify_predicates(Predicates)}}; 46simplify_path({refine,Path1,Path2}) -> 47 {refine,simplify_path(Path1),simplify_path(Path2)}. 48 49 50simplify_node_test({name,{Tag,Prefix,Local}}) -> 51 {name,{to_binary(Tag),Prefix,Local}}; 52 53simplify_node_test(A={node_type, _Type}) -> 54 A; 55simplify_node_test({processing_instruction, Name}) -> 56 {processing_instruction, list_to_binary(Name)}; % strictly, this must be node_type too! 57simplify_node_test(A={wildcard,wildcard}) -> 58 A; 59simplify_node_test({prefix_test, Prefix}) -> 60 %% [37] /prefix:*/ - namespace test 61 {prefix_test, list_to_binary(Prefix)}. 62 63 64simplify_predicates(X) -> lists:map(fun simplify_predicate/1,X). 65simplify_predicate({pred,Pred}) -> 66 {pred,simplify(Pred)}. 67 68to_binary(X) when is_atom(X) -> list_to_binary(atom_to_list(X)). 69 70 71 72 73