Разрешение относительных путей при загрузке файлов XSLT - PullRequest
13 голосов
/ 13 сентября 2010

Мне нужно выполнить XSL-преобразование с использованием Apache FOP, и у меня был такой код:

//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);

, где xslPath - это путь к моему XSLT-файлу.

Я подтвердил, что он работает, когда у меня есть только один XSLT-файл, но в моем проекте я разделил вещи на несколько XSLT-файлов и соединил их с помощью тега <xsl:import />. С этой конфигурацией я получаю исключение NullPointerException, поскольку оно не понимает всю информацию, хранящуюся в XSLT, поскольку оно распространяется по разным файлам.

Интересно, есть ли способ загрузить все эти файлы в переменную Source xsltSrc, чтобы была доступна вся информация XSL.

UPDATE

Я изменил код, основываясь на ответе Мадса Хансена, но он все еще не работает. Я должен включить XSLT slt файлы в classpath, поэтому я загружаю XSLT файл с ClassLoader. Я проверил, что URL имеет правильный путь при выполнении url.toExternalForm(). Это мой новый кусок кода:

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);

Находит и загружает myfile.xslt, но все равно не разрешает относительные пути к другим файлам XSLT.

Что я делаю не так?

Ответы [ 3 ]

20 голосов
/ 17 сентября 2012

Я только что получил, поздний ответ (проверено на FOP 1.0) ------

Все, что вам нужно, это установить URI-резолвер для вашей фабрики, так как у меня работает следующее:

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));
  }
}

и мой импортируемый xsl (поэтому файл import.xsl должен находиться в пути к классам):

<xsl:import href="META-INF/companybusinesscredit/imported.xsl"/>
12 голосов
/ 13 сентября 2010

Когда вы загружаете XSLT как StreamSource и не устанавливаете SystemID , процессор не знает «где» XSLT и не может разрешить относительные пути. *

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

Предоставляя системный идентификатор как Параметр StreamSource, вы говоря процессору XSLT, где ищите commonFooter.xslt. Без этот параметр, вы можете столкнуться с ошибка, когда процессор не может разрешить этот URI. Простое решение заключается в вызвать метод setSystemId () как следующим образом:

// 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);
2 голосов
/ 07 декабря 2012

Я использую Saxon 9.x, но у меня все еще были проблемы при использовании документа в таблице стилей. Таблица стилей была правильно разрешена, но xmls, связанные с таблицей стилей в jar-файле, не загружались должным образом даже с setSystemId. В результате файл не нашел исключение. Мне было проще настроить кодировщик с помощью приведенного ниже кода:

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;
    }
}
...