XSLファイルを使って、SpringMVCでCSV出力をおこなう方法

SpringFrameWork

WEBアプリケーションにおいて、サーバでCSVを作成して、クライアント(ブラウザ)にダウンロードする、といった要件は頻繁に発生します。


SpringMVCでXSLファイルを上手に使えば、簡単にCSVファイルの作成とダウンロードの機能を作成することができます。


今回は、SpringMVCでCSV出力をおこなう方法を紹介します。
Javaで自力でゴリゴリ作成する方法ではなく、XSLファイルを使ってCSV出力おこなう方法となります。


XSLファイルとは、XMLファイルのスタイルを定義しているファイルになります。
出力するCSVファイルのレイアウトをXSLファイルに定義してあらかじめサーバ上に格納しておき、CSVファイルを出力する際に使用します。


XSLファイルとは何か?


XSL(eXtensible Style Language)ファイルは、XML 文書を他の文書タイプに変換したり、出力をフォーマットする際に使用できるスタイルシートです。
Styleという言葉が使われていることからもわかるように、XMLのスタイルシートがXSLになります。


このXSLファイルで便利なのが、テンプレート関数というちょっとしたロジックをXSLファイル内で使用することができる点です。
例えば、以下のような関数です。


  • テンプレート関数の定義の仕方(xsl:template、xsl:param)
  • 引数の値の参照の仕方($引数名)
  • 条件分けの仕方(xsl:if、xsl:choose)
  • XSLT関数(not、contains、substring-before、substring-after)
  • XSLT関数の使い方(<xsl:value-of select=”XSLT関数 (引数…)” />)
  • 定義されたテンプレート関数の呼び出し方(xsl:call-template、xsl:with-param:再帰呼び出しの箇所)

上記のような関数もあらかじめXSLファイル内に定義することができます。


以下に、よく使う関数を紹介していきます。


文字列の連結


concat(str1,str2,str3,・・・)
str1、str2、str3、を連結


文字列の調査


contains(str, substr)
strの中のsubstrを検索。
存在する場合はtrueを通知


数字のフォーマッティング


format-number(number, format)
format-number(number, format, formatType)
numberの数字を、formatで指定されたフォーマットに変換して出力します。


空白の除去


normalize-space(str)
strから空白を除外した文字列を返却します


先頭文字のチェック


starts-with(str, substr)
strがsubstrで始まっているかをチェックします。
始まっている場合はtrueを通知。


文字列への変換


string(val)
valを文字列に変換します。


文字列の長さを取得


string-length(str)
strの長友を取得します。


文字列の抜き出し


substring(str, start)
substring(str, start, length)
strに対して、start位置からlengthの長さの文字列を取得します。


文字列の抜き出し(前文字列の取得)


substring-before(str, substr)
strからsubstrの文字列を検索し、見つかったらその前の文字列を取得します。


substring-after(後文字列の取得)


substring-after(str, substr)
strからsubstrの文字列を検索し、見つかったらその後の文字列を取得します。


文字列の置換


translate(str, src, dest)
strに含まれるsrcという文字列をdestに変換します。


切り上げ


ceiling(val)
valの切り上げをおこないます。


ノード数の取得


count(node)
XML内に含まれるnodeで指定されたノードの数を取得します。

<a>
  <b></b>
  <b></b>
</a>

この例で、’b’のノード数は2です。


切り下げ


floor(val)
valの切り下げをおこないます。


数値に変換


number(any)
anyを数値に変換します。


四捨五入


round(val)
valを四捨五入します。


加算


sum(node)
nodeで指定されている値を加算し、数値で返却します。


<a>
    <b>10</b>
    <b>10</b>
</a>

sum(‘b’)の返却値は20です。


現在のノード取得


current()
現在位置のノードを取得します。


現在のノードの最下層ノードを取得


last()


nodeのローカル名(名前空間を外したもの)を取得


local-name(node)


現在のノード名を取得


name()


現在のノードの名前空間URIを取得


namespace-uri()


現在のノード位置を数値で取得


position()


boolean型への変換


boolean(any)
anyをboolean(true or false)に変換します。


falseの出力


false()
boolean型のfalseを出力します。


trueの出力


true()
boolean型のtrueを出力します。


否定


not(boolean)
booleanの否定値をbooleanで出力します。


ドキュメントルートの取得


document(uri)
uriのドキュメントルートを出力します。


xsltで解釈できるxlstノードかを判定


element-available(str)
返り値はbooleanです。


xsltで解釈できる関数かを判定


function-available(func)


ノードに固有の値を割り当て


generate-id(node)


該当するidのノードを取得


