2010-09-13 17 views
11

muszę zrobić transformację XSL przy użyciu Apache FOP i miałem kodu:Rozwiązywanie ścieżek względnych podczas ładowania plików XSLT

//Setup FOP 
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out); 
//Setup Transformer 
Source xsltSrc = new StreamSource(new File(xslPath)); 
Transformer transformer = tFactory.newTransformer(xsltSrc); 

//Make sure the XSL transformation's result is piped through to FOP 
Result res = new SAXResult(fop.getDefaultHandler()); 
//Setup input 
Source src = new StreamSource(new File(xmlPath)); 
//Start the transformation and rendering process 
transformer.transform(src, res); 

gdzie xslPath jest ścieżka gdzie przechowywany jest mój plik XSLT.

Potwierdziłem, że działa, gdy mam tylko jeden plik XSLT, ale w moim projekcie podzieliłem rzeczy na kilka plików XSLT i dołączyłem je do znacznika <xsl:import />. Dzięki tej konfiguracji otrzymuję wyjątek NullPointerException, ponieważ nie rozumie on wszystkich informacji przechowywanych w XSLT, ponieważ jest on rozprowadzany w różnych plikach.

Zastanawiam się, czy istnieje sposób, aby załadować wszystkie te pliki w zmiennej Source xsltSrc, aby wszystkie informacje XSL były dostępne.

UPDATE

Zmieniłem kod w oparciu o odpowiedzi udzielonej przez Mads Hansen, ale nadal nie działa. Muszę uwzględnić pliki slt XSLT w ścieżce klas, więc wczytam plik XSLT z ClassLoader. Sprawdziłem, czy adres URL ma poprawną ścieżkę podczas wykonywania url.toExternalForm(). To jest mój nowy kawałek kodu:

ClassLoader cl = this.getClass().getClassLoader(); 
String systemID = "resources/xslt/myfile.xslt"; 
InputStream in = cl.getResourceAsStream(systemID); 
URL url = cl.getResource(systemID); 
Source source = new StreamSource(in); 
source.setSystemId(url.toExternalForm()); 
transformer = tFactory.newTransformer(source); 

Okazuje i ładuje myfile.xslt ale to nadal nie rozwiązuje względnych ścieżek do innych plików XSLT.

Co robię źle?

Odpowiedz

10

Podczas ładowania XSLT jako StreamSource i nie ustawić SystemID, procesor nie wie „gdzie” XSLT jest i nie może rozwiązać ścieżek względnych.

http://www.onjava.com/pub/a/onjava/excerpt/java_xslt_ch5/index.html?page=5

Dostarczając identyfikator systemu jako parametr do StreamSource , jesteś mówiąc procesor XSLT gdzie szukać commonFooter.xslt. Bez tego parametru może wystąpić błąd , gdy procesor nie może rozwiązać tego identyfikatora URI. Prostym rozwiązaniem jest Wywołać setSystemId() metoda jak następująco:

// construct a Source that reads from an InputStream 
Source mySrc = new StreamSource(anInputStream); 
// specify a system ID (a String) so the 
// Source can resolve relative URLs 
// that are encountered in XSLT stylesheets 
mySrc.setSystemId(aSystemId); 
+0

dziękuję za odpowiedź, ale nie rozwiązuje ona mojego problemu, chociaż twoja odpowiedź ma sens. Zaktualizowałem moje pytanie, wprowadzając zmiany w kodzie. – Javi

+0

Być może konieczne będzie uzyskanie bezwzględnej ścieżki dla identyfikatora systemowego. Chyba, że ​​wiesz, gdzie rozwiąże względną ścieżkę "od". Spróbuj przekonwertować tę względną ścieżkę do bezwzględnej ścieżki za pomocą czegoś takiego: 'String xsltSystemId = new File (systemID) .toURL(). ToExternalForm();' lub 'String xsltSystemId = new Plik (relativePath) .getAbsolutePath();' –

+0

thanks , Już to zrobiłem i sprawdziłem, że kiedy robię url.toExternalForm(), otrzymuje on absolutną ścieżkę. Ale nie wiem, gdzie teraz jest problem. – Javi

17

Właśnie go późno odpowiedź (testowane na FOP 1.0) ------

Wszystko Wystarczy ustawić uri rozpoznawania nazw dla swojej fabryki, jak dla mnie następujące prace:

TransformerFactory transFact = TransformerFactory.newInstance(); 
StreamSource xsltSource = new StreamSource(xsl); 

// XXX for 'xsl:import' to load other xsls from class path 
transFact.setURIResolver(new ClasspathResourceURIResolver()); 
Templates cachedXSLT = transFact.newTemplates(xsltSource); 
Transformer transformer = cachedXSLT.newTransformer(); 


class ClasspathResourceURIResolver implements URIResolver { 
    @Override 
    public Source resolve(String href, String base) throws TransformerException { 
    return new StreamSource(XXX.getClassLoader().getResourceAsStream(href)); 
    } 
} 

i mój importowania xsl (tak „imported.xsl” powinien znajdować się w ścieżce klasy):

<xsl:import href="META-INF/companybusinesscredit/imported.xsl"/> 
+0

Dziękuję bardzo, to zaoszczędziło mi godzin. –

2

Używam Saxon 9.x i nadal miałem problemy, gdy użyłem dokumentu w arkuszu stylów. Arkusz stylów został poprawnie rozwiązany, ale xmls dołączony wraz z arkuszem stylów w pliku jar nie załadował się zgodnie z oczekiwaniami, nawet w przypadku setSystemId. Powodowało to wyjątek dotyczący pliku.Łatwiej mi było napisać kod resolver z kodem poniżej:

JarfileResolver jarfileResolver = new JarfileResolver(); 
transformer.setURIResolver(jarfileResolver); 


public class JarfileResolver implements URIResolver 
{ 
    public Source resolve(String fileName, String base) throws TransformerException 
    { 
     URL url = getClass().getClassLoader().getResource(fileName); 
     StreamSource jarFileSS = new StreamSource(); 

     try 
     { 
      InputStream jarfileIS = url.openStream(); 
      jarFileSS.setInputStream(jarfileIS); 
     } 
     catch(IOException ioExp) 
     { 
      throw new TransformerException(ioExp); 
     } 
     return jarFileSS; 
    } 
} 
Powiązane problemy