Changeset 26494 for main/trunk/greenstone3/src/java/org/greenstone/gsdl3
- Timestamp:
- 2012-11-21T16:13:59+13:00 (11 years ago)
- Location:
- main/trunk/greenstone3/src/java/org/greenstone/gsdl3
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone3/src/java/org/greenstone/gsdl3/Library2.java
r26454 r26494 95 95 { 96 96 97 if (System.getenv("GSDL3SRCHOME") == null) { 98 System.out.println("Before calling this script, run: source gs3-setup.sh"); 99 System.exit(1); 100 } 101 97 102 if (args.length != 2) 98 103 { -
main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/XMLTransformer.java
r26457 r26494 25 25 import java.io.FileWriter; 26 26 import java.io.InputStreamReader; 27 import java.io.IOException; 27 28 import java.io.StringReader; 28 29 import java.io.StringWriter; 29 30 import java.io.UnsupportedEncodingException; 31 import java.net.MalformedURLException; 32 import java.net.URISyntaxException; 33 import java.net.URI; 34 import java.net.URL; 30 35 import java.util.HashMap; 31 36 import java.util.Iterator; … … 40 45 import javax.xml.transform.TransformerException; 41 46 import javax.xml.transform.TransformerFactory; 47 import javax.xml.transform.URIResolver; 42 48 import javax.xml.transform.dom.DOMResult; 43 49 import javax.xml.transform.dom.DOMSource; … … 264 270 } 265 271 } 272 273 /** 274 When transforming an XML with an XSLT from the command-line, there's two problems if calling 275 XMLTransformer.transform(File xslt, File xml): 276 277 1. Need to run the transformation process from the location of the stylesheet, else it can't find 278 the stylesheet in order to load it. This is resolved by setting the SystemID for the stylesheet. 279 280 2. The XSLT stylesheet has <xsl:import> statements importing further XSLTs which are furthermore 281 specified by relative paths, requiring that the XSLT (and perhaps also XML) input file is located 282 in the folder from which the relative paths of the import statements are specified. This is resolved 283 by working out the absolute path of each imported XSLT file and setting their SystemIDs too. 284 285 Without solving these problems, things will only work if we 1. run the transformation from the 286 web/interfaces/default/transform folder and 2. need to have the input XSLT file (and XML?) 287 placed in the web/interfacces/default/transform folder too 288 289 Both parts of the solution are described in: 290 http://stackoverflow.com/questions/3699860/resolving-relative-paths-when-loading-xslt-filse 291 292 After the systemID on the XSLT input file is set, we can run the command from the toplevel GS3 293 folder. 294 After resolving the URIs of the XSLT files imported by the input XSLT, by setting their systemIDs, 295 the input XSLT (and XML) file need not be located in web/interfaces/default/transform anymore. 296 */ 297 public Node transform(File stylesheet, File source, String interfaceName, Document docDocType) 298 { 299 try 300 { 301 TransformErrorListener transformerErrorListener = (TransformErrorListener) this.t_factory.getErrorListener(); 302 transformerErrorListener.setStylesheet(stylesheet); 303 304 // http://stackoverflow.com/questions/3699860/resolving-relative-paths-when-loading-xslt-files 305 Source xsltSource = new StreamSource(new InputStreamReader(new FileInputStream(stylesheet), "UTF-8")); 306 URI systemID = stylesheet.toURI(); 307 try { 308 URL url = systemID.toURL(); 309 xsltSource.setSystemId(url.toExternalForm()); 310 } catch (MalformedURLException mue) { 311 logger.error("Warning: Unable to set systemID for stylesheet to " + systemID); 312 logger.error("Got exception: " + mue.getMessage(), mue); 313 } 314 315 this.t_factory.setURIResolver(new ClasspathResourceURIResolver(interfaceName)); 316 Transformer transformer = this.t_factory.newTransformer(xsltSource); 317 // Alternative way of instantiating a newTransformer(): 318 //Templates cachedXSLT = this.t_factory.newTemplates(xsltSource); 319 //Transformer transformer = cachedXSLT.newTransformer(); 320 321 DOMResult result = (docDocType == null) ? new DOMResult() : new DOMResult(docDocType); 322 StreamSource streamSource = new StreamSource(new InputStreamReader(new FileInputStream(source), "UTF-8")); 323 324 transformer.setErrorListener(new TransformErrorListener(stylesheet, streamSource)); 325 326 transformer.transform(streamSource, result); 327 return result.getNode().getFirstChild(); 328 } 329 catch (TransformerConfigurationException e) 330 { 331 return transformError("XMLTransformer.transform(File, File)" + "\ncouldn't create transformer object for files\n" + stylesheet + "\n" + source, e); 332 } 333 catch (TransformerException e) 334 { 335 return transformError("XMLTransformer.transform(File, File)" + "\ncouldn't transform the source for files\n" + stylesheet + "\n" + source, e); 336 } 337 catch (UnsupportedEncodingException e) 338 { 339 return transformError("XMLTransformer.transform(File, File)" + "\ncouldn't read file due to an unsupported encoding\n" + stylesheet + "\n" + source, e); 340 } 341 catch (FileNotFoundException e) 342 { 343 return transformError("XMLTransformer.transform(File, File)" + "\ncouldn't find the file specified\n" + stylesheet + "\n" + source, e); 344 } 345 } 346 347 /** 348 * Class for resolving the relative paths used for <xsl:import>s 349 * when transforming XML with an XSLT 350 */ 351 class ClasspathResourceURIResolver implements URIResolver { 352 String interface_name; 353 354 public ClasspathResourceURIResolver(String interfaceName) { 355 interface_name = interfaceName; 356 } 357 358 /** 359 * Override the URIResolver.resolve() method to turn relative paths of imported xslt files into 360 * absolute paths and set these absolute paths as their SystemIDs when loading them into memory. 361 * @see http://stackoverflow.com/questions/3699860/resolving-relative-paths-when-loading-xslt-files 362 */ 363 364 @Override 365 public Source resolve(String href, String base) throws TransformerException { 366 367 //System.err.println("href: " + href); // e.g. href: layouts/main.xsl 368 //System.err.println("base: " + base); // e.g for *toplevel* base: file:/path/to/gs3-svn/CL1.xslt 369 370 371 // 1. for any xsl imported by the original stylesheet, try to work out its absolute path location 372 // by concatenating the parent folder of the base stylesheet file with the href of the file it 373 // imports (which is a path relative to the base file). This need not hold true for the very 1st 374 // base stylesheet: it may be located somewhere entirely different from the greenstone XSLT 375 // files it refers to. This is the case when running transforms on the commandline for testing 376 377 File importXSLfile = new File(href); // assume the xsl imported has an absolute path 378 379 if(!importXSLfile.isAbsolute()) { // imported xsl specifies a path relative to parent of base 380 try { 381 URI baseURI = new URI(base); 382 importXSLfile = new File(new File(baseURI).getParent(), href); 383 384 if(!importXSLfile.exists()) { // if the imported file does not exist, it's not 385 // relative to the base (the stylesheet file importing it). So look in the 386 // interface's transform subfolder for the xsl file to be imported 387 importXSLfile = new File(GSFile.interfaceStylesheetFile(GlobalProperties.getGSDL3Home(), interface_name, href)); 388 } 389 } catch(URISyntaxException use) { 390 importXSLfile = new File(href); // try 391 } 392 } 393 394 String importXSLfilepath = ""; // for printing the expected file path on error 395 try { 396 // path of import XSL file after resolving any .. and . dir paths 397 importXSLfilepath = importXSLfile.getCanonicalPath(); 398 } catch(IOException ioe) { // resort to using the absolute path 399 importXSLfilepath = importXSLfile.getAbsolutePath(); 400 } 401 402 // 2. now we know where the XSL file being imported lives, so set the systemID to its 403 // absolute path when loading it into a Source object 404 URI systemID = importXSLfile.toURI(); 405 Source importXSLsrc = null; 406 try { 407 importXSLsrc = new StreamSource(new InputStreamReader(new FileInputStream(importXSLfile), "UTF-8")); 408 URL url = systemID.toURL(); 409 importXSLsrc.setSystemId(url.toExternalForm()); 410 } catch (MalformedURLException mue) { 411 logger.error("Warning: Unable to set systemID for imported stylesheet to " + systemID); 412 logger.error("Got exception: " + mue.getMessage(), mue); 413 } catch(FileNotFoundException fne) { 414 logger.error("ERROR: importXSLsrc file does not exist " + importXSLfilepath); 415 logger.error("\tError msg: " + fne.getMessage(), fne); 416 } catch(UnsupportedEncodingException uee) { 417 logger.error("ERROR: could not resolve relative path of import XSL file " + importXSLfilepath 418 + " because of encoding issues: " + uee.getMessage(), uee); 419 } 420 return importXSLsrc; 421 //return new StreamSource(this.getClass().getClassLoader().getResourceAsStream(href)); // won't work 422 } 423 } 266 424 267 425 public Node transform(File stylesheet, File source)
Note:
See TracChangeset
for help on using the changeset viewer.