2013年5月19日日曜日

[FOP]FO 作成のパラメータ指定

次の xml ファイルに対して fo 作成用の xsl を操作して出力結果の違いを見てみる。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<article>
  <sect1>
    <title>Hello World</title>
    <para>Hello World</para>
  </sect1>
  <sect1>
    <title>日本語テスト</title>
    <para>日本語が正しく表示されますか?</para>
  </sect1>
  <sect1>
    <title>hoge</title>
    <para>hello</para>
    <sect2>
      <title>hoge2</title>
      <para>hogehoge</para>
    </sect2>
  </sect1>
</article>


標準
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
  <xsl:import href="../docbook-xsl-1.75.0/fo/docbook.xsl"/>
  <xsl:output method="fo" encoding="UTF-8" indent="yes"/>

  <xsl:param name="section.autolabel" select="1"/>
  <xsl:param name="default.encoding" select="'UTF-8'"/>

  <xsl:param name="paper.type" select="'A4'"/>

  <xsl:param name="title.font.family" select="'Meiryo'"/>
  <xsl:param name="body.font.family" select="'Meiryo'"/>
  <xsl:param name="sans.font.family" select="'Meiryo'"/>
  <xsl:param name="monospace.font.family" select="'Meiryo'"/>
</xsl:stylesheet>


文章全体の上下 margin を調整
次の指定を xsl に追加
<xsl:param name="page.margin.top">10mm</xsl:param>
<xsl:param name="page.margin.bottom">10mm</xsl:param>


本文上下の margin を調整
次の指定を xsl に追加
<xsl:param name="body.margin.top">0mm</xsl:param>
<xsl:param name="body.margin.bottom">0mm</xsl:param>


本文左右の margin を調整
次の指定を xsl に追加
<xsl:param name="page.margin.inner">0mm</xsl:param>
<xsl:param name="page.margin.outer">0mm</xsl:param>


段落の開始位置 左 margin を調整
次の指定を xsl に追加
<xsl:param name="body.start.indent">0pt</xsl:param>


Table of Contents, List of Figures なし
次の指定を xsl に追加
<xsl:param name="generate.toc">
 article nop
</xsl:param>


Header に draft を入れる, Background に draft 画像を貼る
次の指定を xsl に追加
<xsl:param name="draft.mode">yes</xsl:param>
<xsl:param name="draft.watermark.image">file:///c:\usr\share\sgml\docbook-xsl-1.75.0\images\draft.png</xsl:param>
draft.watermark.image を指定しないと HTTP 通信をして draft.png ファイルを取得しようとするので, ネットワークがつながっていない・Proxy が設定されていない等でエラーとなった場合に下記の表示が出る
[fop] 致命的: Error with opening URL 'http://docbook.sourceforge.net/release/images/draft.png': Connection timed out: connect


Header, Footer に罫線なし
次の指定を xsl に追加
<xsl:param name="header.rule" select="0"></xsl:param>
<xsl:param name="footer.rule" select="0"></xsl:param>


ページ定義
<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
 <fo:layout-master-set>
  <fo:simple-page-master master-name="simple"
                         page-height="297mm"
                         page-width="210mm"
                         margin-top="10mm"
                         margin-bottom="20mm"
                         margin-left="25mm"
                         margin-right="25mm">
   <fo:region-body margin-top="30mm"/>
   <fo:region-before extent="30mm"/>
   <fo:region-after extent="15mm"/>
  </fo:simple-page-master>
 </fo:layout-master-set>

 <fo:page-sequence master-reference="simple">
  <fo:flow flow-name="xsl-region-body">
   <fo:block font-size="18pt" padding-top="3pt" padding-bottom="10pt">
    TITLE
   </fo:block>
   <fo:block font-size="12pt" font-family="sans-serif">
    hogehoge
   </fo:block>
   <fo:block font-size="14pt" font-family="IPA Mincho">
    ほげほげ
   </fo:block>
  </fo:flow>
 </fo:page-sequence>
</fo:root>
  • ページの定義は以下の部分
    page-height="297mm"
    page-width="210mm"
    margin-top="10mm"
    margin-bottom="20mm"
    margin-left="25mm"
    margin-right="25mm"
    長さ 297mm x 幅 210mm は A4 サイズの用紙
  • 文章本体は以下の部分で定義
    <fo:region-body margin-top="30mm"/>
  • ヘッダ部分
    <fo:region-before extent="30mm"/>
  • フッター部分
    <fo:region-after extent="15mm"/>
  • 以下の箇所が文章本体。master-reference では先に定義していたページ情報を指定する。
    <fo:page-sequence master-reference="simple">
            :
    </fo:page-sequence>
  • 以下の箇所でbody 部分に記載する内容を定義する。body 部分であることは xsl-region-body で指定している。
    <fo:flow flow-name="xsl-region-body">
          :
    </fo:flow>


region
<?xml version="1.0" encoding="UTF-8"?>

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xml:lang="ja">
 <fo:layout-master-set>
  <fo:simple-page-master page-height="148mm"
                         page-width="105mm"
                         margin-top="10mm"
                         margin-left="20mm"
                         margin-right="20mm"
                         margin-bottom="10mm"
                         master-name="PageMaster">
   <fo:region-body   background-color="#cccccc"
                     margin-top="20mm"
                     margin-left="20mm"
                     margin-right="20mm"
                     margin-bottom="20mm"/>
   <fo:region-before background-color="#00ffff"  extent="15mm"/>
   <fo:region-after  background-color="#00ffff"  extent="15mm"/>
   <fo:region-start  background-color="#ffffcc" extent="15mm"/>
   <fo:region-end    background-color="#ffffcc" extent="15mm"/>
  </fo:simple-page-master>
 </fo:layout-master-set>

 <fo:page-sequence initial-page-number="1" master-reference="PageMaster">
  <fo:static-content flow-name="xsl-region-start">
   <fo:block>region-start</fo:block>
  </fo:static-content>
  <fo:static-content flow-name="xsl-region-end">
   <fo:block>region-end</fo:block>
  </fo:static-content>
  <fo:static-content flow-name="xsl-region-before">
   <fo:block>region-before</fo:block>
  </fo:static-content>
  <fo:static-content flow-name="xsl-region-after">
   <fo:block>region-after</fo:block>
  </fo:static-content>

  <fo:flow flow-name="xsl-region-body">
   <fo:block>region-body</fo:block>
  </fo:flow>
 </fo:page-sequence>
</fo:root>
文章位置調整のパラメータは下表・下図のようになっている

Table: region
simple-page-mastermargin-top(1)
margin-left(2)
margin-right(3)
margin-bottom(4)
region-bodymargin-top(5)
margin-left(6)
margin-right(7)
margin-bottom(8)
region-beforeextent(9)
region-startextent(10)
region-endextent(11)
region-afterextent(12)

[FOP]生成した fo ファイルから PDF を生成する

fo ファイル生成で sample_fo.xml というファイルが生成されたので、fop に渡して PDF を生成する。
C:\home\docbook\sample>..\fop-0.95\fop.bat -c ..\fop-0.95\conf\fop.xconf sample.fo sample.pdf
pdf を生成できるように build.xml に追記
Example: build.xml
<taskdef name="fop" classname="org.apache.fop.tools.anttasks.Fop">
  <classpath>
    <pathelement location="../fop-0.95/build/fop.jar"/>
    <fileset dir="../fop-0.95/lib">
      <include name="*.jar"/>
    </fileset>
  </classpath>
</taskdef>

<target name="pdf">
  <xslt basedir="${basedir}"
        destdir="${basedir}"
        style="sample_fo.xsl"
        extension=".fo"
        includes="sample.xml">
    <classpath>
      <pathelement location="${LIBDIR}/xalan.jar"/>
    </classpath>
    <xmlcatalog>
      <dtd publicId="${DOCBOOK_PUBLIC_ID}"
           location="${DOCBOOK_DTD}"/>
    </xmlcatalog>
  </xslt>
  <fop format="application/pdf"
       basedir="${basedir}"
       outdir="${basedir}"
       userconfig="../fop-0.95/conf/fop.xconf"
       messagelevel="debug">
    <fileset dir="${basedir}">
      <include name="*.fo"/>
    </fileset>
  </fop>
</target>
Ant を実行して fo ファイルを生成する
> ant pdf

[FOP]DocBook から PDF を生成する

DocBook から PDF に出力するには以下の手順を踏む
  1. DocBook の XML から fo ファイルを生成する
  2. Apache FOP を使って fo から PDF を生成する


DocBook → fo
Example: 原稿 (sample.xml)
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
  "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" >

<article>
  <title>DocBook sample</title>
  <articleinfo>
    <author>
      <firstname>Hoge</firstname>
      <surname>Fuga</surname>
    </author>

    <copyright>
      <year>2009</year>
    </copyright>
  </articleinfo>

  <sect1><title>Hello World</title><para>Hello World</para></sect1>
  <sect1>
    <title>日本語テスト</title>
    <para>日本語が正しく表示されますか?</para>
  </sect1>
  <sect1>
    <title>hoge</title>
    <para>hello</para>
    <sect2>
      <title>hoge2</title>
      <para>hogehoge</para>
    </sect2>
  </sect1>
</article>
Example: fo を生成するための xsl ファイル (sample_fo.xsl)
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version='1.0'>
  <xsl:import href="../docbook-xsl-1.75.0/fo/docbook.xsl"/>
  <xsl:output method="fo" encoding="UTF-8" indent="yes"/>

  <xsl:param name="section.autolabel" select="1"/>
  <xsl:param name="default.encoding" select="'UTF-8'"/>
  <xsl:param name="paper.type" select="'A4'"/>
  <xsl:param name="draft.mode" select="'no'"/>
  <xsl:param name="hyphenate">false</xsl:param>
  <xsl:param name="callout.graphics.extension" select="'.gif'"/>
  <xsl:param name="title.font.family" select="'Meiryo'"/>
  <xsl:param name="body.font.family" select="'Meiryo'"/>
  <xsl:param name="sans.font.family" select="'Meiryo'"/>
  <xsl:param name="monospace.font.family" select="'Meiryo'"/>
</xsl:stylesheet>
fo を生成するためのルールを build.xml に記述
Example: build.xml
<project name="docbooktest" basedir="." default="xslt">
  <property name="DOCBOOK_DTD" value="../docbook-xml-4.5/docbookx.dtd"/>
  <property name="DOCBOOK_PUBLIC_ID" value="-//OASIS//DTD DocBook XML V4.5//EN"/>
  <property name="LIBDIR" value="../xalan-j_2_7_1/build"/>

  <target name="fo">
    <xslt basedir="${basedir}"
          destdir="${basedir}"
          style="sample_fo.xsl"
          extension=".fo"
          includes="sample.xml">
      <classpath>
        <pathelement location="${LIBDIR}/xalan.jar"/>
      </classpath>
      <xmlcatalog>
        <dtd publicId="${DOCBOOK_PUBLIC_ID}"
             location="${DOCBOOK_DTD}"/>
      </xmlcatalog>
    </xslt>
  </target>
