- PR -

XSL-FOで作成される帳票ファイルの改行文字の改行方法

投稿者投稿内容
悩むSE
会議室デビュー日: 2006/09/26
投稿数: 9
投稿日時: 2006-09-27 15:39
タイトルを読むと分かりづらいかもしれませんが、
HTML(正確にはXML)上で改行を意図しているものが、
PDF上では空白文字が出力されるという問題です。

↓こんな感じです。
・HTML上の出力領域
柿食えば
鐘が鳴るなり
法隆寺

・出力されるPDF
柿食えば 鐘が鳴るなり 法隆寺

状況
ApacheFOP 0.20.5を使用。
Webアプリの開発中。
値はDBより取得のため可変。

HTML上で改行を意図したものはそのまま改行して欲しいのです。
どうかアドバイスのほどよろしくお願いします。
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2006-09-27 20:39
これのことか?
http://www.antenna.co.jp/XSL-FO/support/qa/QA/2002032506.html
悩むSE
会議室デビュー日: 2006/09/26
投稿数: 9
投稿日時: 2006-09-27 21:04
かずくん様、ご回答ありがとうございます。

「fo:block に linefeed-treatment="preserve" を指定」は試してみましたが、結果はだめでした。
私のXSLファイルではそもそもfo:characterなるタグが存在していないので、
教えていただいたページには該当しないと思います。
ue
ぬし
会議室デビュー日: 2005/05/07
投稿数: 581
お住まい・勤務地: 広島市
投稿日時: 2006-09-27 23:04
こんばんは。

FOPでのLFを改行出力したい の みやもさん と 小僧さん のやりとりが参考になります。

例えば LF を置換するとこんな感じになると思います。

test.xml
コード:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<test>
柿食えば
鐘が鳴るなり
法隆寺
</test>


test.xsl
コード:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template name="InsertLineBreak">
<xsl:param name="value" select="あ"/>
<xsl:choose>
<xsl:when test="contains($value,'&#10;')">
<xsl:value-of select="substring-before($value,'&#10;')"/>
<fo:block white-space-collapse="false">
</fo:block>
<xsl:call-template name="InsertLineBreak">
<xsl:with-param name="value" select="substring-after($value,'&#10;')"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>

<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="ja">
<fo:layout-master-set>
<fo:simple-page-master master-name="test">
<fo:region-body margin-top="1cm"/>
<fo:region-before extent="1cm"/>
<fo:region-after extent="1cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="test">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="12pt" font-family="MS Gothic" hyphenate="true">
<xsl:call-template name="InsertLineBreak">
<xsl:with-param name="value" select=".//text()"></xsl:with-param>
</xsl:call-template>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>



C:\FOP>fop.bat -xml test.xml -xsl test.xsl -pdf test.pdf

手元の FOP 0.20.5 では改行できました。


#test.xls を test.xsl に直しました。Excel じゃなかった(^^;

#意図しない改行を修正。文中の &#10; は & を半角に読み替えてください。
_________________
上本亮介 (ue) @ わんくま同盟
Microsoft MVP for Microsoft Office System - Microsoft Office System
(Jul 2006 - Jun 2007)
Hello Another World!

[ メッセージ編集済み 編集者: ue 編集日時 2006-10-02 12:18 ]

