001: /* Copyright 2001 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.utils;
007:
008: import java.io.BufferedInputStream;
009: import java.io.IOException;
010: import java.io.StringReader;
011: import java.net.URL;
012: import java.util.ArrayList;
013: import java.util.Enumeration;
014: import java.util.HashMap;
015: import java.util.Hashtable;
016: import java.util.Iterator;
017: import java.util.Locale;
018: import java.util.ResourceBundle;
019:
020: import javax.xml.transform.Result;
021: import javax.xml.transform.Source;
022: import javax.xml.transform.SourceLocator;
023: import javax.xml.transform.Templates;
024: import javax.xml.transform.Transformer;
025: import javax.xml.transform.TransformerConfigurationException;
026: import javax.xml.transform.TransformerException;
027: import javax.xml.transform.TransformerFactory;
028: import javax.xml.transform.dom.DOMResult;
029: import javax.xml.transform.dom.DOMSource;
030: import javax.xml.transform.sax.SAXResult;
031: import javax.xml.transform.sax.SAXTransformerFactory;
032: import javax.xml.transform.sax.TemplatesHandler;
033: import javax.xml.transform.sax.TransformerHandler;
034: import javax.xml.transform.stream.StreamResult;
035: import javax.xml.transform.stream.StreamSource;
036:
037: import org.jasig.portal.car.ResourceResolver;
038: import org.jasig.portal.BrowserInfo;
039: import org.jasig.portal.GeneralRenderingException;
040: import org.jasig.portal.PortalException;
041: import org.jasig.portal.ResourceMissingException;
042: import org.jasig.portal.StylesheetSet;
043: import org.jasig.portal.i18n.LocaleAwareXSLT;
044: import org.jasig.portal.properties.PropertiesManager;
045: import org.apache.commons.logging.Log;
046: import org.apache.commons.logging.LogFactory;
047: import org.w3c.dom.Document;
048: import org.w3c.dom.Element;
049: import org.w3c.dom.Node;
050: import org.w3c.dom.NodeList;
051: import org.xml.sax.ContentHandler;
052: import org.xml.sax.SAXException;
053: import org.xml.sax.SAXParseException;
054: import org.xml.sax.XMLReader;
055: import org.xml.sax.helpers.XMLReaderFactory;
056:
057: /**
058: * This utility provides methods for transforming XML documents
059: * via XSLT. It takes advantage of Xalan's ability to pre-compile
060: * stylehseets into StylesheetRoot objects. The first time a transform
061: * is requested, a stylesheet is compiled and cached.</p>
062: * <p>None of the method signatures in this class should contain
063: * classes specific to a particular XSLT engine, e.g. Xalan, or
064: * XML parser, e.g. Xerces.</p>
065: * <p>The constructor for XSLT takes an instance of whatever class is requesting
066: * the transformation. XSLT uses this instance to locate resources relative
067: * to the classpath.</p>
068: * <p>Typical usage:</p>
069: * <p><code><pre>
070: * XSLT xslt = new XSLT(this);
071: * xslt.setXML("myXMLDoc.xml");
072: * xslt.setSSL("myChannel.ssl", "aTitle", runtimeData.getBrowserInfo());
073: * xslt.setTarget(out);
074: * xslt.setStylesheetParameter("param1Name", "param1Value");
075: * xslt.setStylesheetParameter("param2Name", "param2Value");
076: * xslt.transform();
077: * </pre></code></p>
078: *
079: * @author Ken Weiner, kweiner@unicon.net
080: * @version $Revision: 42266 $
081: */
082: public class XSLT {
083:
084: private static final Log log = LogFactory.getLog(XSLT.class);
085:
086: // These flags should be set to true for production to
087: // ensure that pre-compiled stylesheets and stylesheet sets are cached.
088: protected static boolean stylesheetRootCacheEnabled = PropertiesManager
089: .getPropertyAsBoolean(
090: "org.jasig.portal.utils.XSLT.stylesheet_root_caching",
091: true);
092: protected static boolean stylesheetSetCacheEnabled = PropertiesManager
093: .getPropertyAsBoolean(
094: "org.jasig.portal.utils.XSLT.stylesheet_set_caching",
095: true);
096: protected static final String mediaProps = "/properties/media.properties";
097: protected static final Hashtable stylesheetRootCache = new Hashtable(); // Consider changing to org.jasig.portal.utils.SmartCache
098: protected static final Hashtable stylesheetSetCache = new Hashtable(); // Consider changing to org.jasig.portal.utils.SmartCache
099:
100: private static SAXTransformerFactory saxTFactory = null;
101:
102: protected Object caller = null;
103: protected Source xmlSource;
104: protected Result xmlResult;
105: protected HashMap stylesheetParams;
106: protected String xslURI;
107: protected ResourceBundle l18n;
108:
109: /**
110: * Constructs an XSLT object. This contructor should
111: * be declared protected, but it will remain public for a while
112: * until most client code is changed to use the getTransformer()
113: * methods. <strong>Please avoid using this constructor!</strong>
114: * @param instance the client of this utility
115: */
116: public XSLT(Object instance) {
117: this .stylesheetParams = new HashMap();
118: this .caller = instance;
119: }
120:
121: /**
122: * Factory method that produces an XSLT transformer utility.
123: * @param instance the client of this utility
124: * @return a transformer utility
125: * @since uPortal 2.2
126: */
127: public static XSLT getTransformer(Object instance) {
128: return new XSLT(instance);
129: }
130:
131: /**
132: * Factory method that produces an XSLT transformer utility
133: * with a capability of choosing a stylesheet depending on a
134: * list of locales.
135: * @param instance the client of this utility
136: * @return a locale-aware transformer utility
137: * @since uPortal 2.2
138: */
139: public static XSLT getTransformer(Object instance, Locale[] locales) {
140: return new LocaleAwareXSLT(instance, locales);
141: }
142:
143: public static SAXTransformerFactory getSAXTFactory() {
144: if (saxTFactory == null) {
145: // attempt to instantiate a sax transformer factory
146: TransformerFactory tFactory = TransformerFactory
147: .newInstance();
148: tFactory.setURIResolver(new ResourceResolver());
149: if (tFactory instanceof SAXTransformerFactory) {
150: saxTFactory = ((SAXTransformerFactory) tFactory);
151: }
152: }
153: if (saxTFactory == null) {
154: log
155: .error("XSLT() : unable to instantiate SAX transformer ! Please make sure the TRAX implementation you're using supports SAX Transformers");
156: }
157: return saxTFactory;
158: }
159:
160: /**
161: * Configures the xml source.
162: * @param xml a string representing the xml document
163: */
164: public void setXML(String xml) {
165: xmlSource = new StreamSource(new StringReader(xml));
166: }
167:
168: /**
169: * Configures the xml source.
170: * @param xml a node representing the xml document
171: */
172: public void setXML(Node xml) {
173: xmlSource = new DOMSource(xml);
174: }
175:
176: /**
177: * Configures the xml source.
178: * @param is an input stream to the serialized xml source
179: */
180: public void setXML(java.io.InputStream is) {
181: xmlSource = new StreamSource(is);
182: }
183:
184: /**
185: * Configures the xml source.
186: * @param file a File object representing the xml source
187: */
188: public void setXML(java.io.File file) {
189: xmlSource = new StreamSource(file);
190: }
191:
192: /**
193: * Configures the xsl source.
194: * @param xslUri the URL of an XSLT stylesheet
195: */
196: public void setXSL(String xslUri) throws PortalException {
197: this .xslURI = ResourceLoader.getResourceAsURLString(caller
198: .getClass(), xslUri);
199: }
200:
201: /**
202: * Configures the xsl source by choosing the appropriate stylesheet from
203: * the provided stylesheet list file.
204: * @param sslUri the URL of the stylesheet list file
205: * @param stylesheetTitle the title of a stylesheet within the stylesheet list file
206: * @param browserInfo the browser info object
207: * @throws org.jasig.portal.PortalException
208: */
209: public void setXSL(String sslUri, String stylesheetTitle,
210: BrowserInfo browserInfo) throws PortalException {
211: StylesheetSet set = getStylesheetSet(ResourceLoader
212: .getResourceAsURLString(caller.getClass(), sslUri));
213: set.setMediaProps(mediaProps);
214: String xslUri = set.getStylesheetURI(stylesheetTitle,
215: browserInfo);
216: setXSL(xslUri);
217: }
218:
219: /**
220: * Configures the xsl source by choosing the appropriate stylesheet from
221: * the provided stylesheet list file.
222: * @param sslUri the URL of the stylesheet list file
223: * @param browserInfo the browser info object
224: * @throws org.jasig.portal.PortalException
225: */
226: public void setXSL(String sslUri, BrowserInfo browserInfo)
227: throws PortalException {
228: setXSL(sslUri, (String) null, browserInfo);
229: }
230:
231: /**
232: * Configures the xslt target.
233: * @param contentHandler the content handler
234: */
235: public void setTarget(ContentHandler contentHandler) {
236: xmlResult = new SAXResult(contentHandler);
237: }
238:
239: /**
240: * Configures the xslt target.
241: * @param os output stream
242: */
243: public void setTarget(java.io.OutputStream os) {
244: xmlResult = new StreamResult(os);
245: }
246:
247: /**
248: * Configures the xslt target.
249: * @param node target node
250: */
251: public void setTarget(org.w3c.dom.Node node) {
252: xmlResult = new DOMResult(node);
253: }
254:
255: /**
256: * Sets all the stylesheet parameters at once.
257: * @param stylesheetParameters a Hashtable of stylesheet parameters
258: */
259: public void setStylesheetParameters(Hashtable stylesheetParameters) {
260: stylesheetParams.putAll(stylesheetParameters);
261: }
262:
263: /**
264: * Sets all the stylesheet parameters at once.
265: * @param stylesheetParameters a HashMap of stylesheet parameters
266: */
267: public void setStylesheetParameters(HashMap stylesheetParameters) {
268: stylesheetParams = stylesheetParameters;
269: }
270:
271: /**
272: * Sets all the stylesheet parameters at once.
273: * @param name the name of the stylesheet parameter
274: * @param value the value of the stylesheet parameter
275: */
276: public void setStylesheetParameter(String name, String value) {
277: stylesheetParams.put(name, value);
278: }
279:
280: /**
281: * Performs a transformation. Assumes that the XML, XSL, and result targets
282: * have already been set.
283: * @throws org.jasig.portal.PortalException
284: */
285: public void transform() throws PortalException {
286: try {
287: Transformer trans;
288: if (l18n == null) {
289: trans = getTransformer(this .xslURI);
290: } else {
291: trans = getTransformer(this .xslURI, l18n);
292: }
293: setStylesheetParams(trans, stylesheetParams);
294: trans.transform(xmlSource, xmlResult);
295: } catch (PortalException pe) {
296: throw pe;
297: } catch (SAXParseException p) {
298: throw new PortalException("Parse exception occurred "
299: + "on line " + p.getLineNumber() + ", column "
300: + p.getColumnNumber() + " in "
301: + "document with public ID " + p.getPublicId()
302: + ", and system ID " + p.getSystemId() + ".", p);
303: } catch (TransformerException p) {
304: throw new PortalException(p.getMessageAndLocation(), p);
305: } catch (Exception e) {
306: throw new PortalException(e);
307: }
308: }
309:
310: /**
311: * Performs an XSL transformation. Accepts stylesheet parameters
312: * (key, value pairs) stored in a Hashtable.
313: * @param xmlSource the source to be transformedn
314: * @param xmlResult the result to be populated
315: * @param stylesheetParams a Hashtable of key/value pairs or <code>null</code> if no parameters
316: * @param xslURI the uri of the stylesheet to be used
317: * @throws org.jasig.portal.PortalException if something goes wrong
318: */
319: public static void transform(Source xmlSource, Result xmlResult,
320: Hashtable stylesheetParams, String xslURI)
321: throws PortalException {
322: try {
323: Transformer trans = getTransformer(xslURI);
324: setStylesheetParams(trans, stylesheetParams);
325: trans.transform(xmlSource, xmlResult);
326: } catch (PortalException pe) {
327: throw pe;
328: } catch (Exception e) {
329: throw new PortalException(e);
330: }
331: }
332:
333: /**
334: * Extracts name/value pairs from a Hashtable and uses them to create stylesheet parameters
335: * @param transformer the XSLT processor
336: * @param stylesheetParams name/value pairs used as stylesheet parameters
337: * @deprecated replaced by {@link #setStylesheetParams(Transformer, HashMap)}
338: */
339: private static void setStylesheetParams(Transformer transformer,
340: Hashtable stylesheetParams) {
341: if (stylesheetParams != null) {
342: HashMap stylesheetParamsHashMap = new HashMap();
343: stylesheetParamsHashMap.putAll(stylesheetParams);
344: setStylesheetParams(transformer, stylesheetParamsHashMap);
345: }
346: }
347:
348: /**
349: * Extracts name/value pairs from a Hashtable and uses them to create stylesheet parameters
350: * @param transformer the XSLT processor
351: * @param stylesheetParams name/value pairs used as stylesheet parameters
352: */
353: private static void setStylesheetParams(Transformer transformer,
354: HashMap stylesheetParams) {
355: if (stylesheetParams != null) {
356: Iterator iterator = stylesheetParams.keySet().iterator();
357: while (iterator.hasNext()) {
358: String key = (String) iterator.next();
359: Object o = stylesheetParams.get(key);
360: if (o != null) {
361: if (o.getClass().getName().equals(
362: "[Ljava.lang.String;")) {
363: // This situation occurs for some requests from cell phones
364: o = ((String[]) o)[0];
365: }
366: transformer.setParameter(key, o);
367: } else {
368: log.warn("Stylesheet parameter [" + key
369: + "] was illegally null.");
370: }
371: }
372: }
373: }
374:
375: public void setResourceBundle(ResourceBundle bundle) {
376: this .l18n = bundle;
377: }
378:
379: /**
380: * This method caches compiled stylesheet objects, keyed by the stylesheet's URI and locale.
381: * @param stylesheetURI the URI of the XSLT stylesheet
382: * @param l18n the localized strings to add to the xsl
383: * @return the StlyesheetRoot object
384: * @throws SAXException
385: */
386: public static Templates getTemplates(String stylesheetURI,
387: ResourceBundle l18n) throws SAXException, PortalException,
388: TransformerConfigurationException {
389: String lookup = new StringBuffer(stylesheetURI).append(
390: l18n.getLocale().toString()).toString();
391: Templates temp = (Templates) stylesheetRootCache.get(lookup);
392: if (temp == null) {
393: Document xsl = null;
394: try {
395: URL url = ResourceLoader.getResourceAsURL(
396: DocumentFactory.class, stylesheetURI);
397: xsl = DocumentFactory
398: .getDocumentFromStream(new BufferedInputStream(
399: url.openStream(), 2048), url
400: .toExternalForm());
401: } catch (IOException e) {
402: throw new ResourceMissingException(
403: stylesheetURI,
404: "Stylesheet",
405: "Unable to read stylesheet from the specified location. Please check the stylesheet URL");
406: }
407: addLocalization(xsl, l18n);
408: Source src = new DOMSource(xsl);
409: TransformerFactory tFactory = TransformerFactory
410: .newInstance();
411: temp = tFactory.newTemplates(src);
412: if (stylesheetRootCacheEnabled) {
413: stylesheetRootCache.put(lookup, temp);
414: }
415: }
416: return temp;
417: }
418:
419: /**
420: * This method caches compiled stylesheet objects, keyed by the stylesheet's URI.
421: * @param stylesheetURI the URI of the XSLT stylesheet
422: * @return the StlyesheetRoot object
423: * @throws SAXException
424: */
425: public static Templates getTemplates(String stylesheetURI)
426: throws SAXException, PortalException {
427: // First, check the cache...
428: Templates temp = (Templates) stylesheetRootCache
429: .get(stylesheetURI);
430: if (temp == null) {
431: // Get the Templates and cache them
432: try {
433: TemplatesHandler thand = getSAXTFactory()
434: .newTemplatesHandler();
435: XMLReader reader = XMLReaderFactory.createXMLReader();
436: reader.setContentHandler(thand);
437: reader.parse(stylesheetURI);
438: temp = thand.getTemplates();
439: if (stylesheetRootCacheEnabled) {
440: stylesheetRootCache.put(stylesheetURI, temp);
441: if (log.isInfoEnabled())
442: log.info("Caching templates for: "
443: + stylesheetURI);
444: }
445: } catch (IOException ioe) {
446: throw new ResourceMissingException(stylesheetURI,
447: "Stylesheet",
448: "Unable to read stylesheet from ["
449: + stylesheetURI
450: + "]. Please check the stylesheet URL",
451: ioe);
452: } catch (TransformerConfigurationException tce) {
453: log
454: .error(
455: "XSLT::getTemplates() : unable to obtain TemplatesHandler due to TRAX misconfiguration!",
456: tce);
457: throw new GeneralRenderingException(
458: "XSLT: current TRAX configuration does not allow for TemplateHandlers. Please reconfigure/reinstall your TRAX implementation.",
459: tce);
460: } catch (SAXParseException px) {
461: throw new GeneralRenderingException(
462: "XSLT:getTemplates(): SAXParseExeption: "
463: + px.getMessage() + " line:"
464: + px.getLineNumber() + " col:"
465: + px.getColumnNumber(), px);
466: } catch (SAXException sx) {
467: // Catch the sax exception so we can report line number info
468: if (null != sx.getException()
469: && (sx.getException() instanceof TransformerException)) {
470: TransformerException trx = (TransformerException) sx
471: .getException();
472: throw new GeneralRenderingException(trx
473: .getMessageAndLocation(), trx);
474: }
475: throw sx;
476: }
477: }
478: return temp;
479: }
480:
481: /**
482: * This method returns a localized Transformer for a given stylesheet.
483: * @param stylesheetURI the URI of the XSLT stylesheet
484: * @return <code>Transformer</code>
485: * @throws SAXException
486: */
487: public static Transformer getTransformer(String stylesheetURI,
488: ResourceBundle l18n) throws SAXException, PortalException {
489: Transformer t = null;
490: try {
491: t = getTemplates(stylesheetURI, l18n).newTransformer();
492: } catch (TransformerConfigurationException tce) {
493: log
494: .error("XSLT::getTransformer() : TRAX transformer is misconfigured : "
495: + tce.getMessage());
496: SourceLocator loc = tce.getLocator();
497: if (loc != null)
498: throw new PortalException(tce.getClass().getName()
499: + " occurred " + "for document "
500: + stylesheetURI + " at line "
501: + loc.getLineNumber() + " and column "
502: + loc.getColumnNumber() + ".", tce);
503: throw new PortalException(tce.getClass().getName()
504: + " occurred " + "for document " + stylesheetURI
505: + ".", tce);
506: }
507: return t;
508: }
509:
510: /**
511: * This method returns a Transformer for a given stylesheet.
512: * @param stylesheetURI the URI of the XSLT stylesheet
513: * @return <code>Transformer</code>
514: * @throws SAXException
515: */
516: public static Transformer getTransformer(String stylesheetURI)
517: throws SAXException, PortalException {
518: Transformer t = null;
519: try {
520: t = getTemplates(stylesheetURI).newTransformer();
521: } catch (TransformerConfigurationException tce) {
522: log
523: .error(
524: "XSLT::getTransformer() : TRAX transformer is misconfigured",
525: tce);
526: }
527: return t;
528: }
529:
530: /**
531: * This method returns a TransformerHandler for a given stylesheet.
532: * @param stylesheetURI the URI of the XSLT stylesheet
533: * @return <code>Transformer</code>
534: * @throws SAXException
535: */
536: public static TransformerHandler getTransformerHandler(
537: String stylesheetURI) throws SAXException, PortalException {
538: TransformerHandler th = null;
539: try {
540: th = getSAXTFactory().newTransformerHandler(
541: getTemplates(stylesheetURI));
542: } catch (TransformerConfigurationException tce) {
543: log
544: .error(
545: "XSLT::getTransformerHandler() : TRAX transformer is misconfigured",
546: tce);
547: }
548: return th;
549: }
550:
551: /**
552: * This method returns a localized TransformerHandler for a given stylesheet.
553: * @param stylesheetURI the URI of the XSLT stylesheet
554: * @param locales the list of locales
555: * @param caller the calling class
556: * @return <code>Transformer</code>
557: * @throws SAXException
558: */
559: public static TransformerHandler getTransformerHandler(
560: String stylesheetURI, Locale[] locales, Object caller)
561: throws SAXException, PortalException {
562: TransformerHandler th = null;
563: try {
564: String localizedStylesheetURI = LocaleAwareXSLT
565: .getLocaleAwareXslUri(stylesheetURI, locales,
566: caller);
567: th = getSAXTFactory().newTransformerHandler(
568: getTemplates(localizedStylesheetURI));
569: } catch (TransformerConfigurationException tce) {
570: log
571: .error(
572: "XSLT::getTransformerHandler() : TRAX transformer is misconfigured",
573: tce);
574: }
575: return th;
576: }
577:
578: /**
579: * This method caches compiled stylesheet set objects, keyed by the stylesheet list's URI.
580: * @param stylesheetListURI the URI of the XSLT stylesheet list file (.ssl)
581: * @return the StlyesheetSet object
582: * @throws PortalException
583: */
584: public static StylesheetSet getStylesheetSet(
585: String stylesheetListURI) throws PortalException {
586: // First, check the cache...
587: StylesheetSet stylesheetSet = (StylesheetSet) stylesheetSetCache
588: .get(stylesheetListURI);
589: if (stylesheetSet == null) {
590: // Get the StylesheetSet and cache it
591: stylesheetSet = new StylesheetSet(stylesheetListURI);
592: if (stylesheetSetCacheEnabled) {
593: stylesheetSetCache
594: .put(stylesheetListURI, stylesheetSet);
595: if (log.isInfoEnabled())
596: log.info("Caching StylesheetSet for: "
597: + stylesheetListURI);
598: }
599: }
600: return stylesheetSet;
601: }
602:
603: /**
604: * Returns a stylesheet URI exactly as it appears in a stylesheet list file.
605: * @param sslUri the stylesheet list file URI
606: * @param browserInfo the browser information
607: * @return the stylesheet URI as a string
608: * @throws org.jasig.portal.PortalException
609: */
610: public static String getStylesheetURI(String sslUri,
611: BrowserInfo browserInfo) throws PortalException {
612: StylesheetSet set = getStylesheetSet(sslUri);
613: String xslUri = set.getStylesheetURI(browserInfo);
614: return xslUri;
615: }
616:
617: /**
618: * Returns a stylesheet URI exactly as it appears in a stylesheet list file.
619: * @param sslUri the stylesheet list file URI
620: * @param title the stylesheet title
621: * @param browserInfo the browser information
622: * @return the stylesheet URI as a string
623: * @throws org.jasig.portal.PortalException
624: */
625: public static String getStylesheetURI(String sslUri, String title,
626: BrowserInfo browserInfo) throws PortalException {
627: StylesheetSet set = getStylesheetSet(sslUri);
628: String xslUri = set.getStylesheetURI(title, browserInfo);
629: return xslUri;
630: }
631:
632: /**
633: * Writes a set of key/value pairs from a resourcebundle as global variables
634: * in an xsl stylesheet
635: *
636: * @param xsl the xsl stylesheet as a DOM document
637: * @param localization the resource bundle of key/value pairs to be written to xsl variables
638: */
639: protected static void addLocalization(Document xsl,
640: ResourceBundle localization) {
641: ArrayList keys = new ArrayList();
642: Enumeration en = localization.getKeys();
643: while (en.hasMoreElements()) {
644: keys.add(en.nextElement());
645: }
646: //String test = "test";
647: Element root = xsl.getDocumentElement();
648: Node ft = root.getFirstChild();
649: boolean foundFT = false;
650: NodeList nl = root.getChildNodes();
651: for (int i = 0; i < nl.getLength(); i++) {
652: Node n = nl.item(i);
653: if (n.getNodeType() == Node.ELEMENT_NODE) {
654: Element e = (Element) n;
655: //System.out.println("Checking Element "+e.getNamespaceURI()+":"+e.getLocalName());
656: if (!foundFT
657: && e.getNamespaceURI().equals(
658: "http://www.w3.org/1999/XSL/Transform")
659: && e.getLocalName().equals("template")) {
660: //System.out.println("found first template in position "+i);
661: ft = n;
662: foundFT = true;
663: }
664: if (e.getNamespaceURI().equals(
665: "http://www.w3.org/1999/XSL/Transform")
666: && e.getLocalName().equals("variable")) {
667: String name = e.getAttribute("name");
668: //System.out.println(name+" = "+e.getAttribute("select"));
669: //test = e.getAttribute("select");
670: if (keys.contains(name)) {
671: e.removeAttribute("select");
672: if (e.hasChildNodes()) {
673: NodeList cl = e.getChildNodes();
674: for (int j = cl.getLength() - 1; j >= 0; j--) {
675: e.removeChild(cl.item(j));
676: }
677: }
678: e.appendChild(xsl.createTextNode(localization
679: .getString(name)));
680: keys.remove(name);
681: }
682: }
683: }
684: }
685:
686: for (int z = 0; z < keys.size(); z++) {
687: String k = (String) keys.get(z);
688: String v = localization.getString(k);
689: Element e = xsl.createElementNS(
690: "http://www.w3.org/1999/XSL/Transform",
691: "xsl:variable");
692: e.setAttribute("name", k);
693: e.appendChild(xsl.createTextNode(v));
694:
695: //System.out.println(e.getAttribute("select"));
696: root.insertBefore(e, ft);
697: }
698: xsl.normalizeDocument();
699:
700: }
701:
702: /**
703: * Escape problem characters which will be inserted into XSL
704: *
705: * @param s the string to escape
706: */
707: protected static String escape(String s) {
708: // for initial implementation, just look for single quote
709: s = CommonUtils.replaceText(s, "'", "\u2019");
710: return s;
711: }
712:
713: /**
714: * Purge the cache of stylesheet roots and stylesheet sets.
715: */
716: public static void purgeStylesheetCache() {
717: stylesheetRootCache.clear();
718: stylesheetSetCache.clear();
719: }
720:
721: /**
722: * Get the number of stylesheets in the stylesheet root cache.
723: * @return the number of stylesheets in the stylesheet root cache.
724: */
725: public static int getStylesheetCacheSize() {
726: return stylesheetRootCache.size();
727: }
728:
729: public String toString() {
730: StringBuffer sb = new StringBuffer();
731: sb.append("XSLT: ");
732: sb.append(" stylesheetRootCacheEnabled:");
733: sb.append(XSLT.stylesheetRootCacheEnabled);
734: sb.append(" stylesheetSetCacheEnabled: ");
735: sb.append(XSLT.stylesheetSetCacheEnabled);
736: sb.append(" mediaProps: ");
737: sb.append(XSLT.mediaProps);
738: if (this .caller != null) {
739: sb.append(" caller:");
740: sb.append(this .caller.getClass().getName());
741: }
742: if (this .xslURI != null) {
743: sb.append(" xslURI:");
744: sb.append(this .xslURI);
745: }
746: if (this .stylesheetParams != null) {
747: sb.append(" stylesheetParams:");
748: sb.append(this.stylesheetParams);
749: }
750: return sb.toString();
751: }
752: }
|