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ファイルへの相対パスを解決しません。
私は何が間違っているのですか?
私はちょうどそれを手に入れました、遅い答え(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"/>
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);
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;
}
}