</project>
Ant を実行して fo ファイルを生成する
> ant fo

[FOP]region-body margin

XSL ファイルの fo:region-body margin の値を変更してみる
<fo:simple-page-master master-name="A4">
  <fo:region-body margin="0cm"/>
</fo:simple-page-master>
左が margin="2cm" の場合、右が margin="0cm" の場合

[FOP]日本語対応

fop.jar 内にある org.apache.fop.fonts.apps.TTFReader を実行すると下記のように org.apache.commons.logging.LogFactory クラスが見つからないとエラーが出る
> java -cp c:\usr\share\java\build\fop.jar org.apache.fop.fonts.apps.TTFReader
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
この場合は java\lib 内に commons-logging-1.0.4.jar があるのでクラスに指定して実行する。
> java -cp c:\usr\share\java\build\fop.jar;c:\usr\share\java\lib\commons-logging-1.0.4.jar org.apache.fop.fonts.apps.TTFReader
TTF Reader for Apache FOP 1.0

java org.apache.fop.fonts.apps.TTFReader [options] fontfile.ttf xmlfile.xml

where options can be:
-d  Debug mode
-q  Quiet mode
-enc ansi
    With this option you create a WinAnsi encoded font.
    The default is to create a CID keyed font.
    If you're not going to use characters outside the
    pdfencoding range (almost the same as iso-8889-1)
    you can add this option.
