8 type query_tree_desc = Binop of op * query_tree * query_tree
9 | Axis of Xpath.Ast.axis * query_tree
12 | Tag of QNameSet.t * Tree.NodeKind.t
14 and op = Union | Inter | Diff
17 mutable desc : query_tree_desc;
27 (q1.id == q2.id && q1.id != -1) ||
28 match q1.desc, q2.desc with
29 | Binop(op1,qt1,qt2),Binop(op2,qt3,qt4)-> op1==op2&& (equal qt1 qt3 && equal qt2 qt4)
31 | Axis(a1,qt1),Axis(a2,qt2) -> compare_axis a1 a2 && equal qt1 qt2
32 | Tag(t1,k1),Tag(t2,k2) -> t1==t2&& k1==k2
33 | Dom,Dom | Start,Start -> true
35 and compare_axis a1 a2 =
37 Self ,Self | Attribute, Attribute | Child , Child | Parent , Parent
38 | FollowingSibling , FollowingSibling
39 | PrecedingSibling , PrecedingSibling
40 | Preceding , Preceding | Following , Following -> true
41 | Descendant b1, Descendant b2 -> b1==b2
42 | Ancestor b1, Ancestor b2 -> b1==b2
46 if q.hash != -1 then q.hash
47 else match q.desc with
50 | Tag(s,_) -> 5 + 17*QNameSet.hash s
51 | Axis(a,q) -> 7 + 17 * Hashtbl.hash a + 23* hash q
52 | Binop(op,q1,q2) -> 11 + 17* Hashtbl.hash op + 23* hash q1 + 27* hash q2
57 module QTreeHash = Hashtbl.Make(QTree)
62 parametres : tree l'arbre xml
65 retour :un noeud qui correspond ॆ la relation r
68 let print_node_list tree l =
69 List.iter (fun node ->
70 Naive_tree.print_xml stdout tree node;
74 let rec print_query_tree fmt q =
76 Dom -> Format.fprintf fmt "Dom"
77 | Start -> Format.fprintf fmt "Start"
78 | Tag (t,k) -> Format.fprintf fmt "Tag(%a, %a)" QNameSet.print t Tree.NodeKind.print k
80 Format.fprintf fmt "%a(%a)" Xpath.Ast.print_axis a print_query_tree q
82 Format.fprintf fmt "%a(%a, %a)"
87 and print_binop fmt o =
89 | Union -> Format.fprintf fmt "Union"
90 | Inter -> Format.fprintf fmt "Inter"
91 | Diff -> Format.fprintf fmt "Diff"
93 let rec eval_relation tree m n =
96 | Firstchild -> Naive_tree.first_child tree n
97 | Nextsibling -> Naive_tree.next_sibling tree n
98 | Revfirstchild -> Naive_tree.parent_of_first tree n
99 | Prevsibling -> Naive_tree.prev_sibling tree n
102 parametres : tree l'arbre xml
103 ls l'ensemble de noeuds
105 retour : l'ensemble de noeuds qui correspondent ॆ la relation r
109 let compare_node tree a b =
110 compare (Naive_tree.preorder tree a ) (Naive_tree.preorder tree b )
112 let rec eval_move tree ls m =
115 | r -> List.filter (fun n -> n != Naive_tree.nil)
116 (List.map (eval_relation tree r) ls)
120 parametres : tree l'arbre xml
121 ls l'ensemble de noeuds
123 retour : l'ensemble de noeuds qui correspondent ॆ des relations lr
126 and eval_star tree ls lr =
127 let h = Hashtbl.create 17 in
128 let q = Queue.create () in
129 List.iter ( fun e -> Queue.add e q ) ls;
130 while not (Queue.is_empty q ) do
131 let n = Queue.pop q in
132 if not (Hashtbl.mem h n) then begin
134 List.iter ( fun r -> let m = eval_relation tree r n in
135 if m != Naive_tree.nil && not (Hashtbl.mem h m ) then begin
141 let l = Hashtbl.fold (fun k _ acc -> k::acc) h [] in
142 List.sort (compare_node tree) l
145 parametres : tree l'arbre xml
146 ls l'ensemble de noeuds
148 retour : l'ensemble de noeuds qui correspondent ॆ l'axe
151 let keep_elements t l = (*
152 List.filter (fun n -> match Naive_tree.kind t n with
153 | Element | Text | Document | Attribute -> true | _ -> false) l
156 let keep_attributs t l = (*
157 List.filter (fun n -> match Naive_tree.kind t n with
158 | Attribute ->true | _ -> false) *) l
160 let rec eval_axis tree ls a =
161 let open Xpath.Ast in
165 | Attribute -> let lfc = eval_move tree ls Firstchild in
166 let lc = eval_star tree lfc [Nextsibling] in
167 keep_attributs tree lc
169 | Child -> let lfc = eval_move tree ls Firstchild in
170 let lc = eval_star tree lfc [Nextsibling] in
171 keep_elements tree lc
173 | Descendant c -> let lfc = eval_move tree ls Firstchild in
174 let ls2 = eval_star tree lfc [Firstchild;Nextsibling] in
177 else List.merge (compare_node tree) ls2 ls
179 keep_elements tree ldes
181 | FollowingSibling -> let lnexts = eval_move tree ls Nextsibling in
182 let lfs = eval_star tree lnexts [Nextsibling] in
183 keep_elements tree lfs
185 | Parent -> let lprevs = eval_star tree ls [Prevsibling] in
186 let lp = eval_move tree lprevs Revfirstchild in
187 keep_elements tree lp
189 | Ancestor b -> let ls2 = eval_star tree ls [Revfirstchild;Prevsibling] in
190 let ls3 = eval_move tree ls2 Revfirstchild in
193 else List.merge (compare_node tree ) ls3 ls
195 keep_elements tree lac
197 | PrecedingSibling -> let ls2 = eval_star tree ls [Prevsibling] in
198 let lps = eval_move tree ls2 Prevsibling in
199 keep_elements tree lps
201 | Preceding -> let ls2 = eval_axis tree ls (Ancestor true) in
202 let ls3 = eval_axis tree ls2 PrecedingSibling in
203 let lp = eval_axis tree ls3 (Descendant true) in
204 keep_elements tree lp
206 | Following -> let ls2 = eval_axis tree ls (Ancestor true) in
207 let ls3 = eval_axis tree ls2 FollowingSibling in
208 let lf = eval_axis tree ls3 (Descendant true) in
209 keep_elements tree lf