id(any)


キー値を返却


key(str any)
str内のハッシュに、anyで指定される表現を返却します。


XSLT固有値の取得


system-property(str)
str内のXSLT固有の値を取得します。


<!entity>タグ値を取得


unparsed-entity-uri()
<!entity>タグで指定されている値を取得します。


CSV出力のサンプルソース


CSV出力のサンプルソースを紹介します。


SpringMVCのコントローラクラスに実装することを想定しています。


@RequestMapping(params = "csvOut", produces = "text/csv")
public ModelAndView makeCsvOut(HttpServletResponse response, Form form)
        throws JAXBException, IOException {

    // DBから出力する情報を取得してDTOに格納
    CsvOutDTO dto = this.service.geCsvInfo(form);

    // DTOをXMLの形式に変換
    JAXBContext context = JAXBContext.newInstance(CsvOutDTO.class);
    Writer writer = new StringWriter();
    context.createMarshaller().marshal(dto, writer);

    // モデルに変換したXMLを格納
    String xslName = "CsxXsl";
    ModelAndView modelAndView = new ModelAndView(xslName);
    modelAndView.addObject(
        "xmlSource", new StringReader(writer.toString()));

    // HTTPレスポンスヘッダを作成
    response.setHeader("Content-Disposition", 
        "attachment; filename=csvFile.csv, "UTF-8"));

    // BOMを先頭に付加
    response.getOutputStream().write(CxFix.BOM);

    return modelAndView;
}

データベースからCSV出力する内容を取得することを想定しています。
「geCsvInfo」の中身は消略していますが、このメソッドの中身がDBアクセスしてDTOのインスタンスを返却するイメージです。


その後はサンプルの通りで、DTOを「JAXBContext」に渡せば、CSVファイルの出来上がり


次にXSLファイルのサンプルです。

上記のJavaソースで”CsvXsl”という名前で定義されたXSLファイルのサンプルになります。


<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output method="text" omit-xml-declaration="yes" 
        byte-order-mark="yes" encoding="UTF-8" />
  <xsl:template match="/csvList">
    <xsl:call-template name="template_csvList" />
  </xsl:template>
    <xsl:template name="template_csvList">
        <!-- ヘッダ情報 -->
        <xsl:text>カラム1,</xsl:text>
        <xsl:text>カラム2,</xsl:text>
        <xsl:text>カラム3,</xsl:text>
        <xsl:text>
    </xsl:text>
        <!-- データ情報 -->
        <xsl:value-of
            select="translate(translate(translate(
                ./entity/col1, '"', ' '), ',', ' '), '', ' ')" />
        <xsl:text>,</xsl:text>
        <xsl:value-of
            select="translate(translate(translate(
                ./entity/col2, '"', ' '), ',', ' '), '', ' ')" />
        <xsl:text>,</xsl:text>
        <xsl:value-of
            select="translate(
                translate(translate(./entity/col3, '"', ' '), 
                ',', ' '), '', ' ')" />
        <xsl:text>,</xsl:text>
    </xsl:template>
</xsl:stylesheet>

「entity」とは、前のJavaコードに記載していた、「CsvOutDTO」で使用しているエンティティクラスです。
1行データ毎に1エンティティのレコードを保持します。


CSVファイルは1行目は各項目名の説明で、実際のデータ出力は2行目からです。
XSLファイルで2行目以降を動的にすることで、「CsvOutDTO」に格納されているエンティティの数だけCSVデータ出力がおこなわれます


関数は「translate」しか使っていません。
ダブルクオテーションと改行コードを半角スペースに変換しています。


まとめ


いかがでしたでしょうか?


SpringMVCでCSV出力をおこなう場合に、参考にしてもらえればと思います。
特に、XSLの関数は助かります。
ちょっとした処理をJavaでおこなう必要がないので。


それではまた!


Javaで動画変換をおこなう。JAVE(Java Audio Video Encoder)でMP4に!

Javeでの画像変換

今回は、Javaで動画変換をおこなう方法を紹介します。
使用するライブラリは『JAVE』です。



あんまりメジャーではないライブラリのようですね。
でも、使い方がシンプルで、かつ、世の中に出回っているほとんどの動画ファイル形式に対応しているので、筆者は気に入っています。


具体的には、『mp4』に変換することを前提にサンプルプログラムを紹介していきます。


mp4に変更するのは特に理由はないですが、あえて理由をあげるとすれば、”圧縮率が一番よさそうだから”です。


検証環境


筆者が動作検証した環境は以下になります。


  • Windows7
  • Java1.8.06
  • JAVE-1.0.2