-ttcname <fontname>
    If you're reading data from a TrueType Collection
    (.ttc file) you must specify which font from the
    collection you will read metrics from. If you read
    from a .ttc file without this option, the fontnames
    will be listed for you.
 -fn <fontname>
    default is to use the fontname in the .ttf file, but
    you can override that name to make sure that the
    embedded font is used (if you're embedding fonts)
    instead of installed fonts when viewing documents
    with Acrobat Reader.
commons.logging も指定してメイリオフォントを読み込ませるようにすると、次は org.apache.commons.io.IOUtils クラスが見つからないとエラーが出る
> java -cp c:\usr\share\java\build\fop.jar;c:\usr\share\java\lib\commons-logging-1.0.4.jar org.apache.fop.fonts.apps.TTFReader c:\WINDOWS\Fonts\meiryo.ttc meiryo.xml
TTF Reader for Apache FOP 1.0

Parsing font...
Reading c:\WINDOWS\Fonts\meiryo.ttc...
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/io/IOUtils
この場合は java\lib 内に commons-io-1.3.1.jar があるのでクラスに指定して実行する。
commons.io も指定すると TTFReader が動作するようになる。ここでは ttcname オプションを指定していないのでエラーが発生しているが、meiryo.ttc ファイルに含まれるフォント名が "Meiryo", "Meiryo Italic" の 2 つであることが分かる。
> java -cp c:\usr\share\java\build\fop.jar;c:\usr\share\java\lib\commons-logging-1.0.4.jar;c:\usr\share\java\lib\commons-io-1.3.1.jar org.apache.fop.fonts.apps.TTFReader c:\WINDOWS\Fonts\meiryo.ttc meiryo.xml
TTF Reader for Apache FOP 1.0

Parsing font...
Reading c:\WINDOWS\Fonts\meiryo.ttc...
This is a TrueType collection file with 2 fonts
Containing the following fonts:
Meiryo
Meiryo Italic
Error while building XML font metrics file.
java.lang.IllegalArgumentException: For TrueType collection you must specify which font to select (-ttcname)
ttcname オプションで "Meiryo" を選択すると org.apache.xmlgraphics.fonts.Gryphs クラスが見つからないとエラーが出る
> java -cp c:\usr\share\java\build\fop.jar;c:\usr\share\java\lib\commons-logging-1.0.4.jar;c:\usr\share\java\lib\commons-io-1.3.1.jar org.apache.fop.fonts.apps.TTFReader -ttcname "Meiryo" c:\WINDOWS\Fonts\meiryo.ttc meiryo.xml
TTF Reader for Apache FOP 1.0

Parsing font...
Reading c:\WINDOWS\Fonts\meiryo.ttc...
This is a TrueType collection file with 2 fonts
Containing the following fonts:
Meiryo <-- selected
Meiryo Italic
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/xmlgraphics/fonts/Glyphs
この場合は java\lib 内に xmlgraphics-commons-1.3.1.jar があるのでクラスに指定して実行する
これで meriyo.ttc から meiryo.xml が生成できた
> java -cp c:\usr\share\java\build\fop.jar;c:\usr\share\java\lib\commons-logging-1.0.4.jar;c:\usr\share\java\lib\commons-io-1.3.1.jar;c:\usr\share\java\lib\xmlgraphics-commons-1.3.1.jar org.apache.fop.fonts.apps.TTFReader -ttcname "Meiryo" c:\WINDOWS\Fonts\meiryo.ttc meiryo.xml
TTF Reader for Apache FOP 1.0

Parsing font...
Reading c:\WINDOWS\Fonts\meiryo.ttc...
This is a TrueType collection file with 2 fonts
Containing the following fonts:
Meiryo <-- selected
Meiryo Italic
Font Family: [メイリオ, Meiryo]
Creating xml font file...
Creating CID encoded metrics...
Writing xml font file meiryo.xml...
This font contains no embedding license restrictions.

XML font metrics file successfully created.
Apache FOP を展開したディレクトリ以下の conf ディレクトリにある fop.xconf ファイルを開いてメイリオフォントの情報を追加する。<render mime="application/pdf"> 要素内の <fonts> 以下に使用するフォントを登録する。
<font metrics-url="file:///c:/usr/share/java/conf/meiryo.xml" kerning="yes" embed-url="file:///C:/WINDOWS/Fonts/meiryo.ttc">
  <font-triplet name="Meiryo" style="normal" weight="normal"/>
  <font-triplet name="Meiryo" style="normal" weight="bold"/>
</font>
上で生成した meiryo.xml も conf ディレクトリに置く
PDF 化するデータ (hello.fo) を準備
Example: hello.fo
<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <fo:layout-master-set>
      <fo:simple-page-master master-name="simple">
         <fo:region-body margin-top="3cm"/>
         <fo:region-before extent="3cm"/>
         <fo:region-after extent="3cm"/>
      </fo:simple-page-master>
   </fo:layout-master-set>

   <fo:page-sequence master-reference="simple">
      <fo:flow flow-name="xsl-region-body">
         <fo:block font-family="Meiryo" font-weight="normal" font-style="normal" font-size="18pt" text-align="center">
            こんにちは
         </fo:block>
      </fo:flow>
   </fo:page-sequence>
</fo:root>
PDF に変換する
c オプションで使用する conf ファイルを指定し、上記の hello.fo を PDF に変換する
>..\fop-0.95\fop.bat -c ..\fop-0.95\conf\fop.xconf hello.fo hello.pdf
2009/05/19 11:24:57 org.apache.fop.apps.FopFactoryConfigurator configure
情報: Default page-height set to: 11in
2009/05/19 11:24:57 org.apache.fop.apps.FopFactoryConfigurator configure
情報: Default page-width set to: 8.26in
2009/05/19 11:24:58 org.apache.fop.fonts.truetype.TTFFile checkTTC
情報: This is a TrueType collection file with 2 fonts
2009/05/19 11:24:58 org.apache.fop.fonts.truetype.TTFFile checkTTC
情報: Containing the following fonts:
2009/05/19 11:24:58 org.apache.fop.fonts.truetype.TTFFile checkTTC
情報: Meiryo <-- selected
2009/05/19 11:24:58 org.apache.fop.fonts.truetype.TTFFile checkTTC
情報: Meiryo Italic
生成した PDF ファイルで正しく日本語が表示されていれば成功

XSL でフォントを指定する場合
Example: pdf_jp.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:output encoding="utf-8" indent="yes"/>
    <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="A4">
                    <fo:region-body margin="2cm"/>
                </fo:simple-page-master>
            </fo:layout-master-set>

            <xsl:apply-templates/>
        </fo:root>
    </xsl:template>

    <xsl:template match="/article">
        <fo:page-sequence master-reference="A4">
            <fo:flow flow-name="xsl-region-body">
                <xsl:apply-templates select="./info/title"/>
                <xsl:apply-templates select=".//para"/>
            </fo:flow>
         </fo:page-sequence>
    </xsl:template>

    <xsl:template match="//info/title">
        <fo:block font-family="Meiryo" font-weight="normal" font-style="normal" font-size="20pt"><xsl:apply-templates/></fo:block>
    </xsl:template>

    <xsl:template match="//para">
        <fo:block font-family="Meiryo" font-weight="normal" font-style="normal" font-size="10.5pt"><xsl:apply-templates/></fo:block>
    </xsl:template>
</xsl:stylesheet>
info - title, para 要素に対して font-family=Meiryo, font-weight=normal, font-style=normal を指定している
原稿となる XML ファイル (sample_pdf_jp.xml)
Example: sample_pdf_jp.xml
<?xml version="1.0" encoding="UTF-8"?>
<article version="5.0">
  <info>
    <title>Sample</title>
  </info>

  <para>Hello World</para>
  <para>こんにちは</para>
</article>
fop を使用して PDF 出力する
> c:\usr\share\java\fop.bat -c c:\usr\share\java\conf\fop.xconf -xml sample_pdf_jp.xml -xsl pdf_jp.xsl sample_jp.pdf
2011/04/13 13:53:14 org.apache.fop.apps.FopFactoryConfigurator configure
情報: Default page-height set to: 11in
2011/04/13 13:53:14 org.apache.fop.apps.FopFactoryConfigurator configure
情報: Default page-width set to: 8.26in
2011/04/13 13:53:15 org.apache.fop.fonts.truetype.TTFFile checkTTC
情報: This is a TrueType collection file with 2 fonts
2011/04/13 13:53:15 org.apache.fop.fonts.truetype.TTFFile checkTTC
情報: Containing the following fonts:
2011/04/13 13:53:15 org.apache.fop.fonts.truetype.TTFFile checkTTC
情報: Meiryo <-- selected
2011/04/13 13:53:15 org.apache.fop.fonts.truetype.TTFFile checkTTC
情報: Meiryo Italic
参考: Apache FOPでPDF
参考: Apache FOP: Fonts

[FOP]動作確認

pdf 化する XML ファイルを作成
Example: hello.xml
<?xml version="1.0" encoding="UTF-8"?>
<article version="5.0">
  <info>
    <title>Sample</title>
  </info>

  <para>Hello World</para>
</article>
XSL ファイルを作成
Example: pdf.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:output encoding="utf-8" indent="yes"/>
    <xsl:template match="/">
       <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
            <fo:layout-master-set>
                <fo:simple-page-master master-name="A4">
                    <fo:region-body margin="2cm"/>
                </fo:simple-page-master>
            </fo:layout-master-set>

            <xsl:apply-templates/>
        </fo:root>
    </xsl:template>

    <xsl:template match="/article">
        <fo:page-sequence master-reference="A4">
            <fo:flow flow-name="xsl-region-body">
                <xsl:apply-templates select="./info/title"/>
                <xsl:apply-templates select=".//para"/>
            </fo:flow>
         </fo:page-sequence>
    </xsl:template>

    <xsl:template match="//info/title">
        <fo:block font-size="20pt"><xsl:apply-templates/></fo:block>
    </xsl:template>

    <xsl:template match="//para">
        <fo:block font-size="10.5pt"><xsl:apply-templates/></fo:block>
    </xsl:template>
</xsl:stylesheet>
Table: FOP コマンドのオプション
引数意味
-fo infilexsl:fo input file
-xml infilexml input file, -xsl と一緒に使用すること
-xsl stylesheetxslt stylesheet
-awt出力結果をディスプレイに表示
-pdf outfilePDF ファイルを生成
-foout outfileXSL-FO ファイルを生成する
参考: DocBookで文系論文を書いてみる 1日目

PDF に変換する
>..\fop-0.95\fop.bat -xsl pdf.xsl -xml sample_pdf.xml -pdf sample.pdf


XML, XSL から FO ファイルを生成
>..\fop-0.95\fop.bat -xsl pdf.xsl -xml sample_pdf.xml -pdf -foout sample.fo
生成された FO ファイル
<?xml version="1.0" encoding="utf-8"?><fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="A4">
<fo:region-body margin="2cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="10.5pt">Hello World</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>

[FOP]インストール

Apache FOP を入れて XML → PDF が生成できる環境を整える
  1. Apache FOP: Downloading A Distribution からバイナリをダウンロードする
  2. ダウンロードしたファイルを解凍する


LinuxMint12 へのインストール
  1. Menu -> その他 -> ソフトウェアの管理
  2. 右上の検索窓に fop と入力
  3. fop を選択
  4. [インストール] ボタンを押す

[CakePHP][pChart]pChart を使用してグラフを描く

pChart を利用して棒グラフとレーダーチャートを描く。
Example: views の exam_all.ctp
<body>
<table>
  <tr>
    <th>Name</th>
    <th>Math</th>
    <th>English</th>
    <th>Physics</th>
  </tr>
  <?php
 foreach ($users as $user) {
  echo "<tr>\n";
  echo "<td>" . $user['User']['username'] . "</td>\n";
  echo "<td>" . $user['Exam']['math'] . "</td>\n";
  echo "<td>" . $user['Exam']['english'] . "</td>\n";
  echo "<td>" . $user['Exam']['physics'] . "</td>\n";
  echo "</tr>\n";
 }
  ?>
</table>
<img src="exam_all_graph" />
<img src="exam_all_radar" />
</body>
Example: exams_controller.php
function exam_all() {
 $users = $this->User->find('all');

 $this->set('users', $users);
 Cache::write('users', $users);
}

function exam_all_graph() {
 /* pChart を使用する */
 App::import('Vendor', 'pchart/pdata');
 App::import('Vendor', 'pchart/pchart');

 $font_path = "c:\Windows\Fonts\sazanami-gothic.ttf";

 /* Cache に保存された値を読み込む */
 $users = Cache::read('users');
 if ($users == false) {
  /* DB から値を取得 */
  $users = $this->User->find('all');
 }
 else {
  /* exam_all_radar() でも使用するので cache を削除しない */
 }

 $mathScore = array();
 $englishScore = array();
 $physicsScore = array();
 $name = array();

 foreach ($users as $user) {
  array_push($mathScore, $user['Exam']['math']);
  array_push($englishScore, $user['Exam']['english']);
  array_push($physicsScore, $user['Exam']['physics']);
  array_push($name, $user['User']['username']);
 }

 $data = new pData;
 $data->AddPoint($mathScore, "math");
 $data->AddPoint($englishScore, "english");
 $data->AddPoint($physicsScore, "physics");
 $data->AddPoint($name, "name");
 $data->AddSerie("math");
 $data->AddSerie("english");
 $data->AddSerie("physics");
 $data->SetAbsciseLabelSerie("name");
 $data->SetSerieName("数学", "math");
 $data->SetSerieName("英語", "english");
 $data->SetSerieName("物理", "physics");

 $chart = new pChart(700, 230);
 $chart->setFontProperties($font_path,8);
 $chart->setGraphArea(50, 30, 680, 200);

 /* グラフに背景色をつける */
 $chart->drawFilledRoundedRectangle(7,7,693,223,5,240,240,240);

 /* グラフ背景に縁をつける */
 $chart->drawRoundedRectangle(5,5,695,225,5,230,230,230);

 /* グラフ領域に背景色をつける */
 $chart->drawGraphArea(255,255,255,TRUE);

 $chart->drawScale($data->GetData(),$data->GetDataDescription(),SCALE_START0,150,150,150,TRUE,0,2,TRUE);

 /* グリッド線を表示する */
 $chart->drawGrid(4,TRUE,230,230,230,50);

 /* chart に data を配置しグラフを描く */
 /* 棒グラフの場合は drawBarGraph */
 $chart->drawBarGraph($data->GetData(), $data->GetDataDescription(), TRUE);

 /* 凡例を追加する */
 $chart->setFontProperties($font_path,8);
 $chart->drawLegend(596,150,$data->GetDataDescription(),255,255,255);

 /* グラフタイトルを追加する */
 $chart->setFontProperties($font_path,10);
 $chart->drawTitle(50,22,"テスト結果",50,50,50,585);

 /* 画像として出力する */
 $chart->Stroke();
}

function exam_all_radar() {
 /* pChart を使用する */
 App::import('Vendor', 'pchart/pdata');
 App::import('Vendor', 'pchart/pchart');

 $font_path = "c:\Windows\Fonts\sazanami-gothic.ttf";

 /* Cache に保存された値を読み込む */
 $users = Cache::read('users');
 if ($users == false) {
  /* DB から値を取得 */
  $users = $this->User->find('all');
 }
 else {
  Cache::delete('users');
 }

 $scores = array();
 $name = array();

 foreach ($users as $user) {
  $score = array();
  $username = $user['User']['username'];
  array_push($score, $user['Exam']['math']);
  array_push($score, $user['Exam']['english']);
  array_push($score, $user['Exam']['physics']);
  $scores[$username] = $score;
  array_push($name, $username);
 }

 $data = new pData;
 $i = 0;
 foreach ($name as $username) {
  $data->AddPoint($scores[$username], "serie" . $i);
  $data->AddSerie("serie" . $i);
  $data->SetSerieName($username, "serie" . $i);
  $i++;
 }
 $data->AddPoint(array("math", "english", "physics"), "subject");
 $data->SetAbsciseLabelSerie("subject");

 $chart = new pChart(400, 400);
 $chart->setFontProperties($font_path,8);
 $chart->setGraphArea(30, 30, 370, 370);

 /* グラフに背景色をつける */
 $chart->drawFilledRoundedRectangle(7,7,393,393,5,240,240,240);

 /* グラフ背景に縁をつける */
 $chart->drawRoundedRectangle(5,5,395,395,5,230,230,230);

 /* chart に data を配置しグラフを描く */
 /* レーダーチャート */
 $chart->drawRadarAxis($data->GetData(), $data->GetDataDescription(), TRUE, 20, 120, 120, 120, 230, 230);
 $chart->drawFilledRadar($data->GetData(), $data->GetDataDescription(), 50, 20);

 /* 凡例を追加する */
 $chart->setFontProperties($font_path,8);
 $chart->drawLegend(15, 15, $data->GetDataDescription(), 255, 255, 255);

 /* グラフタイトルを追加する */
 $chart->setFontProperties($font_path,10);
 $chart->drawTitle(0,22,"テスト結果",50,50,50,400);

 /* 画像として出力する */
 $chart->Stroke();
}

[CakePHP][pChart]CakePHP で pChart を使う

app/vendors に pchat ディレクトリを作成し、その下に pCache.class, pChart.class, pData.class を配置する。ここで拡張子の class を php に変更することで pChart のモジュールが読み込めるようになる。
function exam_graph() {
 /* pChart を使用する */
 App::import('Vendor', 'pchart/pdata');
 App::import('Vendor', 'pchart/pchart');

 $font_path = "c:\Windows\Fonts\sazanami-gothic.ttf";

 /* Cache に保存された値を読み込む */
 $users = Cache::read('users');
 $total = Cache::read('total');

 Cache::delete('users');
 Cache::delete('total');

 $y1data = array();
 $a = array();

 foreach ($users as $user) {
  array_push($y1data, $user['Exam']['math']);
  array_push($a, $user['User']['username']);
 }

 $data = new pData;
 $data->AddPoint($y1data, "math");
 $data->AddPoint($a, "date");
 $data->AddSerie("math");
 $data->SetAbsciseLabelSerie("date");
 $data->SetSerieName("数学", "math");

 $chart = new pChart(700, 230);
 $chart->setFontProperties($font_path,8);
 $chart->setGraphArea(50, 30, 680, 200);
 $chart->drawScale($data->GetData(),$data->GetDataDescription(),SCALE_NORMAL,150,150,150,TRUE,0,2,TRUE);

 /* chart に data を配置しグラフを描く */
 /* 棒グラフの場合は drawBarGraph */
 $chart->drawBarGraph($data->GetData(), $data->GetDataDescription(), TRUE);

 /* 画像として出力する */
 $chart->Stroke();
}

2013年5月5日日曜日

[pChart]レーダーチャート

レーダーチャートの軸を描く
$chart->drawRadarAxis($data->GetData(), $data->GetDataDescription(), TRUE, 20, 120, 120, 120, 230, 230);
void pChart::drawRadarAxis($Data,$DataDescription,$Mosaic=TRUE,$BorderOffset=10,$A_R=60,$A_G=60,$A_B=60,$S_R=200,$S_G=200,$S_B=200,$MaxValue=-1);
Table: drawRadarAxis
Parameter説明
$Dataプロットするデータ
$DataDescriptionプロットするデータの Data Description
$MosaicFALSE の場合は網領域が灰色に塗られない
$BorderOffsetグラフ境界からのオフセット値 (px 単位)
$A_R軸色 (R)
$A_G軸色 (G)
$A_B軸色 (B)
$S_R網色 (R)
$S_G網色 (G)
$S_B網色 (B)
$MaxValue最大値
  • $BorderOffset = 0 の場合
    $chart->drawRadarAxis($data->GetData(), $data->GetDataDescription(), TRUE, 0, 120, 120, 120, 230, 230);
  • $BorderOffset = 50 の場合
    $chart->drawRadarAxis($data->GetData(), $data->GetDataDescription(), TRUE, 50, 120, 120, 120, 230, 230);
  • $A_R = 255, $A_G = 0, $A_B = 0 の場合
    $chart->drawRadarAxis($data->GetData(), $data->GetDataDescription(), TRUE, 20, 255, 0, 0, 230, 230);
  • $S_R = 0, $S_G = 255, $S_B = 0 の場合
    $chart->drawRadarAxis($data->GetData(), $data->GetDataDescription(), TRUE, 20, 120, 120, 120, 0, 255, 0);


レーダーチャートを描く(線)
$chart->drawRadar($data->GetData(), $data->GetDataDescription, 20);
void pChart::drawRadar($Data,$DataDescription,$BorderOffset=10,$MaxValue=-1);
Table: drawRadar
Parameter説明
$Dataプロットするデータ
$DataDescriptionプロットするデータの Data Description
$BorderOffsetグラフ境界からのオフセット値 (px 単位)
$MaxValue最大値
$BorderOffset と $MaxValue は drawRadarAxis() で設定した値と同じにすること。

レーダーチャートを描く(塗りつぶし)
$chart->drawFilledRadar($data->GetData(), $data->GetDataDescription(), 50, 20);
void pChart::drawFilledRadar($Data,$DataDescription,$Alpha=50,$BorderOffset=10,$MaxValue=-1);
Table: drawFilledRadar
Parameter説明
$Dataプロットするデータ
$DataDescriptionプロットするデータの Data Description
$Alpha透過度 (下図参照)
$BorderOffsetグラフ境界からのオフセット値 (px 単位)
$MaxValue最大値
$BorderOffset と $MaxValue は drawRadarAxis() で設定した値と同じにすること。
  • $Alpha = 90 の場合
    $chart->drawFilledRadar($data->GetData(), $data->GetDataDescription(), 90, 20);

[pChart]装飾

凡例 (Legend) を追加する
グラフを描画する前に pChart::drawLegend() で凡例を追加する。
凡例に表示される文字列は以下のようにすると割り当てた名前が表示される。
$data = new pData;
$data->SetSerieName("数学", "math");
$font_path = "c:\Windows\Fonts\sazanami-gothic.ttf";

/* 凡例を追加する */
$chart->setFontProperties($font_path,8);
$chart->drawLegend(596,150,$data->GetDataDescription(),255,255,255);

$chart->Stroke();
void pChart::drawLegend($XPos, $YPos, $DataDescription, $R, $G, $B, $Rs=-1, $Gs=-1, $Bs=-1, $Rt=0, $Gt=0, $Bt=0, $Border=FALSE);
Table: drawLegend
Parameter説明
$XPos凡例の X 位置
$YPos凡例の Y 位置
$DataDescription表示する判例の DataDescription
$R背景色 (R)
$G背景色 (G)
$B背景色 (B)
$Rs=-1影色 (R)
$Gs=-1影色 (G)
$bs=-1影色 (B)
$Rt=0文字色 (R)
$Gt=0文字色 (G)
$Bt=0文字色 (B)
$Border=FALSE境界線


タイトルを追加する
グラフを描画する前に pChart::drawTitle() でグラフのタイトルを追加する。
$font_path = "c:\Windows\Fonts\sazanami-gothic.ttf";

/* グラフタイトルを追加する */
$chart->setFontProperties($font_path,10);
$chart->drawTitle(50,22,"数学のテスト結果",50,50,50,585);

$chart->Stroke();
void pChart::drawTitle($XPos, $YPos, $Value, $R, $G, $B, $XPos2=-1, $YPos2=-1, $Shadow=FALSE);
Table: drawTitle
Parameter説明
$XPosタイトルの X 左上位置
$YPosタイトルの Y 左上位置
$Value表示する文字列
$R文字色 (R)
$G文字色 (G)
$B文字色 (B)
$XPos2タイトルの X 右下位置、タイトルは $XPos との水平中心に配置される
$YPos2タイトルの Y 右下位置、タイトルは $YPos との垂直中心に配置される
$Shadow文字の影


グラフ領域の見た目を変更する
  • グラフに背景色をつける pChart::drawFilledRoundedRectangle() でグラフに背景色 (コーナーに丸みあり) をつける。
    /* グラフに背景色をつける */
    $chart->drawFilledRoundedRectangle(7,7,693,223,5,240,240,240);
    void pChart::drawFilledRoundedRectangle($X1, $Y1, $X2, $Y2, $Radius, $R, $G, $B);
    Table: drawFilledRoundedRectangle
    Parameter説明
    $X1左上 X 座標
    $Y1左上 Y 座標
    $X2右下 X 座標
    $Y2右下 Y 座標
    $Radiusコーナーの曲がり具合 (半径)
    $R塗りつぶし色 (R)
    $G塗りつぶし色 (G)
    $B塗りつぶし色 (B)
  • グラフ背景に縁をつける
    pChart::drawRoundedRectangle() でグラフ背景に縁 (コーナーに丸みあり) をつける。
    /* グラフ背景に縁をつける */
    $chart->drawRoundedRectangle(5,5,695,225,5,230,230,230);
    void pChart::drawRoundedRectangle($X1, $Y1, $X2, $Y2, $Radius, $R, $G, $B);
    Table: drawRoundedRectangle
    Parameter説明
    $X1左上 X 座標
    $Y1左上 Y 座標
    $X2右下 X 座標
    $Y2右下 Y 座標
    $Radiusコーナーの曲がり具合 (半径)
    $R線色 (R)
    $G線色 (G)
    $B線色 (B)
  • グラフ領域に背景色をつける
    @Chart::drawGraphArea() でグラフ領域に背景色をつける。
    /* グラフ領域に背景色をつける */
    $chart->drawGraphArea(255,255,255,TRUE);
    void pChart::drawGraphArea($R,$G,$B,$Stripe=FALSE);
    Table: drawGraphArea
    Parameter説明
    $R塗りつぶし色 (R)
    $G塗りつぶし色 (G)
    $B塗りつぶし色 (B)
    $Stripe45 度のストライプ線で背景色を塗る
  • グリッド線を表示する
    /* グリッド線を表示する */
    $chart->drawGrid(4,TRUE,230,230,230,50);
    void pChart::drawGrid($LineWidth,$Mosaic=TRUE,$R=220,$G=220,$B=220,$Alpha=255);
    Table: drawGrid
    Parameter説明
    $LineWidthグリッド線の太さ
    $MosaicTRUE の場合 2 ラインごとに背景色が変更されモザイク状になる (下図参照)
    $Rグリッド色 (R)
    $Gグリッド色 (G)
    $Bグリッド色 (B)
    $Alphaモザイクエリアの透過度
    $Mosaic=FALSE の場合

[pChart]軸の調整

pChart::drawScale() のパラメータにより軸の調整を行う。
void pChart::drawScale($Data, $DataDescription, $ScaleMode, $R, $G, $B, $DrawTicks=TRUE, $Angle=0, $Decimals=1, $WithMargin=FALSE, $SkipLabels=1, $RightScale=FALSE);
Table: drawScale
Parameter説明
$Dataプロットするデータ
$DataDescriptionプロットするデータの DataDescription
$ScaleMode下表参照
$R色 (R)
$G色 (G)
$B色 (B)
$DrawTicksFALSE にすることでラベルが表示されなくなる (下図参照)
$Angleラベルの角度
$Decimals数値桁数
$WithMarginFALSE の場合グラフの表示幅が描画領域いっぱいで使用される (下図参照)
$SkipLabelsX 軸のラベルのスキップ数 (下図参照)
$RightScale
Table: ScaleMode の値
Parameter意味
SCALE_NORMALプロット値の最大・最小値まで表示
SCALE_START0最小値が 0 に設定される
SCALE_ADDALLすべてのプロット値の累積で最大・最小が決まる
SCALE_ADDALLSTART0上項目と同様だが最小値が 0 に設定される
  • SCALE_NOMAL の場合
    $chart->drawScale($data->GetData(),$data->GetDataDescription(),SCALE_NORMAL,150,150,150,TRUE,0,2,TRUE);
  • SCALE_START0 の場合
    $chart->drawScale($data->GetData(),$data->GetDataDescription(),SCALE_START0,150,150,150,TRUE,0,2,TRUE);
  • $DrawTicks=FALSE の場合
    $chart->drawScale($data->GetData(),$data->GetDataDescription(),SCALE_START0,150,150,150,FALSE,0,2,TRUE);
  • $WidthMargin=FALSE の場合
    $chart->drawScale($data->GetData(),$data->GetDataDescription(),SCALE_START0,150,150,150,TRUE,0,2,FALSE);
  • $SkipLabel=2 の場合
    $chart->drawScale($data->GetData(),$data->GetDataDescription(),SCALE_START0,150,150,150,TRUE,0,2,TRUE, 2);

[pChart]インストール

JpGraph はライセンスが QPL であり、pChart はライセンスが GPL である。
  1. pChart | a PHP Charting library から pChart をダウンロードする。
  2. ダウンロードしたファイルを展開して php/PEAR 以下に pChart ディレクトリを作成し配置する。
  3. pChart ディレクトリ内に必要なファイルがあるので php/PEAR/pChart 直下に配置しなおす。


動作確認
<?php
include("pChart/pData.class");
include("pChart/pChart.class");

$font_path = "c:\Windows\Fonts\sazanami-gothic.ttf";

/* data に plot するデータ情報を入れる */
$data = new pData;
$data->AddPoint(array(1, 4, -3, 5, 10, -2, -8, 2), "serie1");
$data->AddAllSeries();
$data->SetAbsciseLabelSerie();
$data->SetSerieName("test1", "serie1");

/* chart にグラフを描く領域の情報を入れる */
$chart = new pChart(700, 230);
$chart->setFontProperties($font_path,8);
$chart->setGraphArea(50, 30, 680, 200);
$chart->drawScale($data->GetData(),$data->GetDataDescription(),SCALE_NORMAL,150,150,150,TRUE,0,2,TRUE);

/* chart に data を配置しグラフを描く */
/* 棒グラフの場合は drawBarGraph */
$chart->drawBarGraph($data->GetData(), $data->GetDataDescription(), TRUE);
/* 線グラフの場合は drawLineGraph */
//$chart->drawLineGraph($data->GetData(),$data->GetDataDescription());
/* plot の場合は drawPlotGraph */
//$chart->drawPlotGraph($data->GetData(),$data->GetDataDescription(),3,2,255,255,255);

/* 画像として出力する */
$chart->Stroke();
?>

[JavaScript]CSV to Table

cvs2table
Index of /lib/jquery/plugin/csv2table
上記サイトから csv2table-0.02-b-4.1.zip をダウンロードする
<html>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
 <script src="./js/jquery.csv2table-0.02-b-4.1.js" type="text/javascript" charset="utf-8"></script>
  <body>
    csv2table<br/>
    <div id="view0"></div>
    <script type="text/javascript">
      $(function() {
        $('#view0').csv2table('./data.csv');
      });
    </script>
    <hr/>
    csv2table (sortable: false)<br/>
    <div id="view1"></div>
    <script type="text/javascript">
      $(function() {
        $('#view1').csv2table('./data.csv',
          {
            sortable: false,
          });
      });
    </script>
    <hr/>
    csv2table (onload: tr:even)<br/>
    <div id="view2"></div>
    <script type="text/javascript">
      $(function() {
        $('#view2').csv2table('./data.csv',
          {
            onload: function(id, op, data, ary) {
              $('tr:even', '#' + id).css('background', '#eee')
            },
          });
      });
    </script>
  </body>
</html>
sample (fc2 に置いてあるテストページに飛びます)

csvtotable
jquerycsvtotable
上記サイトから jquerycsvtotable.zip をダウンロードする
<html>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <link rel="stylesheet" href="css/csvtable.css" type="text/css">
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
 <script type="text/javascript" src="js/jquery.csvToTable.js"></script>
  <body>
    csvtotable<br/>
    <div id="view1"></div>
    <script type="text/javascript">
      $(function() {
        $('#view1').CSVToTable('./data.csv');
      });
    </script>
    <hr/>
    csvtoable (loadingImage)<br/>
    <div id="view2"></div>
    <script type="text/javascript">
      $(function() {
        $('#view2').CSVToTable('./data.csv',
          {
            loadingImage: 'img/loading.gif',
          });
      });
    </script>
  </body>
</html>
sample (fc2 においてあるテストページに飛びます)

2013年5月4日土曜日

[OpenSSL]AES コマンド

AES 256 CBC モードで暗号化する手順
$ openssl enc -aes-256-cbc -e -in null.dat -out enc_aes256cbc.dat -p -nosalt
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:
key=EA703E7AA1EFDA0064EAA507D9E8AB7E63413AFCBF321FFB9618A9336087C322
iv =AD804FC4942C79B8E7A3F5C26B1E599E


復号化する手順
$ openssl enc -aes-256-cbc -d -in enc_aes256cbc.dat -out dec_aes256cbc.dat -p -nosalt
enter aes-256-cbc decryption password:
key=EA703E7AA1EFDA0064EAA507D9E8AB7E63413AFCBF321FFB9618A9336087C322
iv =AD804FC4942C79B8E7A3F5C26B1E599E

br/ Key と IV を生成する方法
passphase = "hoge" から Key と IV を生成する。 passphase から MD5 値をとる。
00 | 68 6F 67 65
-- (MD5) -->
00 | EA 70 3E 7A A1 EF DA 00 64 EA A5 07 D9 E8 AB 7E
MD5 を 1 回行った結果に hoge を追加して再び MD5 値をとる。
00 | EA 70 3E 7A A1 EF DA 00 64 EA A5 07 D9 E8 AB 7E
10 | 68 6F 67 65
-- (MD5) -->
00 | 63 41 3A FC BF 32 1F FB 96 18 A9 33 60 87 C3 22
その結果に hoge を追加して再び MD5 値をとる。
00 | 63 41 3A FC BF 32 1F FB 96 18 A9 33 60 87 C3 22
10 | 68 6F 67 65
-- (MD5) -->
00 | AD 80 4F C4 94 2C 79 B8 E7 A3 F5 C2 6B 1E 59 9E
以上から 3 つの MD5 値が得られる。
MD5 1回目 EA 70 3E 7A A1 EF DA 00 64 EA A5 07 D9 E8 AB 7E
MD5 2回目 63 41 3A FC BF 32 1F FB 96 18 A9 33 60 87 C3 22
MD5 3回目 AD 80 4F C4 94 2C 79 B8 E7 A3 F5 C2 6B 1E 59 9E
1 回目 MD5 値と 2 回目 MD5 値を連結した値が Key となり、3 回目 MD5 値が IV となる。
Key = EA 70 3E 7A A1 EF DA 00 64 EA A5 07 D9 E8 AB 7E 63 41 3A FC BF 32 1F FB 96 18 A9 33 60 87 C3 22
IV = AD 80 4F C4 94 2C 79 B8 E7 A3 F5 C2 6B 1E 59 9E


OpenSSL コマンドで passphase に hoge を指定した時の Key と IV
$ openssl enc -aes-256-cbc -e -in null.dat -out enc_aes256cbc.dat -p -pass pass:hoge -nosalt
key=EA703E7AA1EFDA0064EAA507D9E8AB7E63413AFCBF321FFB9618A9336087C322
iv =AD804FC4942C79B8E7A3F5C26B1E599E

[OpenSSL]AES 暗号モード

AES には以下の 4 モードがある。
  • ECB (Electronic Code Block)
  • CBC (Cipher Block Chaining)
  • OFB (Output FeedBack)
  • CFB (Cipher FeedBack)
また鍵長 (Bit 数) が 3 種選べる。
  • 128bit
  • 192bit
  • 256bit
以上から AES のモードには以下のパターンが存在する (表中の文字列は OpenSSL コマンドでAES 暗号を行う場合の引数)
Table: AES モードの組み合わせ
ECBCBCOFBCBB
128bitaes-128-ecbaes-128-cbcaes-128-ofbaes-128-cfb
192bitaes-192-ecbaes-192-cbcaes-192-ofbaes-192-cfb
256bitaes-256-ecbaes-256-cbcaes-256-ofbaes-256-cfb

[OpenSSL]Triple DES

Triple DES EDE CBC モードで暗号化の手順
$ openssl enc -des-ede3-cbc -e -in null.dat -out enc_des_e
de3_cbc.dat -p -nosalt
enter des-ede3-cbc encryption password:
Verifying - enter des-ede3-cbc encryption password:
key=EA703E7AA1EFDA0064EAA507D9E8AB7E63413AFCBF321FFB
iv =9618A9336087C322


復号化の手順
$ openssl enc -des-ede3-cbc -d -in enc_des_ede3_cbc.dat -o
ut dec_des_ede3_cbc.dat -p -nosalt
enter des-ede3-cbc decryption password:
key=EA703E7AA1EFDA0064EAA507D9E8AB7E63413AFCBF321FFB
iv =9618A9336087C322


Key, IV の生成方法
passphase = "hoge" から Key と IV を生成する。 passphase から MD5 値をとる。
00 | 68 6F 67 65
-- (MD5) -->
00 | EA 70 3E 7A A1 EF DA 00 64 EA A5 07 D9 E8 AB 7E
MD5 を 1 回行った結果に hoge を追加して再び MD5 値をとる。
00 | EA 70 3E 7A A1 EF DA 00 64 EA A5 07 D9 E8 AB 7E
10 | 68 6F 67 65
-- (MD5) -->
00 | 63 41 3A FC BF 32 1F FB 96 18 A9 33 60 87 C3 22
以上から 2 つの MD5 値が得られる。
1 回目 MD5 値 EA 70 3E 7A A1 EF DA 00 64 EA A5 07 D9 E8 AB 7E
2 回目 MD5 値 63 41 3A FC BF 32 1F FB 96 18 A9 33 60 87 C3 22
Key は 1 回目 MD5 値に 2 回目 MD5 値の上位 8 バイトをくっつけた値になる。
IV は 2 回目 MD5 値の下位 8 バイトとなる。
Key = EA 70 3E 7A A1 EF DA 00 64 EA A5 07 D9 E8 AB 7E 63 41 3A FC BF 32 1F FB
IV = 96 18 A9 33 60 87 C3 22
passphase に hoge を指定して Triple DES EDE CBC モードを行った結果
$ openssl enc -des-ede3-cbc -e -in null.dat -out enc_des_ede3_cbc.dat -p -nosalt -pass pass:hoge
key=EA703E7AA1EFDA0064EAA507D9E8AB7E63413AFCBF321FFB
iv =9618A9336087C322

[OpenSSL]DES コマンド

暗号化手順
$ openssl des -e -in test.txt -out test_enc_des.txt
enter des-cbc encryption password:
Verifying - enter des-cbc encryption password:
Key と IV を指定する場合
$ openssl enc -des-ecb -e -in null.dat -out null_enc_des.dat -iv 00000000 -K 00000000
Key と IVを表示する
$ openssl des -e -in test.txt -out test.enc -p -nosalt
enter des-cbc encryption password:
Verifying - enter des-cbc encryption password:
key=EA703E7AA1EFDA00
iv =64EAA507D9E8AB7E
Keyを作成するための方法を指示する
$ openssl enc -des-ecb -e -in test.txt -out test.enc -iv 0000000000000000 -p -nosalt -md md5
enter des-ecb encryption password:
Verifying - enter des-ecb encryption password:
key=EA703E7AA1EFDA00
iv =0000000000000000


復号化手順
$ openssl des -d -in test_enc_des.txt -out test_dec_des.txt
enter des-cbc decryption password:
Key と IV (Initial Vector) を指定する場合
$ openssl enc -des-ecb -d -in null_enc_des.dat -out null_dec_des.dat -iv 00000000 -K 00000000


Key, IV の作り方
$ openssl enc -des-ecb -e -in test.txt -out test.enc -p -nosalt
enter des-ecb encryption password:
Verifying - enter des-ecb encryption password:
key=EA703E7AA1EFDA00
iv =64EAA507D9E8AB7E
password を hoge にすると key, iv は以下のようになる
key=EA703E7AA1EFDA00
iv =64EAA507D9E8AB7E
hoge と書いたテキストファイル hoge.txt (末尾に改行なしで保存) を準備して MD5 ダイジェスト値を取ると以下のようになる。
$ openssl dgst -md5 hoge.txt
MD5(hoge.txt)= ea703e7aa1efda0064eaa507d9e8ab7e
MD5 ダイジェスト値の前半が key に該当し、後半が iv に該当する。すなわち
passphase = hoge
hoge -- (MD5) --> ea703e7aa1efda0064eaa507d9e8ab7e
上位8byte = ea703e7aa1efda00 = key
下位8byte = 64eaa507d9e8ab7e = iv

[OpenSSL]DES 暗号モード

DES のモードには以下のパターンが存在する(表中の文字列は OpenSSL コマンドで DES 暗号を行う場合の引数)
Table: DES モードの組み合わせ
ECBCBCCFBOFB
DESdes-ecbdes-cbcdes-cfbdes-ofb
3DES two keydes-ededes-ede-cbcdes-ede-cfbdes-ede-ofb
3DES three keydes-ede3des-ede3-cbcdes-ede3-cfbdes-ede3-cfb

[OpenSSL]DES 暗号

DES には以下の 4 モードがある。
  • ECB (Electronic Code Block)
    • 基本となるモード。
    • 暗号ブロック間の関連性はなく、単に平文をブロックごとに区切り、暗号化する方式。
    • 各ブロックが独立しているので、並列処理が可能で高速。
    • 暗号の強度は低い。
  • CBC (Cipher Block Chaining)
    • 既に暗号化されたデータを利用して次のブロックを暗号化する。
    • 一つ前の平文ブロックの暗号結果(暗号ブロック)と次の平文ブロックをXOR演算子、その結果を暗号化する方式。暗号には、外部から与えた初期ベクトル (Initial Vecotr: IV)を使う。
    • ECB モードよりも暗号強度が高い
  • CFB (Cipher FeedBack)
    • まず最初にIVを暗号化し、それと1番目の平文ブロックとのXOR演算によって1番目の暗号ブロックを生成する。続いて1番目の 暗号ブロックを暗号化し、それと2番目の平文ブロックとのXOR演算によって、2番目の暗号ブロックを生成する。
  • OFB (Output FeedBack)
    • まず最初にIVを暗号化し、それと1番目の平文ブロックとのXOR演算によって1番目の暗号ブロックを生成する。続いて暗号化さ れたIVを更に暗号化し、それと2番目の平文ブロックとのXOR演算によって2番目の暗号化ブロックを生成する。

[OpenSSL]公開鍵暗号方式

RSA (Rivest Shamir Adleman)Ron Rivest, Adi Shamir, LeonardAdleman の三氏によって 1978 年に公開された公開鍵暗号方式。3 人の名前の頭文字をとって RSA と名付けられた。公開鍵暗号方式の標準として広く普及している。桁数の大きな整数の素因数分解が困難であるということを安全性の根拠にしている。1024 ビットの鍵が標準的に使用されていたが、危殆化が懸念されており、2048 ビット以上の鍵への移行が進められている。
楕円曲線暗号 (Elliptic Curve Cryptosystem)楕 円曲線状の離散対数問題 (ECDLP: Elliptic Curve Discrete Logarithm Problem) の難しさを安全性の根拠にする公開鍵暗号化方式。RSA よりも短い鍵長で同程度の暗号強度を実現でき、その分処理が高速に行えるという長所があるが、条件の選び方によっては逆に脆弱になってしまうという欠点も 指摘されている。160 ビットの鍵長で、鍵長 1024 ビットの RSA と同程度の安全性を保つとされている。

[OpenSSL]ブロック暗号方式

DES (Data Enryption Standard)1975年米国商務省標準局 で公表され、1977年以降米国政府の標準として採用された。ブロック長は64ビットで56ビットの鍵を使用する。
3DES (Triple DES)DESを三重に適用するこ とによって強度を高めたもの。
3DES には使用する 2 つの鍵を使用する場合と 3 つの鍵を使用する場合がある
  • 2 つの鍵を使用する場合
    鍵 A で暗号化 → 鍵 B で複合化 → 鍵 A で暗号化
  • 3 つの鍵を使用する場合
    鍵 A で暗号化 → 鍵 B で複合化 → 鍵 C で暗号化
上記の「暗号→復号→暗号」の流れを EDE (Encrypt-Decrypt-Encrypt) という
AES (Advanced Encryption Standard)DESの後継となる米国政府 の標準暗号方式。NIST(米国標準技術 局)の公募で集まった15の方式が審査を受けていたが、ベルギーのJoan Daemen氏とVincent Rijmen氏が開発した「Rijndael」という方式が選ばれた。ブロック長は128ビットで、使用する鍵の長さは128/192/256ビットの中 から選択できる。
IDEA (International Data Encryption Algorithm)スイス工科大学の James L.Massey 氏と Xuejia Lai 氏によって考案された方式。ブロック長は 64 ビットで 128 ビットの鍵を使用する。PGP や SSH などで使用されている。
FEAL (Fast data Enciphement ALgorithm)NTT が開発した方式であり、IC カードや携帯電話などで利用されている。ブロック長は 64 ビットで、64 ビットもしくは 128 ビットの鍵を使用する。
MISTY三菱電機が開発した方式であ り、携帯電話の W-CDMA 用暗号 KASUMI はこれがベースになっている。ブロック長は 64 ビットで 128 ビットの鍵を使用する。
RC2Ron Rivest 氏が開発したブロック暗号方式。ブロック長は 64 ビットえ可変長鍵(最大 128 ビット)を使用する。
RC5Ron Rivest 氏が開発したブロック暗号方式。ブロック長、鍵長ともに可変である。

[TeX]Section

Section番号の表記変更
section, subsectionコマンドを使用すると通常は以下のように数字で表示される。
\documentclass[9pt,a4paper]{jsarticle}
\begin{document}
\section{その 1}

\subsection{その 1-1}

\section{その 2}

\end{document}

\renewcommand を使用してsectionコマンドを再定義することでセクション番号に使用される文字を変更、またはなくすことができる。

セクション番号をなくす
\documentclass[9pt,a4paper]{jsarticle}
\renewcommand{\thesection}{}
\renewcommand{\thesubsection}{}
\begin{document}
\section{その 1}

\subsection{その 1-1}

\section{その 2}

\end{document}


セクション番号をローマ数字表記に変更する
\documentclass[9pt,a4paper]{jsarticle}
\renewcommand{\thesection}{\Roman{section}}
\renewcommand{\thesubsection}{\thesection-\roman{subsection}}
\begin{document}
\section{その 1}

\subsection{その 1-1}

\section{その 2}

\end{document}

他にも \alpha で a, b, c, ... となり、\Alpha で A, B, C, ... となる。

Section のサイズ調整
次の tex ファイルから Section のサイズ調整をする。
\documentclass[a4paper,9pt]{jsarticle}

\begin{document}
あああああああああああああああああああああああ \\
あああああああああああああああああああああああ

\section{第1章}
いいいいいいいいいいいいいいいいいいいいいいい \\
いいいいいいいいいいいいいいいいいいいいいいい

\section{第2章}
ううううううううううううううううううううううう \\
ううううううううううううううううううううううう

\section{第3章}
えええええええええええええええええええええええ \\
えええええええええええええええええええええええ

\end{document}
何も設定していない状態で出力した結果。

Section のサイズ調整をするために sectinFontSize.sty というパッケージを準備する。
このパッケージ内で Section コマンドを再定義してサイズの調整をする。
\documentclass[a4paper,9pt]{jsarticle}
\usepackage{sectionFontSize}

\begin{document}
あああああああああああああああああああああああ \\
あああああああああああああああああああああああ

\section{第1章}
いいいいいいいいいいいいいいいいいいいいいいい \\
いいいいいいいいいいいいいいいいいいいいいいい

\section{第2章}
ううううううううううううううううううううううう \\
ううううううううううううううううううううううう

\section{第3章}
えええええええええええええええええええええええ \\
えええええええええええええええええええええええ

\end{document}
section コマンドは以下のフォーマットで定義する。
\@startsection {NAME}{LEVEL}{INDENT}{BEFORESKIP}{AFTERSKIP}{STYLE} optional * [ALTHEADING]{HEADING}
Table: startsection
NAMEsection, subsection などが入る
LEVELセクションの深さ
INDENT左マージンからのインデント量
BEFORESKIP前段落からのスキップ量, マイナス値を指定するとセクションに続く段落先頭行のインデントがなくなる
AFTERSKIP後ろに続く段落とのスキップ量, マイナス値を指定するとセクションに続いて改行なしで段落が始まる
STYLE文字スタイル|
  • INDENT=0pt, BEFORESKIP=0pt, AFTERSKIP=0pt の場合
    Example: sectinFontSize.sty
    \NeedsTeXFormat{LaTeX2e}
    \ProvidesPackage{sectionFontSize}[2010/02/08 Section font size package]
    \renewcommand{\section}{%
     \@startsection{section}{1}{0pt}{0pt}{0pt}{\normalsize\bf}
    }
  • INDENT=10pt, BEFORESKIP=0pt, AFTERSKIP=0pt の場合
    Example: sectinFontSize.sty
    \NeedsTeXFormat{LaTeX2e}
    \ProvidesPackage{sectionFontSize}[2010/02/08 Section font size package]
    \renewcommand{\section}{%
     \@startsection{section}{1}{10pt}{0pt}{0pt}{\normalsize\bf}
    }
    
    INDENT を 10pt 下げて表示される。
  • INDENT=0pt, BEFORESKIP=10pt, AFTERSKIP=0pt の場合
    Example: sectinFontSize.sty
    \NeedsTeXFormat{LaTeX2e}
    \ProvidesPackage{sectionFontSize}[2010/02/08 Section font size package]
    \renewcommand{\section}{%
     \@startsection{section}{1}{0pt}{10pt}{0pt}{\normalsize\bf}
    }
    
    前段落からのスキップ量 10pt
  • INDENT=0pt, BEFORESKIP=-10pt (段落開始行のインデントなし), AFTERSKIP=0pt の場合
    Example: sectionFontSize.sty
    \NeedsTeXFormat{LaTeX2e}
    \ProvidesPackage{sectionFontSize}[2010/02/08 Section font size package]
    \renewcommand{\section}{%
     \@startsection{section}{1}{0pt}{-10pt}{0pt}{\normalsize\bf}
    }
    
  • INDENT=0pt, BEFORESKIP=0pt, AFTERSKIP=10pt の場合
    Example: sectinFontSize.sty
    \NeedsTeXFormat{LaTeX2e}
    \ProvidesPackage{sectionFontSize}[2010/02/08 Section font size package]
    \renewcommand{\section}{%
     \@startsection{section}{1}{0pt}{0pt}{10pt}{\normalsize\bf}
    }
    
    段落開始前のスキップ量 10pt
  • INDENT=0pt, BEFORESKIP=0pt, AFTERSKIP=-10pt (改行なしで段落開始) の場合
    Example: sectinFontSize.sty
    \NeedsTeXFormat{LaTeX2e}
    \ProvidesPackage{sectionFontSize}[2010/02/08 Section font size package]
    
    \renewcommand{\section}{%
    % \@startsection{section}{1}{\z@}{-3.5ex plus -1ex minus -.2ex}{2.3ex plus .2ex}{\normalsize\bf}
     \@startsection{section}{1}{0pt}{0pt}{-10pt}{\normalsize\bf}
    }
    

[TeX]Class, Package

  • LaTeX では文章で使用する体裁、コマンドをロードすることができる。
  • 文章の体裁は class を読み込む (例えば jsarticle.cls)。
  • コマンドは package (style) を読み込む (例えば grahicx.sty, graphicx.dtx)
  • class, package ファイルは以下のような構成からなる。
    1. Identification
      class, package の宣言
    2. Preliminary declarations
      コマンド, 他のファイルの読み込み
    3. Options
      オプション
    4. More declarations
      変数, コマンド, フォント


Identification
Package の場合
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{<package>}[<date> <other information>]
例)
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{testpackage}[2010/02/08 Test package]
Class の場合
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{<class-name>}[<date> <other information>]
例)
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{testclass}[2010/02/08 Test class]


