Разрешение относительных путей при загрузке XSLT файлов
Мне нужно преобразовать 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 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
Я изменил код, основанный на ответе, данном Mads Hansen, но он все еще не работает. Я должен включить файлы slt XSLT в путь к классам, поэтому я загружаю 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.
Что я делаю неправильно?
Ответы
Ответ 1
Я только что получил его, поздний ответ (проверенный на FOP 1.0) ------
Все, что вам нужно, это установить для вашего factory распознаватель 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"/>
Ответ 2
Когда вы загружаете XSLT как StreamSource и не устанавливаете SystemID, процессор не знает "where" 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);
Ответ 3
Я использую 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;
}
}