フィルタを使ってxsltのimport/includeタグのパスを変える
はじめに
antのフィルタを使ってxsltの中でimport/includeするファイルのパスを実行時に変える.具体的にはこんなこと.
<xsl:import href="ここのパスを変える/ファイル名.xsl"/>
importもincludeもやり方は同じなので,以下importのみ記載する.
結論
- antのフィルタを使う.
- import/includeのhrefに記載するパスにフィルタのトークン(@で囲んだ文字列)を書く.
- filterを指定してcopyタスクを実行.
- paramでは上手くいかない.
やってみる
こんなことをやってみる.
- xslファイルを二つ(test.xslとframework.xsl),xmlファイルを一つ(in.xml)を作る.
- 一時フォルダを作成してframework.xslを一時フォルダにコピー.
- test.xslの中でframework.xslをimport.パスは上記2で作った一時フォルダ.
- framework.xslの中でin.xmlの内容を出力.
一時フォルダにコピーしたframework.xslが,正しくtest.xslにimportできれば,in.xmlの内容が出てくるはず.
xslt(test.xsl)の記載(import/includeタクを記載する側)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="@TMP.PATH@/framework.xsl"/>
<!-- importするファイルのあるパスをトークン(@で囲んだ文字列)として記載 -->
<xsl:output method="text"/>
</xsl:stylesheet>
xslt(framework.xsl)の記載(import/includeタクに記載される側)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
in.xmlの記載
<?xml version="1.0" encoding="UTF-8"?>
<root>
this is test.
</root>
build.xmlの記載
こんなことを行う.
- 一時フォルダを作成.
- 一時フォルダにframework.xsl(importされるファイル)をコピー.
- test.xsl(importを記載するファイル)の中のパス名をフィルタで一時フォルダに変える.
- xsltファイルを適用.
<project name="sample" default="run">
<property environment="env"/>
<target name="run">
<!-- 一時フォルダを作成 -->
<tempfile destdir="${env.TMP}" property="tmp.path.windows"/>
<echo message="${tmp.path.windows}"/>
<mkdir dir="${tmp.path.windows}"/>
<!--
cygwinを使っているので,パス区切文字の変換(Windows形式からUNIX形式へ)が必要.
パスの区切文字がWindows形式(バックスラッシュ)だとエラーになるので,UNIX形式(スラッシュ)に変える
-->
<pathconvert property="tmp.path" targetos="unix">
<path>
<pathelement location="${tmp.path.windows}"/>
</path>
</pathconvert>
<echo message="${tmp.path}"/>
<!-- 一時フォルダにframework.xsl(importされるファイル)をコピー -->
<copy file="framework.xsl" tofile="${tmp.path}/framework.xsl"/>
<!-- パス名をフィルタで一時フォルダに変える -->
<copy file="test.xsl" tofile="${tmp.path}/test.xsl">
<filterset>
<filter token="TMP.PATH" value="${tmp.path}"/>
</filterset>
</copy>
<!-- スタイルシートを適用 -->
<xslt style="${tmp.path}/test.xsl" in="in.xml" out="out.txt"/>
</target>
</project>
実行結果
$ ant
Buildfile: C:\Users\foo\Desktop\ant.test\filter\build.xml
run:
[echo] C:\Users\foo\AppData\Local\Temp\null1986596527
[mkdir] Created dir: C:\Users\foo\AppData\Local\Temp\null1986596527
[echo] C:/Users/foo/AppData/Local/Temp/null1986596527
[copy] Copying 1 file to C:\Users\foo\AppData\Local\Temp\null1986596527
[copy] Copying 1 file to C:\Users\foo\AppData\Local\Temp\null1986596527
$ cat out.txt
this is test.
変数は使えないのか
paramタスクを使っても,antからxsltに値を渡せる.これでパスの変換はできないのだろうか.結論から言うとできなかった.import/include実行時には変数に値が入っていないようだ.
xslt(test.param.xsl)
antから引数を受取るためにparamタグを指定する.importはstylesheetタグ直下にないといけないので,paramタグはimportタグの後ろになる.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="$tmp.path/framework.xsl"/> <!-- importはstylesheet直下にないとエラー -->
<xsl:param name="tmp.path"/> <!-- antからの引数を受け取る -->
<xsl:output method="text"/>
</xsl:stylesheet>
build.param.xml
xsltタスクの中でparamタスクを使ってxsltにパスを渡す.
<project name="sample" default="run">
<property environment="env"/>
<target name="run">
<!-- 一時フォルダを作成 -->
<tempfile destdir="${env.TMP}" property="tmp.path.windows"/>
<echo message="${tmp.path.windows}"/>
<mkdir dir="${tmp.path.windows}"/>
<!-- パスの区切り文字を変更 -->
<pathconvert property="tmp.path" targetos="unix">
<path>
<pathelement location="${tmp.path.windows}"/>
</path>
</pathconvert>
<echo message="${tmp.path}"/>
<!-- 一時フォルダにframework.xsl(importされるファイル)をコピー -->
<copy file="framework.xsl" tofile="${tmp.path}/framework.xsl"/>
<!-- スタイルシートを適用.paramでxsltへ値を渡す -->
<xslt style="test.param.xsl" in="in.xml" out="out.param.txt">
<param name="tmp.path" expression="${tmp.path}"/> <!-- xsltへ値を渡す -->
</xslt>
</target>
</project>
実行結果
引数tmp.path
は具体値に変換されず,エラーになる.
$ ant -f build.param.xml
Buildfile: C:\Users\foo\Desktop\ant.test\filter\build.param.xml
run:
[echo] C:\Users\foo\AppData\Local\Temp\null1353224696
[mkdir] Created dir: C:\Users\foo\AppData\Local\Temp\null1353224696
[echo] C:/Users/foo/AppData/Local/Temp/null1353224696
[copy] Copying 1 file to C:\Users\foo\AppData\Local\Temp\null1353224696
[xslt] Processing C:\Users\foo\Desktop\ant.test\filter\in.xml to C:\Users\foo\Desktop\ant.test\filter\out.param.txt
[xslt] Loading stylesheet C:\Users\foo\Desktop\ant.test\filter\test.param.xsl
[xslt] : Error! スタイルシートをコンパイルできませんでした
[xslt] : Fatal Error! C:\Users\foo\Desktop\ant.test\filter\$tmp.path\framework.xsl (指定されたパスが見つかりません。) Cause: java.io.FileNotFoundException: C:\Users\foo\Desktop\ant.test\filter\$tmp.path\framework.xsl (指定されたパスが見つかりません。)
[xslt] Failed to process C:\Users\foo\Desktop\ant.test\filter\in.xml
BUILD FAILED
C:\Users\foo\Desktop\ant.test\filter\build.param.xml:18: Fatal error during transformation using C:\Users\foo\Desktop\ant.test\filter\test.param.xsl: C:\Users\foo\Desktop\ant.test\filter\$tmp.path\framework.xsl (指定されたパスが見つかりません。)
include版
paramがimportよりも後ろにあるからエラーになるのかもしれない.includeで試してみた.
xsl(test.param2.xsl)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="tmp.path"/>
<xsl:include href="$tmp.path/framework.xsl"/> <!-- includeはファイルの途中にあってもOK -->
<xsl:output method="text"/>
</xsl:stylesheet>
build.param2.xml
<project name="sample" default="run">
<property environment="env"/>
<target name="run">
<tempfile destdir="${env.TMP}" property="tmp.path.windows"/>
<echo message="${tmp.path.windows}"/>
<mkdir dir="${tmp.path.windows}"/>
<pathconvert property="tmp.path" targetos="unix">
<path>
<pathelement location="${tmp.path.windows}"/>
</path>
</pathconvert>
<echo message="${tmp.path}"/>
<copy file="framework.xsl" tofile="${tmp.path}/framework.xsl"/>
<xslt style="test.param2.xsl" in="in.xml" out="out.param2.txt">
<param name="tmp.path" expression="${tmp.path}"/>
</xslt>
</target>
</project>
実行結果
import同様,引数tmp.path
は具体値に変換されず,エラーになる.
$ ant -f build.param2.xml
Buildfile: C:\Users\foo\Desktop\ant.test\filter\build.param2.xml
run:
[echo] C:\Users\foo\AppData\Local\Temp\null693261028
[mkdir] Created dir: C:\Users\foo\AppData\Local\Temp\null693261028
[echo] C:/Users/foo/AppData/Local/Temp/null693261028
[copy] Copying 1 file to C:\Users\foo\AppData\Local\Temp\null693261028
[xslt] Processing C:\Users\foo\Desktop\ant.test\filter\in.xml to C:\Users\foo\Desktop\ant.test\filter\out.param2.txt
[xslt] Loading stylesheet C:\Users\foo\Desktop\ant.test\filter\test.param2.xsl
[xslt] : Error! スタイルシートをコンパイルできませんでした
[xslt] : Fatal Error! C:\Users\foo\Desktop\ant.test\filter\$tmp.path\framework.xsl (指定されたパスが見つかりません。) Cause: java.io.FileNotFoundException: C:\Users\foo\Desktop\ant.test\filter\$tmp.path\framework.xsl (指定されたパスが見つかりません。)
[xslt] Failed to process C:\Users\foo\Desktop\ant.test\filter\in.xml
BUILD FAILED
C:\Users\foo\Desktop\ant.test\filter\build.param2.xml:18: Fatal error during transformation using C:\Users\foo\Desktop\ant.test\filter\test.param2.xsl: C:\Users\foo\Desktop\ant.test\filter\$tmp.path\framework.xsl (指定されたパスが見つかりません。)
Total time: 0 seconds
環境
- Windows 10 Pro
- cygwin 2.9.0
- ant 1.10.5
- Saxon-HE 9.9.1.1J
- OpenJDK 12.0.1