Подтвердить что ты не робот

Разрешение относительных путей при загрузке 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.

Что я делаю неправильно?

4b9b3361

Ответ 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;
    }
}