class, package の読み込み
tex ファイル中で class, package など他のファイルを読み込む場合は以下のように指定する。
Package の場合
\RequirePackage[<options>]{<package>}[<date>]
例)
\RequirePackage{ifthen}{1994/06/01}
Class の場合
\LoadClass[<options>]{<class-name>}[<date>]
例)
\LoadClass[twocolumn]{article}


Options
\DeclareOption{<option>}{<code>}
例1)
graphics package でオプションに dvips を指定する場合は tex ファイルに
\usrpackage[dvips]{graphics}
と記述される。graphics package 内ではこの dvips オプションに対して以下のように振る舞いを記述してある。
\DeclareOption{dvips}{\input{dvips.def}}
例2)
article class でオプションにa4paper を指定する場合は tex ファイルに
\documentclass[a4paper]{article}
と記述される。article class 内ではこの a4paper オプションに対して以下のように用紙の縦横長が記述してある。
\DeclareOption{a4paper}{%
 \setlength{\paperheight}{297mm}%
 \setlength{\paperwidth}{210mm}%
}
と用紙の縦横長が記述してある

[TeX]表組み

行・ 列を跨ぐ表組みの作成方法
\begin{tabular}{|c|c|c|}
 \hline
 1 & 2 & 3 \\ \hline
 4 & 5 & 6 \\ \cline{1-2}
 7 & 8 & \\ \hline
 9 & \multicolumn{2}{|c|}{10} \\ \hline
