123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169(*********************************************************************************)(* Xmldiff *)(* *)(* Copyright (C) 2014-2021 Institut National de Recherche en Informatique *)(* et en Automatique. All rights reserved. *)(* *)(* This program is free software; you can redistribute it and/or modify *)(* it under the terms of the GNU Lesser General Public License version *)(* 3 as published by the Free Software Foundation. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Library General Public License for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public *)(* License along with this program; if not, write to the Free Software *)(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)(* 02111-1307 USA *)(* *)(* Contact: Maxence.Guesdon@inria.fr *)(* *)(* *)(*********************************************************************************)(** *)openJs_of_ocamlmoduleXdiff=Xmldiffletlogs=Firebug.console##log(Js.strings);;letdom_of_xml=letrecmap(doc:Dom_html.documentJs.t)=function`Ds->letn=doc##createTextNode(Js.strings)in(n:>Dom.nodeJs.t)|`E(name,atts,subs)->letn=matchnamewith("",tag)->doc##createElement(Js.stringtag)|(uri,tag)->doc##createElementNS(Js.stringuri)(Js.stringtag)inXdiff.Nmap.iter(funnamev->letv=Js.stringvinmatchnamewith("",att)->ignore(n##setAttribute(Js.stringatt)v)|(uri,att)->tryignore(Js.Unsafe.meth_calln"setAttributeNS"(Array.mapJs.Unsafe.inject[|Js.stringuri;Js.stringatt;v|]))(* FIXME: use setAttributeNS when will be available *)with_->log("could not add attribute "^(Xdiff.string_of_namename)))atts;letsubs=List.map(mapdoc)subsinList.iter(Dom.appendChildn)subs;(n:>Dom.nodeJs.t)infun?(doc=Dom_html.document)t->mapdoct;;letdom_node_by_path?(doc=Dom_html.document)?(skip_node=(fun_->false))path=letrecnextnodepath=letnode=Js.Opt.get(node##.nextSibling)(fun_->log((Js.to_stringnode##.nodeName)^" has no sibling");raiseNot_found)initernodepathandon_child(node:Dom.nodeJs.t)path=letnode=Js.Opt.get(node##.firstChild)(fun_->log((Js.to_stringnode##.nodeName)^" has no child");raiseNot_found)initernodepathanditernodepath=ifskip_nodenodethennextnodepathelsematchpathwithXdiff.Path_cdatanwhennode##.nodeType=Dom.TEXT->ifn=0thennodeelsenextnode(Xdiff.Path_cdata(n-1))|Xdiff.Path_node(name,n,more)whennode##.nodeType=Dom.ELEMENT->let(pref,lname)=nameinletlname=String.lowercase_asciilnameinletnode_name=Js.to_stringnode##.nodeNamein(*log ("name="^s_name^", nodeName="^node_name^", n="^(string_of_int n));*)letnode_name=String.lowercase_asciinode_nameinletsame=lname=node_namein(*
match lname = node_name, pref with
false, _ -> false
| true, "" -> true
| true, _ ->
let uri = node##lookupNamespaceURI(Js.string "") in
let node_uri = node##namespaceURI in
log (Printf.sprintf "lname=%S, node_name=%S, uri=%S, node_uri=%S"
lname node_name
(Js.Opt.case uri (fun _ -> "") (fun uri -> Js.to_string uri))
(Js.Opt.case node_uri (fun _ -> "") (fun uri -> Js.to_string uri))
);
uri = node_uri
in
*)ifsamethenifn=0thenmatchmorewithNone->node|Somep->on_childnodepelsenextnode(Xdiff.Path_node(name,n-1,more))elsenextnode(Xdiff.Path_node(name,n,more))|p->nextnodepinon_child(doc:>Dom.nodeJs.t)pathletapply_patch_operation?(doc=Dom_html.document)?skip_node(path,op)=log(Xmldiff.string_of_patch_operation(path,op));letparentnode=Js.Opt.getnode##.parentNode(fun_->assertfalse)inletapplynodeop=matchopwith|Xdiff.PReplacetree->letparent=parentnodeinignore(parent##replaceChild(dom_of_xml~doctree)node)|Xdiff.PInsert(tree,`FirstChild)->ignore(node##insertBefore(dom_of_xml~doctree)(node##.firstChild))|Xdiff.PInsert(tree,`After)->letparent=parentnodeinignore(parent##insertBefore(dom_of_xml~doctree)(node##.nextSibling))|Xdiff.PDelete->letparent=parentnodeinignore(parent##removeChildnode)|Xdiff.PUpdateCDatas->letparent=parentnodeinlettext=Dom_html.document##createTextNode(Js.strings)inignore(parent##replaceChild(text:>Dom.nodeJs.t)node)|Xdiff.PUpdateNode(name,atts)whennode##.nodeType=Dom.TEXT->letn=dom_of_xml~doc(`E(name,atts,[]))inletparent=parentnodeinignore(parent##replaceChildnnode)|Xdiff.PUpdateNode(name,atts)whennode##.nodeType=Dom.ELEMENT->letparent=parentnodeinletn=dom_of_xml~doc(`E(name,atts,[]))inletchildren=node##.childNodesinfori=0tochildren##.length-1doJs.Opt.iternode##.firstChild(funnode->Dom.appendChildnnode);done;ignore(parent##replaceChildnnode)|Xdiff.PUpdateNode_->assertfalse|Xdiff.PMove(newpath,pos)->letparent_node=parentnodeinletremoved_node=parent_node##removeChildnodeinletnew_loc=dom_node_by_path~doc?skip_nodenewpathinmatchposwith|`FirstChild->ignore(new_loc##insertBeforeremoved_nodenew_loc##.firstChild)|`After->letnew_parent=parentnew_locinignore(new_parent##insertBeforeremoved_nodenew_loc##.nextSibling);inletnode=dom_node_by_path~doc?skip_nodepathinapply(node:>Dom.nodeJs.t)op;;letapply_dom_patch?doc?skip_nodel=List.iter(apply_patch_operation?doc?skip_node)l;;