Current section
Files
Jump to
Current section
Files
src/xpath_parser.erl
%% @author Pablo Polvorin
%% @doc Compile XPath expressions.
%% This module uses the xpath parser of xmerl.. that interface isn't documented
%% so could change between OTP versions.. its know to work with OTP R12B2
%% created on 2008-05-07
-module(xpath_parser).
-export([compile_xpath/1]).
%% Return a compiled XPath expression
compile_xpath(XPathString) ->
{ok,XPath} = xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens(XPathString)),
simplify(XPath).
%% @doc Utility functions to convert between the *internal* representation of
% xpath expressions used in xmerl(using lists and atoms), to a
% representation using only binaries, to match the way in
% which the mochiweb html parser represents data
simplify({path, union, {Path1, Path2}})->
%% "expr1 | expr2 | expr3"
{path, union, {simplify(Path1), simplify(Path2)}};
simplify({path,Type,Path}) ->
{path,Type,simplify_path(Path)};
simplify({comp,Comp,A,B}) ->
{comp,Comp,simplify(A),simplify(B)};
simplify({literal,L}) ->
{literal,unicode:characters_to_binary(L)};
simplify({number,N}) ->
{number,N};
simplify({negative, Smth}) ->
{negative, simplify(Smth)};
simplify({bool, Comp, A, B}) ->
{bool, Comp, simplify(A), simplify(B)};
simplify({function_call,Fun,Args}) ->
{function_call,Fun,lists:map(fun simplify/1,Args)};
simplify({arith, Op, Arg1, Arg2}) ->
{arith, Op, simplify(Arg1), simplify(Arg2)}.
simplify_path({step,{Axis,NodeTest,Predicates}}) ->
{step,{Axis,
simplify_node_test(NodeTest),
simplify_predicates(Predicates)}};
simplify_path({refine,Path1,Path2}) ->
{refine,simplify_path(Path1),simplify_path(Path2)}.
simplify_node_test({name,{Tag,Prefix,Local}}) ->
{name,{to_binary(Tag),Prefix,Local}};
simplify_node_test(A={node_type, _Type}) ->
A;
simplify_node_test({processing_instruction, Name}) ->
{processing_instruction, unicode:characters_to_binary(Name)}; % strictly, this must be node_type too!
simplify_node_test(A={wildcard,wildcard}) ->
A;
simplify_node_test({prefix_test, Prefix}) ->
%% [37] /prefix:*/ - namespace test
{prefix_test, list_to_binary(Prefix)}.
simplify_predicates(X) -> lists:map(fun simplify_predicate/1,X).
simplify_predicate({pred,Pred}) ->
{pred,simplify(Pred)}.
to_binary(X) when is_atom(X) -> list_to_binary(atom_to_list(X)).