\end{tabular}
出力結果は以下のようになる。


表の幅を指定
表の幅を指定するには tabularx パッケージを使用する。
\usepackage{tabularx}

\begin{tabularx}{100mm}{|p{20mm}|p{10mm}|X|}
 \hline
 1 & 2 & 3 \\ \hline
 4 & 5 & 6 \\ \hline
\end{tabularx}
\end{verbatim}
出力結果は以下のようになる。

もう少し複雑な例
\begin{tabularx}{\textwidth}{|p{10mm}|X|p{10mm}|p{10mm}|p{10mm}|}
 \hline
 \multicolumn{2}{|X|}{1} & 3 & 4 & 5 \\ \hline
 6 & \multicolumn{2}{X|}{7} & 8 & 9 \\ \hline
\end{tabularx}
出力結果は以下のようになる。


行を跨いで配置
最初に multirow パッケージを使用することを明記しておく。
\beginpackage{multirow}

\begin{document}
\begin{tabular}{|c|c|c|}
 \hline
 1 & 2 & 3 \\ \hline
 4 & 5 & \multirow{2}{*}{6} \\ \cline{1-2}
 7 & 8 & \\ \hline
 9 & \multicolumn{2}{c|}{10} \\ \hline
 \multirow{3}{*}{11} & 12 & 13 \\ \cline{2-3}
 & \multicolumn{2}{c|}{14} \\ \cline{2-3}
 & 15 & 16 \\ \hline
