]> matita.cs.unibo.it Git - helm.git/blob - helm/gTopLevel/xmlDiff.ml
XmlDiff-ing of DOM trees implemented.
[helm.git] / helm / gTopLevel / xmlDiff.ml
1 (* Copyright (C) 2000-2002, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  *)
25
26 let update_dom ~(from : Gdome.document) (d : Gdome.document) =
27  let rec aux (p: Gdome.node) (f: Gdome.node) (t: Gdome.node) =
28 (* Perche' non andava?
29   if f#get_localName = t#get_localName &&
30      f#get_namespaceURI = t#get_namespaceURI
31 *)
32   match
33    f#get_nodeType,t#get_nodeType,
34    f#get_namespaceURI,t#get_namespaceURI,
35    f#get_localName,t#get_localName
36   with
37      GdomeNodeTypeT.TEXT_NODE,GdomeNodeTypeT.TEXT_NODE,_,_,_,_ when
38       match f#get_nodeValue, t#get_nodeValue with
39          Some v, Some v' -> v#to_string = v'#to_string
40        | _,_ -> assert false
41       ->
42 prerr_endline ("XML_DIFF: preservo il nodo testo " ^ match f#get_nodeValue with Some v -> v#to_string | None -> assert false);
43        ()
44    | GdomeNodeTypeT.ELEMENT_NODE,GdomeNodeTypeT.ELEMENT_NODE,
45       Some nu, Some nu', Some ln, Some ln' when
46        ln#to_string = ln'#to_string && nu#to_string = nu'#to_string ->
47 prerr_endline ("XML_DIFF: preservo il nodo "^ nu#to_string ^ ":" ^ln#to_string);
48         begin
49          match f#get_attributes, t#get_attributes with
50             Some fattrs, Some tattrs ->
51              let flen = fattrs#get_length in
52              let tlen = tattrs#get_length in
53               let processed = ref [] in
54               for i = 0 to flen -1 do
55                match fattrs#item i with
56                   None -> assert false
57                 | Some attr ->
58                     match attr#get_namespaceURI with
59                        None ->
60                         (* Back to DOM Level 1 ;-( *)
61                         begin
62                          let name = attr#get_nodeName in
63                           match tattrs#getNamedItem ~name with
64                              None ->
65 prerr_endline ("XML_DIFF: rimuovo l'attributo " ^ name#to_string);
66                               ignore (f#removeChild attr)
67                            | Some attr' ->
68                               processed :=
69                                (None,Some name)::!processed ;
70                               match attr#get_nodeValue, attr'#get_nodeValue with
71                                  Some v1, Some v2 when
72                                      v1#to_string = v2#to_string
73                                   || (name#to_string = "selection" &&
74                                       nu#to_string =
75                                        "http://www.w3.org/1998/Math/MathML" &&
76                                       ln#to_string = "maction")
77                                   ->
78 prerr_endline ("XML_DIFF: DOM 1; preservo l'attributo " ^ name#to_string);
79                                    ()
80                                | Some _, Some _ ->
81 prerr_endline ("XML_DIFF: DOM 1; rimpiazzo l'attributo " ^ name#to_string);
82                                   let attr'' = from#importNode attr' true in
83                                    ignore (fattrs#setNamedItem attr'')
84                                | _,_ -> assert false
85                         end
86                      | Some namespaceURI ->
87                         let localName = 
88                          match attr#get_localName with
89                            Some v -> v
90                           | None -> assert false
91                         in
92                          match
93                           tattrs#getNamedItemNS ~namespaceURI ~localName
94                          with
95                             None ->
96 prerr_endline ("XML_DIFF: rimuovo l'attributo " ^ localName#to_string);
97                              ignore (f#removeChild attr)
98                           | Some attr' ->
99                              processed :=
100                               (Some namespaceURI,Some localName)::!processed ;
101                              (*CSC: questo mi dice read-only ;-( 
102                                attr#set_nodeValue attr'#get_nodeValue *)
103                              (*CSC: questo mi abortisce con una assert
104                              let attr'' = from#importNode attr' true in
105                               ignore(f#replaceChild ~newChild:attr'' ~oldChild:attr)*)
106                               match attr#get_nodeValue, attr'#get_nodeValue with
107                                  Some v1, Some v2 when
108                                   v1#to_string = v2#to_string ->
109 prerr_endline ("XML_DIFF: DOM 2; preservo l'attributo " ^ namespaceURI#to_string ^ ":" ^ localName#to_string);
110                                    ()
111                                | Some _, Some _ ->
112 prerr_endline ("XML_DIFF: DOM 2; rimpiazzo l'attributo " ^ namespaceURI#to_string ^ ":" ^ localName#to_string);
113                                   let attr'' = from#importNode attr' true in
114                                    ignore (fattrs#setNamedItem attr'')
115                                | _,_ -> assert false
116               done ;
117               for i = 0 to tlen -1 do
118                match tattrs#item i with
119                   None -> assert false
120                 | Some attr ->
121 let debugs = ref "" in
122                    let namespaceURI,localName =
123                     match attr#get_namespaceURI with
124                        None ->
125 debugs := ("XML_DIFF: DOM 1.0; creo un nuovo attributo " ^ attr#get_nodeName#to_string) ;
126                         None,attr#get_nodeName
127                      | Some namespaceURI as v ->
128 debugs := ("XML_DIFF: DOM 2.0; creo un nuovo attributo " ^ namespaceURI#to_string ^ ":" ^ match attr#get_localName with Some v -> v#to_string | None -> assert false);
129                        v, match attr#get_localName with
130                           None -> assert false
131                         | Some v -> v
132                    in
133                     if
134                      not
135                       (List.exists
136                         (function
137                             None,Some localName' ->
138                              (match namespaceURI with
139                                  None ->
140                                   localName#to_string = localName'#to_string
141                                | Some _ -> false)
142                           | Some namespaceURI', Some localName' ->
143                              (match namespaceURI with
144                                  None -> false
145                                | Some namespaceURI ->
146                                   localName#to_string = localName'#to_string &&
147                                   namespaceURI#to_string=namespaceURI'#to_string
148                              )
149                           | _,_ -> assert false
150                         ) !processed)
151                     then
152                      let attr' = from#importNode attr false in
153 prerr_endline !debugs ;
154                       ignore (fattrs#setNamedItem attr')
155               done
156           | _,_ -> assert false
157         end ;
158         let fchildren = f#get_childNodes in
159         let tchildren = t#get_childNodes in
160          let rec dumb_diff =
161           function
162              [],[] -> ()
163            | he1::tl1,he2::tl2 ->
164 prerr_endline "XML_DIFF: processo una coppia di figli" ;
165               aux f he1 he2 ;
166               dumb_diff (tl1,tl2)
167            | [],tl2 ->
168 prerr_endline "XML_DIFF: appendo i nodi residui" ;
169               List.iter
170                (function n ->
171                  let n' = from#importNode n true in
172                   ignore (f#appendChild n')
173                ) tl2
174            | tl1,[] ->
175 prerr_endline "XML_DIFF: cancello i nodi residui" ;
176               List.iter (function n -> ignore (f#removeChild n)) tl1
177          in
178           let node_list_of_nodeList nl =
179            let rec aux i =
180             match nl#item ~index:i with
181                None -> []
182              | Some n when
183                    n#get_nodeType = GdomeNodeTypeT.ELEMENT_NODE
184                 or n#get_nodeType = GdomeNodeTypeT.TEXT_NODE ->
185                  n::(aux (i+1))
186              | Some n ->
187 prerr_endline ("XML_DIFF: mi sto perdendo i nodi di tipo " ^ string_of_int (Obj.magic n#get_nodeType)) ;
188                aux (i+1)
189            in
190             aux 0
191           in
192 for i = 0 to fchildren#get_length - 1 do
193 match fchildren#item i with
194 None -> prerr_endline "EUREKA: ma siamo matti?"
195 |Some n ->
196 match n#get_nodeType with GdomeNodeTypeT.ATTRIBUTE_NODE -> prerr_endline "EUREKA attr" | GdomeNodeTypeT.CDATA_SECTION_NODE -> prerr_endline "EUREKA text" | GdomeNodeTypeT.DOCUMENT_FRAGMENT_NODE -> prerr_endline "EUREKA document fragment" | _ -> prerr_endline ("EUREKA " ^ string_of_int (Obj.magic n#get_nodeType))
197 done ;
198 prerr_endline("XML_DIFF: from ha " ^ string_of_int fchildren#get_length ^ " nodi, ovvero " ^ string_of_int (List.length (node_list_of_nodeList fchildren)) ^ " figli");
199 prerr_endline("XML_DIFF: to   ha " ^ string_of_int tchildren#get_length ^ " nodi, ovvero " ^ string_of_int (List.length (node_list_of_nodeList tchildren)) ^ " figli");
200            dumb_diff
201             (node_list_of_nodeList fchildren, node_list_of_nodeList tchildren)
202    | t1,t2,_,_,_,_ when
203       (t1 = GdomeNodeTypeT.ELEMENT_NODE || t1 = GdomeNodeTypeT.TEXT_NODE) &&
204       (t2 = GdomeNodeTypeT.ELEMENT_NODE || t2 = GdomeNodeTypeT.TEXT_NODE) ->
205        let t' = from#importNode t true in
206 prerr_endline "XML_DIFF: importo il nodo" ;
207 (*
208 prerr_endline ("Rimpiazzo" ^ (match f#get_namespaceURI with Some s -> s#to_string) ^ ":" ^ (match f#get_localName with Some s -> s#to_string) ^ " con " ^ (match t#get_namespaceURI with Some s -> s#to_string) ^ ":" ^ (match t#get_localName with Some s -> s#to_string) ^ " in " ^ (match p#get_localName with Some s -> s#to_string | None -> "_")) ;
209 *)
210         ignore (p#replaceChild ~newChild:t' ~oldChild:f)
211    | _,_,_,_,_,_ -> assert false
212  in
213   try
214    aux (d :> Gdome.node)
215     (from#get_documentElement :> Gdome.node)
216     (d#get_documentElement :> Gdome.node)
217   with
218      (GdomeInit.DOMException (e,msg) as ex) ->
219 (*
220     let module E = GdomeDOMExceptionT in
221 *)
222        prerr_endline
223         ("DOM EXCEPTION: " ^ msg ^ " --- " ^
224 string_of_int (Obj.magic e)) ;
225        raise ex
226  (*
227         match e with
228            E.NO_ERR -> "NO_ERR"
229          | E.INDEX_SIZE_ERR -> "INDEX_SIZE_ERR"
230          | E.DOMSTRING_SIZE_ERR -> "DOMSTRING_SIZE_ERR"
231          | E.HIERARCHY_REQUEST_ERR -> "HIERARCHY_REQUEST_ERR"
232          | E.WRONG_DOCUMENT_ERR -> "WRONG_DOCUMENT_ERR"
233          | E.INVALID_CHARACTER_ERR -> "INVALID_CHARACTER_ERR"
234          | E.NO_DATA_ALLOWED_ERR -> "NO_DATA_ALLOWER_ERR"
235          | E.NO_MODIFICATION_ALLOWED_ERR -> "NO_MODIFICATION_ALLOWED_ERR"
236          | E.NOT_FOUND_ERR -> "NOT_FOUND_ERR"
237          | E.NOT_SUPPORTED_ERR -> "NOT_SUPPORTED_ERR"
238          | E.INUSE_ATTRIBUTE_ERR -> "INUSE_ATTRIBUTE_ERR"
239          | E.INVALID_STATE_ERR -> "INVALID_STATE_ERR"
240          | E.SYNTAX_ERR -> "SYNTAX_ERR"
241          | E.INVALID_MODIFICATION_ERR -> "INVALID_MODIFICATION_ERR"
242          | E.NAMESPACE_ERR -> "NAMESPACE_ERR"
243          | E.INVALID_ACCESS_ERR -> "INVALID_ACCESS_ERR"
244 *)
245   | e ->
246     prerr_endline "PROBLEMA" ;
247     raise e
248 ;;