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

Last change on this file since 25397 was 25397, checked in by ak19, 12 years ago

Correction to previous commit where xsl:import statements during merging of stylesheets were considered. The way they were handled was wrong, since xsl:import statements must come at the top as first children of the xsl:stylesheet parent. This updated code corrects this and also improves the way xsl:include and xsl:output statements are handled.

  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 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 org.w3c.dom.Node;
22import org.w3c.dom.Element;
23import org.w3c.dom.NodeList;
24import org.w3c.dom.Document;
25
26import java.util.Vector;
27import java.util.ArrayList;
28
29/** various functions for manipulating Greenstone xslt */
30public class GSXSLT
31{
32 /**
33 * takes a stylesheet Document, and adds in any child nodes from extra_xsl
34 * named templates overwrite any existing one, while match templates are
35 * just added to the end of teh stylesheet
36 */
37 public static void mergeStylesheets(Document main_xsl, Element extra_xsl)
38 {
39 Element main = main_xsl.getDocumentElement();
40
41 NodeList children = extra_xsl.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "import");
42 for (int i = 0; i < children.getLength(); i++) {
43 Node node = children.item(i);
44 // If the new xsl:import element is identical (in terms of href attr value)
45 // to any in the merged document, don't copy it over
46 if(!isDuplicateElement(main, node, "xsl:import", "href")) {
47 // Import statements should be the first children of an xsl:stylesheet element
48 // If firstchild is null, then this xsl:import element will be inserted at the "end"
49 // Although Node.insertBefore() will first remove identical nodes before inserting, we check
50 // only the href attribute to see if they're "identical" to any pre-existing <xsl:import>
51 main.insertBefore(main_xsl.importNode(node, true), main.getFirstChild());
52 }
53 }
54
55 children = extra_xsl.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "include");
56 for (int i = 0; i < children.getLength(); i++) {
57 Node node = children.item(i);
58 // If the new xsl:include element is identical (in terms of href attr value)
59 // to any in the merged document, don't copy it over
60 // Although Node.appendChild() will first remove identical nodes before appending, we check
61 // only the href attribute to see if they're "identical" to any pre-existing <xsl:include>
62 if(!isDuplicateElement(main, node, "xsl:include", "href")) {
63 main.appendChild(main_xsl.importNode(node, true));
64 }
65 }
66
67 children = extra_xsl.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "output");
68 for (int i = 0; i < children.getLength(); i++) {
69 Node node = children.item(i);
70 // If the new xsl:output element is identical (in terms of the value for the method attr)
71 // to any in the merged document, don't copy it over
72 if(!isDuplicateElement(main, node, "xsl:output", "method")) {
73 main.appendChild(main_xsl.importNode(node, true));
74 }
75 }
76
77 children = extra_xsl.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "template");
78 for (int i = 0; i < children.getLength(); i++)
79 {
80 Node node = children.item(i);
81 // remove any previous occurrences of xsl:template with the same value for name
82 // or even the same value for match (should we use priorities for match?)
83 removeDuplicateElementsFrom(main, node, "xsl:template", "name");
84 removeDuplicateElementsFrom(main, node, "xsl:template", "match");
85 main.appendChild(main_xsl.importNode(node, true));
86 }
87 }
88
89 // In element main, tries to find any previous occurrence of elements with xsl-template-name=templateName,
90 // and whose named attribute (attributeName) has the same value as the same attribute in node.
91 // If this is the case, such a previous occurrence is removed from element main, since
92 // the new node will contain a more specific redefinition of this element.
93 public static void removeDuplicateElementsFrom(Element main, Node node, String templateName, String attrName) {
94 String attr = ((Element) node).getAttribute(attrName);
95 if (!attr.equals(""))
96 {
97 Element old_template = GSXML.getNamedElement(main, templateName, attrName, attr);
98 if (old_template != null)
99 {
100 main.removeChild(old_template);
101 }
102 }
103 }
104
105 // Call this method on elements like xsl:include, xsl:import and xsl:output
106 // In element main, tries to find any previous occurrence of elements with xsl-element-name=xslName,
107 // and whose named attribute (attributeName) has the same value as the same attribute in node.
108 // If this is the case, it returns true, since the element would a complete duplicate for our intents.
109 public static boolean isDuplicateElement(Element main, Node node, String xslName, String attrName) {
110 String attr = ((Element) node).getAttribute(attrName);
111 if (!attr.equals(""))
112 {
113 Element old_element = GSXML.getNamedElement(main, xslName, attrName, attr);
114 if (old_element != null)
115 {
116 return true;
117 }
118 }
119 return false;
120 }
121
122 /**
123 * takes any import or include nodes, and creates absolute path names for
124 * the files
125 */
126 public static void absoluteIncludePaths(Document stylesheet, String gsdl3_home, String site_name, String collection, String interface_name, ArrayList base_interfaces)
127 {
128
129 Element base_node = stylesheet.getDocumentElement();
130 if (base_node == null)
131 {
132 return;
133 }
134 Node child = base_node.getFirstChild();
135 while (child != null)
136 {
137 String name = child.getNodeName();
138 if (name.equals("xsl:import") || name.equals("xsl:include"))
139 {
140 ((Element) child).setAttribute("href", GSFile.stylesheetFile(gsdl3_home, site_name, collection, interface_name, base_interfaces, ((Element) child).getAttribute("href")));
141 }
142 child = child.getNextSibling();
143 }
144
145 }
146
147 /**
148 * looks through a stylesheet for <xxx:template match='template_name'>
149 * inside this template it looks for any <xxx:value-of
150 * select='metadataList/metadata[@name=yyy]> elements, and extracts the
151 * metadata names into a Vector
152 */
153 public static Vector extractWantedMetadata(Document stylesheet, String template_name)
154 {
155
156 Vector metadata = new Vector();
157 Element base_node = stylesheet.getDocumentElement();
158 NodeList templates = base_node.getElementsByTagNameNS("*", "template");
159 for (int i = 0; i < templates.getLength(); i++)
160 {
161 Element template = (Element) templates.item(i);
162 String match_name = template.getAttribute("match");
163 if (!match_name.equals(template_name))
164 {
165 continue; // we're only looking for specific templates
166 }
167 String mode = template.getAttribute("mode");
168 if (!mode.equals(""))
169 {
170 continue; // we only want ones without modes - these are processing ones, not display ones
171 }
172 // we have one that we want to look through
173 NodeList values = template.getElementsByTagNameNS("*", "value-of");
174 for (int v = 0; v < values.getLength(); v++)
175 {
176 String select = ((Element) values.item(v)).getAttribute("select");
177 if (select.startsWith("metadataList/metadata[@name="))
178 {
179 String[] bits = select.split("'|\"");
180 // there should be two quotes in teh string, therefore 3 items, and the second one is teh one we want
181 String name = bits[1];
182 metadata.add(name);
183 }
184 }
185 }
186 return metadata;
187 }
188
189}
Note: See TracBrowser for help on using the repository browser.