\end{tabular}
\end{document}
出力結果は以下のようになる。

[TeX]Windows にインストール

  1. TeX Live から install-tl.zip をダウンロードする。
  2. 解凍したディレクトリ内にあるinstall-tl.batを実行する。
Proxy環境下ではインターネットに接続できないので、コマンドプロンプトで以下を実行して環境変数を設定する。
set HTTP_PROXY=http://proxyserver:8080
install-tl.bat

[TeX]Linux にインストール

# yum install texlive* xdvik xdvipdfmx
# mktexlsr
この状態では jsarticle には非対応。
編集は EUC-JP で行うこと。UTF-8 で編集すると dvi に変換した時に文字化けを起こす。
$ platex test.tex
$ pxdvi test.dvi


IPA フォントをインストールする
# yum install ipa-gothic-fonts
# yum install ipa-mincho-fonts


Adobe Reader インストール
Adobe のページから Adobe Reader をダウンロードして PDF を見られるようにしておく。
2009/06/24 時点では AdbeRdr9.1.1-1_i486linux_jpn.rpm
# rpm -ihv --test AdobeRdr9.1.1-1_i486linux_jpn.rpm
Preparing...
#################################### [100%]
# rpm -ihv AdbeRdr9.1.1-1_i486linux_jpn.rpm
Preparing... #################################### [100%]
1:AdbeReader_jpn #################################### [100%]
dvi から PDF ファイルを作成
$ dvipdfmx test.dvi
Adobe Reader で表示
$ acroread test.pdf


jsarticle をインストール
  1. pLaTeX2e 新ドキュメントクラスから jsclasses-090222.zip (2009/08/06 時点) と jis-tfm.zipをダウンロードする
  2. インストール
    $ su -
    # mkdir /usr/share/texmf/ptex/platex/jsclass
    # mv jsclasses-090222.zip /usr/share/texmf/ptex/platex/jsclass/
    # mv jis-tfm.zip /usr/share/texmf/fonts/tfm/ptex/
    # cd /usr/share/texmf/ptex/platex/jsclass/
    # unzip jsclasses-090222.zip
    # rm jsclasses-090222.zip
    # cd /usr/share/texmf/fonts/tfm/ptex/
    # unzip jis-tfm.zip
    # rm jis-tfm.zip
    # mktexlsr
    最後に mktexlsr を実行することで platex にインストールしたことを伝えることができる
    この状態で jsarticle は使えるようになったが、日本語が含まれた tex ファイルをコンパイルすると文字化けが発生する
  3. jis フォントの追加
    # wget ftp://ftp.ascii.co.jp/pub/TeX/ascii-ptex/jvf/jis.tar.gz
    # wget ftp://ftp.ascii.co.jp/pub/TeX/ascii-ptex/jvf/morisawa.tar.gz
    # tar zxvf jis.tar.gz
    # tar zxvf morisawa.tar.gz
    # cp jis/tfm/ptex/* /usr/share/texmf/fonts/tfm/ptex/
    # cp jis/vf/* /usr/share/texmf/fonts/vf/ptex/
    # cp morisawa/tfm/ptex/* /usr/share/texmf/fonts/tfm/ptex/
    # cp morisawa/tfm/dvips/* /usr/share/texmf/fonts/tfm/ptex/
    # cp morisawa/vf/* /usr/share/texmf/fonts/vf/ptex/
    # mktexlsr
    これにより pxdvi を使えば日本語が表示されるようになる。ここで xdvi を使用すると文字化けしてしまうので注意。

2013年5月3日金曜日

[Saxon]Windows

インストール
  1. SAXON-HE 9.3 から saxonhe9-3-0-4j.zip をダウンロードする。
  2. ダウンロードしたファイルを展開する。


動作確認
> java -jar saxonhe9-3-0-4j\saxon9he.jar -s:test.xml -xsl:test.xsl -o:test.html
Warning: at xsl:stylesheet on line 2 column 81 of test.xsl:
  Running an XSLT 1 stylesheet with an XSLT 2 processor


DocBook で使う
> java -jar saxon9he.jar -s:hello.xml -xsl:C:/home/docbook/docbook-xsl-1.75.0/xhtml/docbook.xsl -o:hello.html
Warning: at xsl:stylesheet on line 4 column 317 of docbook.xsl:
  Running an XSLT 1 stylesheet with an XSLT 2 processor
Warning: on line 282 of stripns.xsl:
  The attribute axis starting at a document node will never select anything

[Saxon]Linux (Fedora)

インストール
# yum install saxon

動作確認
Example: test.xml
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="test.xsl" type="text/xsl" ?>
<document>
  <header>はじめての XML, XSLT</header>
  <paragraph>XML ,XSLT テスト</paragraph>
</document>

Example: test.xsl
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template>
  <xsl:template match="document">
    <html><xsl:apply-templates/></html>
  </xsl:template>
  <xsl:template match="header">
    <h1><xsl:value-of select="."/></h1>
  </xsl:template>
  <xsl:template match="paragraph">
    <p><xsl:value-of select="."/></p>
  </xsl:template>
</xsl:stylesheet>
saxon.jar を使って test.html を生成
$ java -jar /usr/share/java/saxon.jar -s:test.xml -xsl:test.xsl -o:test.html
Warning: at xsl:stylesheet on line 2 column 81 of test.xsl:
  Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor


DocBook で使う
DocBook の Style Sheet は /usr/share/sgml/docbook/xsl-stylesheets/xhtml/docbook.xsl にインストールされている
Example: test.xsl
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "/usr/share/sgml/docbook/xml-dtd-4.5/docbookx.dtd">
<article>
  <title>Hello, world</title>
  <sect1>
    <title>Hello, world</title>
    <para>Hello, world</para>
    <sect2>
      <title>こんにちは</title>
      <para>日本語表示できますか?</para>
    </sect2>
  </sect1>
</article>
$ java -jar /usr/share/java/saxon.jar -s:hello.xml -xsl:/usr/share/sgml/docbook/xsl-stylesheets/xhtml/docbook.xsl -o:hello.html
Warning: at xsl:stylesheet on line 4 column 317 of docbook.xsl:
  Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor


Ant (build.xml)
src ディレクトリにある原稿 xml を SAXON を通して DocBook の HTML ファイルを生成する build.xml は以下の通り。
<?xml version="1.0" encoding="UTF-8"?>

