⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmerl_xpath_pred.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 2 页
字号:
%%% The contents of this file are subject to the Erlang Public License,%%% Version 1.0, (the "License"); you may not use this file except in%%% compliance with the License. You may obtain a copy of the License at%%% http://www.erlang.org/license/EPL1_0.txt%%%%%% Software distributed under the License is distributed on an "AS IS"%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%%% the License for the specific language governing rights and limitations%%% under the License.%%%%%% The Original Code is xmerl-0.6%%%%%% The Initial Developer of the Original Code is Ericsson Telecom%%% AB. Portions created by Ericsson are Copyright (C), 1998, Ericsson%%% Telecom AB. All Rights Reserved.%%%%%% Contributor(s): ______________________________________.%%%%%%----------------------------------------------------------------------%%% #0.    BASIC INFORMATION%%%----------------------------------------------------------------------%%% @private%%% File:       xmerl_xpath_pred.erl%%% Author       : Ulf Wiger <ulf.wiger@ericsson.com>%%% Description  : Helper module to xmerl_xpath: XPATH predicates.%%% %%% Modules used : lists, string, xmerl_scan, xmerl_xpath%%% %%%-----------------------------------------------------------------------module(xmerl_xpath_pred).-vsn('0.6').-date('00-09-22').-author('ulf.wiger@ericsson.com').%% API-export([eval/2]).%% internal functions (called via apply/3)-export([boolean/1, boolean/2,	 ceiling/2,	 concat/2,	 contains/2,	 count/2,	 floor/2,	 fn_false/2,	 fn_not/2,	 fn_true/2,	 id/2,	 lang/2,	 last/2,	 'local-name'/2,	 'namespace-uri'/2,	 nodeset/1,	 'normalize-space'/2,	 number/1, number/2,	 position/2,	 round/2,	 'starts-with'/2,	 string/1,	 'string-length'/2,	 substring/2,	 'substring-after'/2,	 'substring-before'/2,	 sum/2,	 translate/2]).	 -include("xmerl.hrl").-include("xmerl_xpath.hrl").%% -record(obj, {type,%% 	      value}).-define(string(X), #xmlObj{type = string,			   value = X}).-define(nodeset(X), #xmlObj{type = nodeset,			    value = X}).-define(number(X), #xmlObj{type = number,			   value = X}).-define(boolean(X), #xmlObj{type = boolean,			    value = X}).eval(Expr, C = #xmlContext{context_node = #xmlNode{pos = Pos}}) ->    Obj = expr(Expr, C),    Res = case Obj#xmlObj.type of	      number when Obj#xmlObj.value == Pos ->		  true;	      number ->		  false;	      boolean ->		  Obj#xmlObj.value;	      _ ->		  mk_boolean(C, Obj)	  end,%    io:format("eval(~p, ~p) -> ~p~n", [Expr, Pos, Res]),    Res.string(X) ->    ?string(X).nodeset(X) ->     ?nodeset(X).number(X) ->    ?number(X).boolean(X) ->    ?boolean(X).expr({arith, Op, E1, E2}, C) ->    arith_expr(Op, E1, E2, C);expr({comp, Op, E1, E2}, C) ->    comp_expr(Op, E1, E2, C);expr({bool, Op, E1, E2}, C) ->    bool_expr(Op, E1, E2, C);expr({'negative', E}, C) ->    N = mk_number(C, E),    - N;expr({number, N}, _C) ->    ?number(N);expr({literal, S}, _C) ->    ?string(S);expr({function_call, F, Args}, C) ->    case core_function(F) of	{true, F1} ->	    ?MODULE:F1(C, Args);	true ->	    ?MODULE:F(C, Args);	false ->	    %% here, we should look up the function in the context provided 	    %% by the caller, but we haven't figured this out yet.	    exit({not_a_core_function, F})    end;expr({path, Type, PathExpr}, C) ->    #state{context=#xmlContext{nodeset = NS}} =	xmerl_xpath:eval_path(Type, PathExpr, C),    ?nodeset(NS);expr(Expr, _C) ->    exit({unknown_expr, Expr}).arith_expr('+', E1, E2, C) ->    ?number(mk_number(C, E1) + mk_number(C, E2));arith_expr('-', E1, E2, C) ->    ?number(mk_number(C, E1) - mk_number(C, E2));arith_expr('*', E1, E2, C) ->    ?number(mk_number(C, E1) * mk_number(C, E2));arith_expr('div', E1, E2, C) ->    ?number(mk_number(C, E1) / mk_number(C, E2));arith_expr('mod', E1, E2, C) ->    ?number(mk_number(C, E1) rem mk_number(C, E2)).comp_expr('>', E1, E2, C) ->    N1 = expr(E1,C),    N2 = expr(E2,C),    ?boolean(compare_ineq_format(N1,N2,C) > compare_ineq_format(N2,N1,C));comp_expr('<', E1, E2, C) ->    N1 = expr(E1,C),    N2 = expr(E2,C),    ?boolean(compare_ineq_format(N1,N2,C) > compare_ineq_format(N2,N1,C));comp_expr('>=', E1, E2, C) ->    N1 = expr(E1,C),    N2 = expr(E2,C),    ?boolean(compare_ineq_format(N1,N2,C) > compare_ineq_format(N2,N1,C));comp_expr('<=', E1, E2, C) ->    N1 = expr(E1,C),    N2 = expr(E2,C),    ?boolean(compare_ineq_format(N1,N2,C) > compare_ineq_format(N2,N1,C));comp_expr('=', E1, E2, C) ->    N1 = expr(E1,C),    N2 = expr(E2,C),    ?boolean(compare_eq_format(N1,N2,C) == compare_eq_format(N2,N1,C));comp_expr('!=', E1, E2, C) ->    N1 = expr(E1,C),    N2 = expr(E2,C),    ?boolean(compare_eq_format(N1,N2,C) == compare_eq_format(N2,N1,C)).bool_expr('or', E1, E2, C) ->    ?boolean(mk_boolean(C, E1) or mk_boolean(C, E2));bool_expr('and', E1, E2, C) ->    ?boolean(mk_boolean(C, E1) and mk_boolean(C, E2)).%% According to chapter 3.4 in XML Path Language ver 1.0 the format of%% the compared objects are depending on the type of the other%% object. %% 1. Comparisons involving node-sets is treated equally despite%% of which comparancy operand is used. In this case:%% - node-set comp node-set: string values are used%% - node-set comp number : ((node-set string value) -> number) %% - node-set comp boolean : (node-set string value) -> boolean%% 2. Comparisons when neither object is a node-set and the operand%% is = or != the following transformation is done before comparison:%% - if one object is a boolean the other is converted to a boolean.%% - if one object is a number the other is converted to a number.%% - otherwise convert both to the string value.%% 3. Comparisons when neither object is a node-set and the operand is%% <=, <, >= or > both objects are converted to a number.compare_eq_format(N1=#xmlObj{type=T1},N2=#xmlObj{type=T2},C) when T1==nodeset;							      T2==nodeset ->    compare_nseq_format(N1,N2,C);compare_eq_format(N1=#xmlObj{type=T1},#xmlObj{type=T2},C) when T1==boolean;							      T2==boolean ->    mk_boolean(C,N1);compare_eq_format(N1=#xmlObj{type=T1},#xmlObj{type=T2},C) when T1==number;							      T2==number ->    mk_number(C,N1);compare_eq_format(N1,_,C) ->    mk_string(C,string_value(N1)).compare_ineq_format(N1=#xmlObj{type=T1},		    N2=#xmlObj{type=T2},C) when T1==nodeset;						T2==nodeset ->    compare_nseq_format(N1,N2,C);compare_ineq_format(N1,_N2,C) ->    mk_number(C,N1).compare_nseq_format(N1=#xmlObj{type = number},_N2,C) ->    mk_number(C,N1);compare_nseq_format(N1=#xmlObj{type = boolean},_N2,C) ->    mk_boolean(C,N1);compare_nseq_format(N1=#xmlObj{type = string},_N2,C) ->    mk_string(C,N1);compare_nseq_format(N1=#xmlObj{type = nodeset},_N2=#xmlObj{type=number},C) ->    %% transform nodeset value to its string-value    mk_number(C,string_value(N1));compare_nseq_format(N1=#xmlObj{type = nodeset},_N2=#xmlObj{type=boolean},C) ->    mk_boolean(C,N1);compare_nseq_format(N1=#xmlObj{type = nodeset},_N2,C) ->    mk_string(C,string_value(N1)).core_function('last') ->		true;core_function('position') ->		true;core_function('count') ->		true;core_function('id') ->			true;core_function('local-name') ->		true;core_function('namespace-uri') ->	true;core_function('name') ->		true;core_function('string') ->		true;core_function('concat') ->		true;core_function('starts-with') ->		true;core_function('contains') ->		true;core_function('substring-before') ->	true;core_function('substring-after') ->	true;core_function('string-length') ->	true;core_function('normalize-space') ->	true;core_function('translate') ->		true;core_function('boolean') ->		true;core_function('not') ->			{true, fn_not};core_function('true') ->		{true, fn_true};core_function('false') ->		{true, fn_false};core_function('lang') ->		true;core_function('number') ->		true;core_function('sum') ->			true;core_function('floor') ->		true;core_function('ceiling') ->		true;core_function('round') ->		true;core_function(_) ->    false.%%%  node set functions%% number: last()last(#xmlContext{nodeset = Set}, []) ->    ?number(length(Set)).%% number: position()position(#xmlContext{context_node = #xmlNode{pos = Pos}}, []) ->    ?number(Pos).%% number: count(node-set)count(C, [Arg]) ->    ?number(length(mk_nodeset(C, Arg))).%% node-set: id(object)id(C, [Arg]) ->    NS0 = [C#xmlContext.whole_document],    case Arg#xmlObj.type of	nodeset ->	    NodeSet = Arg#xmlObj.value,	    IdTokens = 		lists:foldl(		  fun(N, AccX) ->			  StrVal = string_value(N),			  TokensX = id_tokens(StrVal),			  TokensX ++ AccX		  end, [], NodeSet),	    NewNodeSet = 		xmerl_xpath:axis(descendant_or_self, 				 fun(Node) ->					 attribute_test(Node, id, IdTokens)				 end, C#xmlContext{nodeset = NS0}),	    ?nodeset(NewNodeSet);	_ ->	    StrVal = string_value(Arg#xmlObj.value),	    IdTokens = id_tokens(StrVal),	    lists:foldl(	      fun(Tok, AccX) ->		      select_on_attribute(NS0, id, Tok, AccX)	      end, [], IdTokens)    end.id_tokens(Str) ->    string:tokens(Str, " \t\n\r").			  attribute_test(#xmlNode{node = #xmlElement{attributes = Attrs}}, 	       Key, Vals) ->    case lists:keysearch(Key, #xmlAttribute.name, Attrs) of	{value, #xmlAttribute{value = V}} ->	    lists:member(V, Vals);	_ ->	    false    end;attribute_test(_Node, _Key, _Vals) ->    false.%%% CONTINUE HERE!!!!%% string: local-name(node-set?)'local-name'(C, []) ->    local_name1(default_nodeset(C));'local-name'(C, [Arg]) ->    local_name1(mk_nodeset(C, Arg)).local_name1([]) ->    ?string([]);local_name1([#xmlElement{name = Name, nsinfo = NSI}|_]) ->    case NSI of	{_Prefix, Local} ->	    ?string(Local);	[] ->	    ?string(Name)    end.%% string: namespace-uri(node-set?)'namespace-uri'(C, []) ->    ns_uri(default_nodeset(C));'namespace-uri'(C, [Arg]) ->    ns_uri(mk_nodeset(C, Arg)).ns_uri([]) ->    ?string([]);ns_uri([#xmlElement{nsinfo = NSI, namespace = NS}|_]) ->    case NSI of	{Prefix, _} ->	    case lists:keysearch(Prefix, 1, NS#xmlNamespace.nodes) of		false ->		    ?string([]);		{value, {_K, V}} ->		    ?string(V)	    end;	[] ->	    []    end.%%% String functions%% string: string(object?)string(C, []) ->    ns_string(default_nodeset(C));string(C, [Arg]) ->    string_value(mk_object(C, Arg)).ns_string([Obj|_]) ->

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -