source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXSLT.java@ 25924

Last change on this file since 25924 was 25924, checked in by sjm84, 12 years ago

Removing an unnecessary print statement

  • Property svn:keywords set to Author Date Id Revision
File size: 14.7 KB
Line 
1/*
2 * GSXSLT.java
3 * Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.util;
20
21import java.io.File;
22import java.util.ArrayList;
23import java.util.Vector;
24
25import org.greenstone.util.GlobalProperties;
26import org.w3c.dom.Document;
27import org.w3c.dom.Element;
28import org.w3c.dom.Node;
29import org.w3c.dom.NodeList;
30
31/** various functions for manipulating Greenstone xslt */
32public class GSXSLT
33{
34 public static void mergeStylesheets(Document main_xsl, Element extra_xsl, boolean overwrite)
35 {
36 mergeStylesheetsDebug(main_xsl, extra_xsl, overwrite, false, null, null);
37 }
38
39 /**
40 * takes a stylesheet Document, and adds in any child nodes from extra_xsl
41 * named templates overwrite any existing one, while match templates are
42 * just added to the end of the stylesheet
43 *
44 * elements are added in following order, and added to preserve original
45 * order with imported ones coming after existing ones import, include,
46 * output, variable, template
47 */
48 public static void mergeStylesheetsDebug(Document main_xsl, Element extra_xsl, boolean overwrite, boolean debug, String firstDocFileName, String secondDocFileName)
49 {
50 if (debug)
51 {
52 System.err.println("ADDING DEBUG ELEMENTS WITH FILE NAME " + firstDocFileName);
53 insertDebugElements(main_xsl, firstDocFileName);
54 }
55
56 Element main = main_xsl.getDocumentElement();
57 Node insertion_point = null;
58 Element last_import = GSXML.getLastElementByTagNameNS(main, "http://www.w3.org/1999/XSL/Transform", "import");
59 if (last_import != null)
60 {
61 insertion_point = last_import.getNextSibling();
62 }
63 else
64 {
65 insertion_point = main.getFirstChild();
66 }
67
68 // imports
69 NodeList children = extra_xsl.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "import");
70 for (int i = 0; i < children.getLength(); i++)
71 {
72 Element node = (Element) children.item(i);
73 // If the new xsl:import element is identical (in terms of href attr value)
74 // to any in the merged document, don't copy it over
75 if (GSXML.getNamedElementNS(main, "http://www.w3.org/1999/XSL/Transform", "import", "href", node.getAttribute("href")) == null)
76 {
77 // Import statements should be the first children of an xsl:stylesheet element
78 // If firstchild is null, then this xsl:import element will be inserted at the "end"
79 // Although Node.insertBefore() will first remove identical nodes before inserting, we check
80 // only the href attribute to see if they're "identical" to any pre-existing <xsl:import>
81 //main.insertBefore(main_xsl.importNode(node, true), main.getFirstChild());
82 main.insertBefore(main_xsl.importNode(node, true), insertion_point);
83 }
84 }
85
86 // do we have a new insertion point??
87 Element last_include = GSXML.getLastElementByTagNameNS(main, "http://www.w3.org/1999/XSL/Transform", "include");
88 if (last_include != null)
89 {
90 insertion_point = last_include.getNextSibling();
91 }
92
93 // includes
94 children = extra_xsl.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "include");
95 for (int i = 0; i < children.getLength(); i++)
96 {
97 Element node = (Element) children.item(i);
98 // If the new xsl:include element is identical (in terms of href attr value)
99 // to any in the merged document, don't copy it over
100 // Although Node.appendChild() will first remove identical nodes before appending, we check
101 // only the href attribute to see if they're "identical" to any pre-existing <xsl:include>
102 if (GSXML.getNamedElementNS(main, "http://www.w3.org/1999/XSL/Transform", "include", "href", node.getAttribute("href")) == null)
103 {
104 //main.appendChild(main_xsl.importNode(node, true));
105 main.insertBefore(main_xsl.importNode(node, true), insertion_point);
106 }
107 } // for each include
108
109 if (main.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "output").getLength() == 0)
110 {
111 // outputs
112 children = extra_xsl.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "output");
113 for (int i = 0; i < children.getLength(); i++)
114 {
115 Element node = (Element) children.item(i);
116 // If the new xsl:output element is identical (in terms of the value for the method attr)
117 // to any in the merged document, don't copy it over
118
119 main.insertBefore(main_xsl.importNode(node, true), insertion_point);
120 }
121 }
122
123 // variables - only top level ones!!
124 // append to end of document
125 children = GSXML.getChildrenByTagNameNS(extra_xsl, "http://www.w3.org/1999/XSL/Transform", "variable");
126 for (int i = 0; i < children.getLength(); i++)
127 {
128 Element node = (Element) children.item(i);
129 // If the new xsl:import element is identical (in terms of href attr value)
130 // to any in the merged document, don't copy it over
131 if (GSXML.getNamedElementNS(main, "http://www.w3.org/1999/XSL/Transform", "variable", "name", node.getAttribute("name")) == null)
132 {
133 main.appendChild(main_xsl.importNode(node, true));
134 }
135 }
136
137 // params - only top level ones!!
138 // append to end of document
139 children = GSXML.getChildrenByTagNameNS(extra_xsl, "http://www.w3.org/1999/XSL/Transform", "param");
140 for (int i = 0; i < children.getLength(); i++)
141 {
142 Element node = (Element) children.item(i);
143 // If the new xsl:import element is identical (in terms of href attr value)
144 // to any in the merged document, don't copy it over
145 if (GSXML.getNamedElementNS(main, "http://www.w3.org/1999/XSL/Transform", "param", "name", node.getAttribute("name")) == null)
146 {
147 main.appendChild(main_xsl.importNode(node, true));
148 }
149 }
150
151 // templates
152 // append to end of document
153 children = extra_xsl.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "template");
154 for (int i = 0; i < children.getLength(); i++)
155 {
156 Element node = (Element) children.item(i);
157 // remove any previous occurrences of xsl:template with the same value for name or match
158 String template_match = node.getAttribute("match");
159 String template_name = node.getAttribute("name");
160 String template_mode = node.getAttribute("mode");
161
162 if (overwrite)
163 {
164 // if we have a name attribute, remove any other similarly named template
165 if (!template_name.equals(""))
166 {
167 GSXML.removeNamedElementNS(main, "http://www.w3.org/1999/XSL/Transform", "template", "name", template_name);
168 }
169 // if we have a match attribute, remove other templates that match -
170 if (!template_match.equals(""))
171 {
172 GSXML.removeNamedElementsNS(main, "http://www.w3.org/1999/XSL/Transform", "template", "match", template_match);
173 }
174 // now add our good template in
175 main.appendChild(main_xsl.importNode(node, true));
176 }
177 else
178 {
179 // if overwrite is false, then we only add in templates if they don't match something else.
180 // In this case (eg from expanding imported stylesheets)
181 // there can't be any duplicate named templates, so just look for matches
182 // we already have the one with highest import precedence (from the top most level) so don't add any more in
183 if (GSXML.getNamedElementNS(main, "http://www.w3.org/1999/XSL/Transform", "template", "match", template_match) == null)
184 {
185 main.appendChild(main_xsl.importNode(node, true));
186 }
187
188 if (GSXML.getNamedElementNS(main, "http://www.w3.org/1999/XSL/Transform", "template", "name", template_name) == null)
189 {
190 main.appendChild(main_xsl.importNode(node, true));
191 }
192 }
193 }
194
195 if (debug)
196 {
197 System.err.println("ADDING DEBUG ELEMENTS WITH FILE NAME " + secondDocFileName);
198 insertDebugElements(main_xsl, secondDocFileName);
199 }
200 }
201
202 protected static void insertDebugElements(Document doc, String fileName)
203 {
204 NodeList htmlTags = GSXML.getHTMLStructureElements(doc);
205 System.err.println("HTML TAGS SIZE IS " + htmlTags.getLength());
206 for (int i = 0; i < htmlTags.getLength(); i++)
207 {
208 Element current = (Element) htmlTags.item(i);
209 if (current.getUserData("GSDEBUGFILENAME") == null)
210 {
211 Element xslParent = (Element) current.getParentNode();
212
213 while (xslParent.getNamespaceURI() != "http://www.w3.org/1999/XSL/Transform" && !xslParent.getNodeName().startsWith("xsl:"))
214 {
215 xslParent = (Element) xslParent.getParentNode();
216 }
217
218 System.err.println("ADDING FILE NAME " + fileName);
219 current.setUserData("GSDEBUGFILENAME", fileName, null);
220 current.setUserData("GSDEBUGXML", xslParent.cloneNode(true), null);
221 }
222 else
223 {
224 System.err.println("ALREADY SET!");
225 }
226 }
227 }
228
229 public static void inlineImportAndIncludeFiles(Document doc, String pathExtra)
230 {
231 inlineImportAndIncludeFilesDebug(doc, pathExtra, false, null);
232 }
233
234 public static void inlineImportAndIncludeFilesDebug(Document doc, String pathExtra, boolean debug, String docFileName)
235 {
236 XMLConverter converter = new XMLConverter();
237
238 String path = (pathExtra == null) ? "" : pathExtra;
239
240 NodeList importList = doc.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "import");
241 NodeList includeList = doc.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "include");
242
243 for (int i = 0; i < importList.getLength() + includeList.getLength(); i++)
244 {
245 Element current = (Element) ((i < importList.getLength()) ? importList.item(i) : includeList.item(i - importList.getLength()));
246 String href = current.getAttribute("href");
247 String filePath = GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), "default") + File.separator + "transform" + File.separator + path.replace("/", File.separator) + href.replace("/", File.separator);
248
249 try
250 {
251 Document inlineDoc = converter.getDOM(new File(filePath), "UTF-8");
252
253 String newPath = path;
254 int lastSepIndex = href.lastIndexOf("/");
255 if (lastSepIndex != -1)
256 {
257 newPath += href.substring(0, lastSepIndex + 1);
258 }
259
260 //Do this recursively
261 inlineImportAndIncludeFilesDebug(inlineDoc, newPath, debug, filePath);
262
263 GSXSLT.mergeStylesheetsDebug(doc, inlineDoc.getDocumentElement(), false, debug, docFileName, filePath);
264 }
265 catch (Exception ex)
266 {
267 ex.printStackTrace();
268 return;
269 }
270 }
271
272 while (importList.getLength() > 0)
273 {
274 Element importElem = (Element) importList.item(0);
275 importElem.getParentNode().removeChild(importElem);
276 }
277 while (includeList.getLength() > 0)
278 {
279 Element includeElem = (Element) includeList.item(0);
280 includeElem.getParentNode().removeChild(includeElem);
281 }
282 }
283
284 public static void modifyConfigFormatForDebug(Document doc, String fileName)
285 {
286 NodeList templateNodes = doc.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "template");
287 if (templateNodes.getLength() == 0)
288 {
289 templateNodes = doc.getElementsByTagName("xsl:template");
290 }
291
292 String debugElementString = "";
293 debugElementString += "<span class=\"configDebugSpan\" style=\"display:none;\">";
294 debugElementString += " \"filename\":\"" + fileName + "\",";
295 debugElementString += " \"xml\":\"<xsl:value-of select=\"util:xmlNodeToString(.)\"/>\""; //<xsl:copy><xsl:copy-of select=\"@*\"/></xsl:copy>
296 debugElementString += "</span>";
297
298 XMLConverter converter = new XMLConverter();
299 Element debugElement = (Element) converter.getDOM("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xslt:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:xslt=\"output.xsl\" xmlns:gsf=\"http://www.greenstone.org/greenstone3/schema/ConfigFormat\">" + debugElementString + "</xslt:stylesheet>").getDocumentElement().getFirstChild();
300
301 for (int i = 0; i < templateNodes.getLength(); i++)
302 {
303 Element currentTemplate = (Element) templateNodes.item(i);
304 if (currentTemplate.getAttribute("match") != null && (currentTemplate.getAttribute("match").equals("gsf:metadata") || currentTemplate.getAttribute("match").equals("*") || currentTemplate.getAttribute("match").equals("format")))
305 {
306 continue;
307 }
308
309 if (currentTemplate.hasChildNodes())
310 {
311 currentTemplate.insertBefore(doc.importNode(debugElement.cloneNode(true), true), currentTemplate.getFirstChild());
312 }
313 else
314 {
315 currentTemplate.appendChild(doc.importNode(debugElement.cloneNode(true), true));
316 }
317 }
318 }
319
320 /**
321 * takes any import or include nodes, and creates absolute path names for
322 * the files
323 */
324 public static void absoluteIncludePaths(Document stylesheet, String gsdl3_home, String site_name, String collection, String interface_name, ArrayList<String> base_interfaces)
325 {
326 Element base_node = stylesheet.getDocumentElement();
327 if (base_node == null)
328 {
329 return;
330 }
331 Node child = base_node.getFirstChild();
332 while (child != null)
333 {
334 String name = child.getNodeName();
335 if (name.equals("xsl:import") || name.equals("xsl:include"))
336 {
337 ((Element) child).setAttribute("href", GSFile.stylesheetFile(gsdl3_home, site_name, collection, interface_name, base_interfaces, ((Element) child).getAttribute("href")));
338 }
339 child = child.getNextSibling();
340 }
341 }
342
343 /**
344 * looks through a stylesheet for <xxx:template match='template_name'>
345 * inside this template it looks for any <xxx:value-of
346 * select='metadataList/metadata[@name=yyy]> elements, and extracts the
347 * metadata names into a Vector
348 */
349 public static Vector<String> extractWantedMetadata(Document stylesheet, String template_name)
350 {
351
352 Vector<String> metadata = new Vector<String>();
353 Element base_node = stylesheet.getDocumentElement();
354 NodeList templates = base_node.getElementsByTagNameNS("*", "template");
355 for (int i = 0; i < templates.getLength(); i++)
356 {
357 Element template = (Element) templates.item(i);
358 String match_name = template.getAttribute("match");
359 if (!match_name.equals(template_name))
360 {
361 continue; // we're only looking for specific templates
362 }
363 String mode = template.getAttribute("mode");
364 if (!mode.equals(""))
365 {
366 continue; // we only want ones without modes - these are processing ones, not display ones
367 }
368 // we have one that we want to look through
369 NodeList values = template.getElementsByTagNameNS("*", "value-of");
370 for (int v = 0; v < values.getLength(); v++)
371 {
372 String select = ((Element) values.item(v)).getAttribute("select");
373 if (select.startsWith("metadataList/metadata[@name="))
374 {
375 String[] bits = select.split("'|\"");
376 // there should be two quotes in teh string, therefore 3 items, and the second one is teh one we want
377 String name = bits[1];
378 metadata.add(name);
379 }
380 }
381 }
382 return metadata;
383 }
384
385}
Note: See TracBrowser for help on using the repository browser.