[ メッセージ編集済み 編集者: ue 編集日時 2006-10-02 21:47 ]
悩むSE
会議室デビュー日: 2006/09/26
投稿数: 9
投稿日時: 2006-10-02 10:43
ue様ご回答ありがとうございます。返答が遅れてすみません。
諸事情により業務から離れていたためご回答方針の施行が遅くなってしまいました。
ue様に提示していただいた方法を試したところ、改行は行われませんでした。
その代わり?というのは変ですが、適用した部分の情報がまったく存在しなくなりました。
ブラウザ上では「いろはにほへと」と表示されていても、PDF上は真っ白な状態でした。
下に導入した時のものを載せますのでアドバイスいただけると幸いです。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:xdt="http://www.w3.org/2005/02/xpath-datatypes">
<!-- 追記部分 01 START -->
<xsl:template name="InsertLineBreak">
<xsl:param name="value" select="あ"/>
<xsl:choose>
<xsl:when test="contains($value,'
')">
<xsl:value-of select="substring-before($value,'
')"/>
<fo:block white-space-collapse="false">
</fo:block>
<xsl:call-template name="InsertLineBreak">
<xsl:with-param name="value" select="substring-after($value,'
')"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
<!-- 追記部分 01 END -->
<!-- 中略 -->
<!-- 追記部分 02 START -->
<xsl:call-template name="InsertLineBreak">
<xsl:with-param name="value" select=".//text()">
<!-- 追記部分 02 END -->
<xsl:for-each select="XXXXXX"> <!-- XXXXXXは項目名 -->
<fo:inline font-size="10.0pt" font-family="MS 明朝" font-weight="bold">
<xsl:apply-templates />
</fo:inline>
</xsl:for-each>
<!-- 追記部分 03 START -->
</xsl:with-param>
</xsl:call-template>
<!-- 追記部分 03 END -->

末筆ですが、よろしくお願いします。
ue
ぬし
会議室デビュー日: 2005/05/07
投稿数: 581
お住まい・勤務地: 広島市
投稿日時: 2006-10-02 21:42
こんばんは。ueです。

私の 2006-09-27 23:04 の投稿ですが、LF をあらわした &#10; が本当に改行されて表示されています。

<xsl:when test="contains($value,'
')">

こういった記述は正しくはこうなります。

<xsl:when test="contains($value,'&#10;')">
&は半角に読み替えてください。

失礼しました。

<xsl:for-each> 要素で反復処理をしたいならこんな感じで出来ます。

-----test.xml-----
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<句集>
<句>
柿食えば
鐘が鳴るなり
法隆寺
</句>
<句>
夜更けて
米とぐ音や
きりぎりす
</句>
</句集>


-----test.xsl-----
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template name="InsertLineBreak">
<xsl:param name="value" select="あ"/>
<xsl:choose>
<xsl:when test="contains($value,'&#10;')">
<xsl:value-of select="substring-before($value,'&#10;')"/>
<fo:block white-space-collapse="false"> </fo:block>
<xsl:call-template name="InsertLineBreak">
<xsl:with-param name="value" select="substring-after($value,'&#10;')"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>

<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="ja">
<fo:layout-master-set>
<fo:simple-page-master master-name="test">
<fo:region-body margin-top="1cm"/>
<fo:region-before extent="1cm"/>
<fo:region-after extent="1cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="test">
<fo:flow flow-name="xsl-region-body">
<xsl:for-each select="句集/句">
<fo:block font-size="12pt" font-family="MS Gothic" hyphenate="true">
<xsl:call-template name="InsertLineBreak">
<xsl:with-param name="value" select="text()"></xsl:with-param>
</xsl:call-template>
</fo:block>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>


いかがでしょうか。

_________________
上本亮介 (ue) @ わんくま同盟
Microsoft MVP for Microsoft Office System - Microsoft Office System
(Jul 2006 - Jun 2007)
Hello Another World!

[ メッセージ編集済み 編集者: ue 編集日時 2006-10-02 21:44 ]
悩むSE
会議室デビュー日: 2006/09/26
投稿数: 9
投稿日時: 2006-10-03 10:15
ue様ご回答ありがとうございます。
ue様のご提示方法を施行いたしましたが、結果は思わしくありません。

1:正確にはご提示方法は助けを求める前段階で施行済みでした。
2:そもそも、導入方法が誤っていました。
3:導入方法を変えたら挙動に変化はあったものの、最後の1行は出力されません。

上記のような流れが私の作業状況でございます。現在は3の状態です。

