web-dev-qa-db-ja.com

XSLTファイルをロードする際の相対パスの解決

Apache FOPを使用してXSL変換を行う必要があり、次のようなコードがありました。

_//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ファイルが1つしかない場合でも機能することを確認しましたが、私のプロジェクトでは、いくつかのXSLTファイルに分割し、_<xsl:import />_タグで結合しました。この構成では、XSLTがさまざまなファイルに分散されているため、XSLTに格納されているすべての情報を理解できないため、NullPointerExceptionが発生します。

これらすべてのファイルを_Source xsltSrc_変数にロードして、すべてのXSL情報を利用できるようにする方法があるのだろうか。

[〜#〜]更新[〜#〜]

Mads Hansenの回答に基づいてコードを変更しましたが、それでも機能しません。 XSLT sltファイルをクラスパスに含める必要があるため、ClassLoaderを使用してXSLTファイルをロードします。 url.toExternalForm()を実行するときに、URLに正しいパスがあることを確認しました。これは私の新しいコードです:

_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ファイルへの相対パスを解決しません。

私は何が間違っているのですか?

14
Javi

私はちょうどそれを手に入れました、遅い答え(FOP1.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(したがって、 'imported.xsl'はクラスパスにあるはずです):

<xsl:import href="META-INF/companybusinesscredit/imported.xsl"/>
20
JunLei

XSLTをStreamSourceとしてロードし、SystemIDを設定しない場合、プロセッサはXSLTが「どこ」にあるかを知らず、相対パスを解決できません。

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

StreamSourceへのパラメーターとしてシステムIDを提供することにより、commonFooter.xsltを探す場所を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);
12
Mads Hansen

Saxon 9.xを使用していますが、スタイルシート内でドキュメントを使用すると問題が発生します。スタイルシートは正しく解決されましたが、jarファイルのスタイルシートと一緒にバンドルされたxmlは、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;
    }
}
2
Anand