<project name="saxonTest" basedir="." default="html">
  <property name="BUILD" location="build"/>
  <property name="SRC" location="src"/>
  <property name="DOCBOOK_PUBLIC_ID" value="-//OASIS//DTD DocBook XML V4.5//EN"/>
  <property name="DOCBOOK_DTD" value="/usr/share/sgml/docbook/xml-dtd-4.5/docbookx.dtd"/>
  <property name="DOCBOOK_XSL" location="/usr/share/sgml/docbook/xsl-stylesheets/xhtml/docbook.xsl"/>
  <property name="SAXON_LOC" location="/usr/share/java/saxon.jar"/>

  <target name="init">
    <tstamp/>
    <mkdir dir="${BUILD}"/>
  </target>

  <target name="html" depends="init">
    <xmlvalidate warn="false">
      <xmlcatalog>
        <dtd publicId="${DOCBOOK_PUBLIC_ID}"
             location="${DOCBOOK_DTD}"/>
      </xmlcatalog>
      <fileset dir="${SRC}">
        <include name="*.xml"/>
      </fileset>
    </xmlvalidate>
    <xslt basedir="${SRC}"
          destdir="${BUILD}"
          style="${DOCBOOK_XSL}"
          extension=".html"
          includes="*.xml">
      <classpath>
        <pathelement location="${SAXON_LOC}"/>
      </classpath>
      <factory name="net.sf.saxon.TransformerFactoryImpl"/>
      <xmlcatalog>
        <dtd publicId="${DOCBOOK_PUBLIC_ID}"
             location="${DOCBOOK_DTD}"/>
      </xmlcatalog>
    </xslt>
  </target>

  <target name="clean">
    <delete dir="${BUILD}"/>
  </target>
</project>
<xslt> の中で <factory name="net.sf.saxon.TransformerFactoryImpl"/> を指定していないと TraXLiaison を使用してエラーとなる。明示的に SAXON を使うために factory name で指定しておくこと。
$ ant -verbose
Apache Ant(TM) version 1.8.2 compiled on February 10 2011
Trying the default build file: build.xml
Buildfile: /home/user/Develop/docbook/saxonTest/antTest/build.xml
(略)
[xmlvalidate] 2 file(s) have been successfully validated.
     [xslt] Using class org.apache.tools.ant.taskdefs.optional.TraXLiaison
     [xslt] Transforming into /home/user/Develop/docbook/saxonTest/antTest/build
     [xslt] Processing /home/user/Develop/docbook/saxonTest/antTest/src/hello.xml to /home/user/Develop/docbook/saxonTest/antTest/build/hello.html
     [xslt] Loading stylesheet /usr/share/sgml/docbook/xsl-stylesheets/xhtml/docbook.xsl
Apache resolver library not found, internal resolver will be used
     [xslt] : Warning! file:/usr/share/sgml/docbook/xsl-stylesheets/xhtml/autoidx.xsl: line 502: 属性 'href' がエレメントの外側です。
(略)
     [xslt] : Error! null
     [xslt] Failed to process null

BUILD FAILED

[Saxon]XML, XSLT ファイルの関係

変換元 XML ファイル ---->  XSLT Processor -----> 変換先 XML 文章
    (test.xml)             (SAXON)               (test.html)
                              |
                              |
                      XSLT スタイルシート
                          (test.xsl)

[CakePHP]Controller 内でのデバッグ

Controller 内に直接 debug() 関数を埋め込めば値の表示が可能。
<?php

class UsersController extends AppController
{
  var $name = 'Users';

  function index() {
    $users = $this->Users->find('all');
    foreach ($users as $user) {
      debug($user['username'], $showHTML=true);
    }
  }
}

?>

[CakePHP]Controller から複数の Model を使用する

controller 定義内で $uses を用いて使用する Model を指定する
<?php

class UsersController extends AppController
{
  var $name = 'Users';
  var $uses = array('User', 'Profile');

  function index() {
    $users = $this->Users->find('all');
    $profiles = $this->Profile->find('all');
  }
}

?>

[CakePHP]ORDER BY

順序を指定してデータを取り出す
$conditions = array('date >' => '2000-01-01');
$order = 'date';
$scores = $this->Score->find('all', array('conditions' => $conditions, 'order' => $order));

[CakePHP]CkaePHP App::import() の返値

必要なPluginを app/venders の下に置く
$ret = App:import('Vendor', 'geshi/geshi');
var_dump($ret);
として返値を見ることでロードが正常にできているか確認できる。

[CakePHP]add フォームを追加できるページ

/app/views/exams/multi_add.ctp を準備し、<body> 部に以下を記述する。
<div id="add">
</div>
<a href="/php/cake/exams/add" id="link1262083738" onclick=" event.returnValue = false; return false;">Add exam score</a>
<script type="text/javascript">
//<![CDATA[
Event.observe('link1262083738', 'click', function(event) {
 new Ajax.Updater('add','/php/cake/exams/add', {
  asynchronous:true,
  evalScripts:true,
  insertion: Insertion.Top,
  requestHeaders:['X-Update', 'add']
  })
 }, false);
//]]>
</script>
通常は ajax ヘルパーの $ajax->link() を使用すれば add.ctp を <div id="add"> に追加表示することができるが、そのままでは 1 つ分のフォームしか表示できないので自前で Ajax.Updater を書き、オプションに insertion: Insertion.Top を追加することでリンクをクリックする度にフォームが追加されるようにしてみた。

[CakePHP]データ追加ページ

/app/views/exams/add.ctp というページを準備し、<body> 部に以下を記述する。
<?php
echo $form->create('Exam');
echo $form->input('user_id');
echo $form->input('date');
echo $form->input('math');
echo $form->input('english');
echo $form->input('physics');
echo $form->end('Save');
?>
/app/controllers/exams_controller.php を準備し、以下を記述する。
<?
class ExamsController extends AppController
{
 var $name = 'Exams';
 var $uses = array('User', 'Exam');
 var $helpers = array('Html', 'Javascript', 'Ajax');

 function index() {
  $this->set('exams', $this->Exam->find('all'));
 }

 function add() {
  $fields = 'username';
  $users = $this->Exam->User->find('list', array('fields' => $fields));
  $this->set('users', $users);
  if (!empty($this->data)) {
   debug($this->data);

   if ($this->Exam->save($this->data)) {
    $this->flash('Your post has been saved.' , '/examss');
   }
  }
 }
}
?>
$users を view の add.ctp に渡してやることで user_id の部分を user テーブルにある username と紐付けて表示することができる。

[CakePHP]App::import の注意点

モジュール名はすべて小文字で書かないと読み込んでもらえない。
ファイルの実体が app/venders/pcahrt/pData.php であっても pchart/pdata で import しなければならない。
App::import('Vendor', 'pchart/pdata');
App::import('Vendor', 'pchart/pchart');

[CakePHP]Database

Cache を利用して DB へのアクセスを減らす
Table: exams テーブル
iduser_idmathenglishphysics
11493656
22454842
33728091
上記の exams テーブルにアクセスして表を作成し、さらにそのデータから JpGraph でグラフを作成する場合 ExamsController に表を作成するための関数をグラフを作成するための関数を準備する必要がある。
function exam_total() {
 $users = $this->User->find('all');
 foreach ($users as $user) {
  $total[$user['User']['id']] = 0;
  $total[$user['User']['id']] = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];
 }
 $this->set('users', $users);
 $this->set('total', $total);
 $this->set('graph_path', './exam_total_graph');
}

function exam_total_graph() {
 /* JpGraph を使用する */
 App::import('Vendor', 'jpgraph/jpgraph');
 App::import('Vendor', 'jpgraph/jpgraph_bar');

 /* DB から値を取得 */
 $users = $this->User->find('all');

 $y1data = array();
 $y2data = array();
 $zerodata = array();

 $a = array();

 /* 合計計算 */
 foreach ($users as $user) {
  $total = 0;
  $total = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];

  array_push($y1data, $user['Exam']['math']);
  array_push($y2data, $total);
  array_push($zerodata, 0);
  array_push($a, $user['User']['username']);
 }

 /* グラフ作成 */
 $graph = new Graph(350, 250, "auto");
 $graph->SetScale("textlin", 0, 100);
 $graph->SetY2Scale("lin", 0, 300);
 /* 右側の Y 軸で値が全部表示できないのでグラフを表示する場所の
  * margin を指定する
  */
 $graph->img->SetMargin(30, 30, 30, 30);

 /* X軸項目追加 */
 $graph->xaxis->SetTickLabels($a);

 /* plot作成 */
 $bplot1 = new BarPlot($y1data);
 $bplot1->value->Show();
 $bplot1->value->SetFormat('%d');

 $bplot2 = new BarPlot($y2data);
 $bplot2->value->Show();
 $bplot2->value->SetFormat('%d');

 /* 単純に bplot1, bplot2 を表示するとグラフが重なってしまうので
  * $zerodata のダミーを間に挟んでグループ化して
  * bplot1, bplot2 が並んでいるように表示する
  */
 $bplotzero = new BarPlot($zerodata);
 $bgplot1 = new GroupBarPlot(array($bplot1, $bplotzero));
 $bgplot2 = new GroupBarPlot(array($bplotzero, $bplot2));

 /* グラフ上に描画 */
 $graph->Add($bgplot1);
 $graph->AddY2($bgplot2);

 /* グラフ表示 */
 $graph->Stroke();
}
この中で DB にアクセスして値を格納し、各人の合計得点を計算する箇所が重複している
$users = $this->User->find('all');
foreach ($users as $user) {
  $total[$user['User']['id']] = 0;
  $total[$user['User']['id']] = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];
}
Cache 機能を使うことで DB へのアクセスを減らすことが可能となる。
Cache::read($key, $config = null);
Cache::write($key, $value, $config = null);
Cache::delete($key, $config = null);
  • write() で $key に入力した文字列に $value の値を関連付けて保存する。
  • read() で $key に関連付けられた値を読み込む。
  • delete() で $key の値を cache から削除する。
$config は Cache 機能の設定ファイルを指定する。null の場合はデフォルト設定が使用される。
function exam_total() {
 $users = $this->User->find('all');

 foreach ($users as $user) {
  $total[$user['User']['id']] = 0;
  $total[$user['User']['id']] = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];
 }

 $this->set('users', $users);
 $this->set('total', $total);
 Cache::write('users', $users);
 Cache::write('total', $total);
}

function exam_total_graph() {
 /* JpGraph を使用する */
 App::import('Vendor', 'jpgraph/jpgraph');
 App::import('Vendor', 'jpgraph/jpgraph_bar');

 /* Cache に保存された値を読み込む */
 $users = Cache::read('users');
 $total = Cache::read('total');

 Cache::delete('users');
 Cache::delete('total');

 $y1data = array();
 $y2data = array();
 $zerodata = array();
 $a = array();

 foreach ($users as $user) {
  array_push($y1data, $user['Exam']['math']);
  array_push($y2data, $total[$user['User']['id']]);
  array_push($zerodata, 0);
  array_push($a, $user['User']['username']);
 }

 (以下略)
  • exam_total() の最後で $users, $total を Cache に保存しておき、exam_total() の後に呼び出される exam_total_graph() では cache のデータを利用するように変更して DB へのアクセス回数を減らすことができる。
  • Cache::write() により app/tmp/cache 以下に cake_total, cake_users というファイルが生成される。これを exam_total_graph() 関数で Cache::read() により読み出し、読み出し後は Cache::delete() で削除する。