下に現段階のXSLソースを掲載します。
<!-- InsertLineBreak 定義部 -->
<xsl:template name="InsertLineBreak">
<xsl:param name="value" select="あ"/>
<xsl:choose>
<xsl:when test="contains($value,'&#10;')"> <!-- アンドは半角で読み替えて下さい -->
<xsl:value-of select="substring-before($value,'&#10;')"/>
<fo:block white-space-collapse="false">
</fo:block>
<xsl:call-template name="InsertLineBreak">
<xsl:with-param name="value" select="substring-after($value,'&#10;')"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
<!-- InsertLineBreak 定義部 -->

<!-- InsertLineBreak 使用部 -->
<fo:block hyphenate="true">
<xsl:for-each select="XXXXXX"> <!-- XXXXXXは実際の項目名とは異なります -->
<fo:inline font-size="10.0pt" font-family="MS 明朝" font-weight="bold">
<xsl:call-template name="InsertLineBreak">
<xsl:with-param name="value" select="text()">
<xsl:apply-templates />
</xsl:with-param>
</xsl:call-template>
</fo:inline>
</xsl:for-each>
</fo:block>
<!-- InsertLineBreak 使用部 -->

幾度となく申し訳ない限りですが、アドバイスのほどよろしくお願いします。
ue
ぬし
会議室デビュー日: 2005/05/07
投稿数: 581
お住まい・勤務地: 広島市
投稿日時: 2006-10-03 20:06
こんばんは。

引用:

悩むSEさんの書き込み (2006-10-03 10:15) より:

3:導入方法を変えたら挙動に変化はあったものの、最後の1行は出力されません。


例えばソースの XML ファイルが下のようになっているとき「きりぎりす」が表示されないということでしょうか。

-----test.xml-----
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<句集>
<句>
柿食えば
鐘が鳴るなり
法隆寺
</句>
<句>
夜更けて
米とぐ音や
きりぎりす</句> <!-- 下五の直後に LF が入らない -->
</句集>


そうであれば、これはコードで定義した通りの挙動なので正常です。

ソース XML で下五の直後に改行が入らない、つまり下五の直後でタグが閉じることを保証できるなら、例えば以下のように XSL を変更すれば出力されます。

-----test.xml-----
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<句集>
<句>柿食えば
鐘が鳴るなり
法隆寺</句>
<句>夜更けて
米とぐ音や
きりぎりす</句>
</句集>


-----test.xsl-----
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template name="InsertLineBreak">
<xsl:param name="value" select="あ"/>
<xsl:choose>
<xsl:when test="contains($value,'&#10;')">
<xsl:value-of select="substring-before($value,'&#10;')"/>
<fo:block white-space-collapse="false" />
<xsl:call-template name="InsertLineBreak">
<xsl:with-param name="value" select="substring-after($value,'&#10;')"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="ja">
<fo:layout-master-set>
<fo:simple-page-master master-name="test">
<fo:region-body margin-top="1cm"/>
<fo:region-before extent="1cm"/>
<fo:region-after extent="1cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="test">
<fo:flow flow-name="xsl-region-body">
<xsl:for-each select="句集/句">
<fo:block font-size="12pt" font-family="MS Gothic" hyphenate="true">
<xsl:call-template name="InsertLineBreak">
<!-- concat 関数で末尾に改行コードを付けておく -->
<xsl:with-param name="value" select="concat(text(),'&#10;')"/>
</xsl:call-template>
</fo:block>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>


その場しのぎでスマートな方法ではありませんが、concat 関数を使って各俳句の末尾に LF を付ける処理を加えました。

いかがでしょうか。
_________________
上本亮介 (ue) @ わんくま同盟
Microsoft MVP for VSTO (Jul 2008 - Jun 2009)
Hello Another World!
.NET 勉強会 / ヒーロー島

スキルアップ/キャリアアップ(JOB@IT)