3 * Stefano Zacchiroli <zack@cs.unibo.it>
4 * for the HELM Team http://helm.cs.unibo.it/
6 * This file is part of HELM, an Hypertextual, Electronic
7 * Library of Mathematics, developed at the Computer Science
8 * Department, University of Bologna, Italy.
10 * HELM is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * HELM is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with HELM; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * For details, see the HELM World-Wide-Web page,
26 * http://helm.cs.unibo.it/
32 exception Stylesheet_not_found of string ;;
33 exception Stylesheet_already_in of string ;;
34 exception Unsupported_property of string;;
36 let xslNS = Gdome.domString "http://www.w3.org/1999/XSL/Transform"
37 let outputS = Gdome.domString "output"
38 let q_outputS = Gdome.domString "xsl:output"
40 let default_properties = [] (* no default properties *)
42 (** apply an output property to an xslt stylesheet *)
43 let apply_property logger (element: Gdome.element) (name, value) =
44 if Uwobo_common.is_supported_property name then begin
45 logger#log `Debug (sprintf "Setting property: %s = %s" name value);
46 element#setAttribute (Gdome.domString name) (Gdome.domString value)
48 raise (Unsupported_property name)
50 (** set a list of output properties in an xslt stylesheet, return a copy of
51 the given stylesheet modified as needed, given stylesheet wont be changed by
53 Before applying "props" properties applies a set of default properties as
54 defined in "default_properties" *)
55 let apply_properties logger last_stylesheet props =
57 new Gdome.document_of_node (last_stylesheet#cloneNode ~deep:true)
60 let node_list = last_stylesheet#getElementsByTagNameNS xslNS outputS in
61 (match node_list#item 0 with
62 | None -> (* no xsl:output element, create it from scratch *)
63 logger#log `Debug "Creating xsl:output node ...";
64 let elt = last_stylesheet#createElementNS (Some xslNS) q_outputS in
65 let root = last_stylesheet#get_documentElement in
66 ignore (root#appendChild (elt :> Gdome.node));
68 | Some node -> new Gdome.element_of_node node)
71 (apply_property logger (output_element :> Gdome.element))
72 (default_properties @ props);
77 (* INVARIANT: 'stylesheets' and 'uris' are in sync *)
79 (** association list: key * props -> I_gdome_xslt.processed_stylesheet
80 It is the cache of the processed stylesheets *)
81 val mutable p_stylesheets = []
82 val mutable stylesheets = [] (** association list: key -> Gdome.document *)
83 val mutable uris = [] (** association list: key -> uri *)
85 val domImpl = Gdome.domImplementation ()
87 (** process an XSLT stylesheet *)
88 method private process uri =
89 let dom = domImpl#createDocumentFromURI ~uri () in
90 dom, Gdome_xslt.processStylesheet dom (* produce libXSLT messages in
93 (* stylesheets management *)
96 if (List.mem_assoc key uris) then
97 raise (Stylesheet_already_in key)
99 uris <- (key, uri) :: uris;
100 let stylesheet, p_stylesheet = self#process uri in
101 stylesheets <- (key, stylesheet) :: stylesheets ;
102 p_stylesheets <- ((key,[]), p_stylesheet) :: p_stylesheets ;
106 if not (List.mem_assoc key uris) then
107 raise (Stylesheet_not_found key)
109 uris <- List.remove_assoc key uris;
110 stylesheets <- List.remove_assoc key stylesheets ;
112 List.filter (function ((key',_),_) -> key = key') p_stylesheets
122 let uri = List.assoc key uris in
123 let stylesheet,p_stylesheet = self#process uri in
125 (key, stylesheet) :: (List.remove_assoc key stylesheets) ;
126 (* we remove the processed stylesheet from the cache *)
128 List.filter (function ((key',_),_) -> key = key') p_stylesheets ;
129 p_stylesheets <- ((key,[]),p_stylesheet)::p_stylesheets
131 raise (Stylesheet_not_found key))
134 let (stylesheets',p_stylesheets') =
136 List.map (fun (key, uri) -> (key, self#process uri)) uris
138 List.map (function (key,(stylesheet,_)) -> key,stylesheet) processed,
140 (function (key,(_,p_stylesheet)) -> (key,[]),p_stylesheet) processed
142 stylesheets <- stylesheets' ;
143 p_stylesheets <- p_stylesheets'
145 (* stylesheets usage *)
147 method keys = List.map fst uris
152 sprintf "key = %s, uri = %s" key (List.assoc key uris))
155 method get keys props (logger : Uwobo_logger.sysLogger) =
156 match List.rev keys with
158 | last_key::rev_keys ->
159 let last_stylesheet =
161 List.assoc last_key stylesheets
162 with Not_found -> raise (Stylesheet_not_found last_key)
164 let p_last_stylesheet =
166 List.assoc (last_key,props) p_stylesheets
170 let last_stylesheet' =
172 apply_properties logger last_stylesheet props
173 with Unsupported_property prop ->
174 raise (Uwobo_failure (sprintf "Unsupported property: %s" prop))
176 let p_last_stylesheet =
177 Gdome_xslt.processStylesheet last_stylesheet'
180 ((last_key,props),p_last_stylesheet)::p_stylesheets ;
185 (fun collected_styles key ->
188 List.assoc (key,[]) p_stylesheets
194 List.assoc key stylesheets
195 with Not_found -> raise (Stylesheet_not_found key)
198 Gdome_xslt.processStylesheet stylesheet
200 p_stylesheets <- ((key,[]),p_stylesheet)::p_stylesheets ;
203 (key,p_stylesheet)::collected_styles)
204 [last_key,p_last_stylesheet]
207 p_stylesheets, last_stylesheet