JAVE(Java Audio Video Encoder)について


JAVE(Java Audio Video Encoder)とは何か?ということになるのですが、公式サイトの説明を日本語化すると以下になります。


JAVE(Java Audio Video Encoder)ライブラリは、ffmpegプロジェクトのJavaラッパーです。
開発者は、JAVEを利用して、オーディオファイルとビデオファイルをある形式から別の形式にトランスコードできます。
例では、AVIファイルをMPEGファイルにトランスコードでき、DivXビデオストリームを(YouTubeのような)Flash FLVファイルに変更でき、WAVオーディオファイルをMP3またはOgg Vorbisに変換できます。
オーディオトラックとビデオトラックをトランスコードする場合、ビデオのサイズを変更したり、サイズや比率を変更したりできます。
JAVEでは、他の多くの形式、コンテナ、および操作がサポートされています。


動画操作で有名なライブラリは「ffmpeg」ですが、JAVEはffmpegをラッピングしているライブラリみたいです。


説明文をみるとように、様々なファイル形式に対応しています。
ベースはffmpegなので、当然っちゃ当然ですね。


JAVEでMP4に変換する


一通りの動画について変換を試してみました。
一覧でまとめました。
動画は基本的に圧縮されます。


拡張子

mp4変換時の圧縮率

.avi

70%

.mp4

70%

.m2ts

99%

.ts

27%

.mpeg

27%

.mpg

29%

.mkv

29%

.wmv

41%

.webm

42%

.ogm

180%

.mov

96%


JAVEを使用した動画変換処理


動画変換処理のサンプルコードを紹介します。
使い方は簡単で、変換処理の条件(コーデック、ビットレート、など)を属性情報として設定し、変換処理を実行します。
様々な形式に変換が可能(っぽい)ですが、MP4形式への変換サンプルコードになります。


import it.sauronsoftware.jave.AudioAttributes;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncoderException;
import it.sauronsoftware.jave.EncodingAttributes;
import it.sauronsoftware.jave.InputFormatException;
import it.sauronsoftware.jave.VideoAttributes;
import it.sauronsoftware.jave.VideoSize;

import java.io.File;

public class JaveManage {

    private JaveManage() {
    }

    public static void main(String[] args) {
        System.out.println("start.");

        try {
            // 動画フォーマットを設定
            EncodingAttributes attrs = 
                new EncodingAttributes();

			// 動画圧縮変換時フォーマット
            attrs.setFormat("mp4");

            // 音声の変換情報を設定
            AudioAttributes audio = new AudioAttributes();
			// 動画圧縮変換時オーディオコーデック
            audio.setCodec("aac");
			// 動画圧縮変換時オーディオビットレート
            audio.setBitRate(256000);
			// 動画圧縮変換時オーディオチャンネル
            audio.setChannels(1);
            audio.setSamplingRate(88200);
			// 動画圧縮変換時オーディオサンプリングレート
            attrs.setAudioAttributes(audio);

            // 動画の変換情報を設定
            VideoAttributes video = new VideoAttributes();
			// 動画圧縮変換時ビデオコーデック
            video.setCodec("libx264");
			// 動画圧縮変換時ビデオビットレート
            video.setBitRate(2700000);
			// 動画圧縮変換時ビデオフレームレート
            video.setFrameRate(30);
			// 動画圧縮変換時ビデオ幅,動画圧縮変換時ビデオ高さ
            video.setSize(new VideoSize(1296, 768));
            attrs.setVideoAttributes(video);

            // 変換を実施
            File source = new File("source.wav");
            File dest = new File("source.mp4");
            Encoder encoder = new Encoder();
            encoder.encode(source, dest, attrs);

            // 変換結果を検証
            if (!dest.exists() || dest.length() == 0) {
                System.out.println("encode failer.");
            }
        } catch (EncoderException e) {
            System.out.println("Occured EncoderException.");
        } catch (Exception e) {
            System.out.println("Occured Exception.");
        }
        System.out.println("end.");
    }
}

設定値はソースコードに直接記述していますが、以下のパラメータを設定します。


  • オーディオビットレート:256000
  • オーディオチャンネル:1
  • サンプリングレート:88200
  • ビデオビットレート:2700000
  • フレームレート:30
  • サイズ:height:1296 width:768

まとめ


いかがでしたでしょうか?


JAVEはあんまりメジャーなライブラリではないようですね。
ググってもあんまり情報がないです。


使ってみた直観としては、使いやすい印象です。
「パラメータを設定して変換」っていうだけですからね。


皆さんが使う際に、参考にして頂ければと思います。


それではまた!