Questetra における EL 式を活用したさまざまな文字列操作・数値処理・日付処理の手法を紹介します。単一行/複数行の文字列からの部分抽出や条件抽出、データ変換・情報取得、さらには数値や日付の整形・演算などの豊富なサンプルとともに紹介します。
基本的な EL 式の書き方については 「R2272: EL式による文字列としての出力(データ設定式)(初級編)」 を、 SpEL の詳細な仕様については SpELのリファレンス をご覧ください。
*活用シーン
- [データ更新]での文字列変換
- [メッセージ送信中間イベント(メール)]でのメール本文の動的な生成
- [分岐 XOR ゲートウェイ]、[分岐 OR ゲートウェイ]での条件設定
*操作カテゴリ
1. 操作で用いる演算子
SpEL式で高度な操作を記述するにあたり、よく利用する演算子について簡単に紹介します。詳細については、SpEL の演算子についてのリファレンスをご覧下さい。
1.1 論理演算子
&&(AND)や ||(OR)を用いて複数の条件を組み合わせられます。
例:contains("error") && length() >= 8
1.2 比較演算子
<=(以下または等しい)、==(等しい)、>=(以上または等しい)、!=(等しくない) などの演算子があります。
例:#q_string1 == #q_string2 や #q_string1 != #q_string2
1.3 セーフナビゲーション演算子
?. を使うと、入力値が null の場合でもエラーを起こさず、空文字や未出力として扱えます。 そのため安全に参照できます。文字型だけでなく、数値型や日付型に対しても同様に使用できます。
サンプル式
#{#q_stringExample?.toUpperCase()}入力例1
hello
出力例1
HELLO
入力例2
出力例2
未入力の場合にエラーとなりません。
1.4 選択と射影
SpEL ではリストなどのコレクションに対して、「選択」 .? と「射影」 .! の操作が可能です。 選択はコレクションから条件に合う要素だけを抽出した新たなコレクションを作る操作、射影はコレクションの各要素を変換した新たなコレクションを作る操作です。
{1, 2, 3, 4}.?[#this % 2 == 0] // 選択 = {2, 4}
{1, 2, 3, 4}.![#this * 2] // 射影 = {2, 4, 6, 8}
上記の例では、#this は {...} で作ったリストの各要素を指します。
また、?.^[条件] は最初に合致する要素のみ、?.$[条件] は最後に合致する要素のみ取り出す特殊な選択です。
{3, 5, 8, 6, 10}.^[#this > 5] // 最初に合致する要素は {8}
{3, 5, 8, 6, 10}.$[#this > 5] // 最後に合致する要素は {10}
1.5 三項演算子
? : 演算子を使うことで、条件分岐を簡潔に記述できます。
サンプル式
#{#q_numExample > 100 ? "large" : "small or equal"}入力例1
120
出力例1
large
入力例2
100
出力例2
small or equal
2. 文字列の操作(単一行/複数行)
「単一行」および「複数行」の文字型データを操作するEL式を紹介します。
文字型データ(複数行)については、行ごとに(改行文字を区切りとして)リストの要素へと分解し、各行に対して操作を行います。その後、改行文字を挿入して再結合を行います。
2.1 文字列の一部抽出
指定文字以降を抽出
文字型データ内で、指定した文字列(以下のサンプルでは apple )を探し、最初に出現する指定文字列( apple )以降の文字列を抽出します。文字型データ前方にある不要な文字列を省く場合に便利です。
サンプル式
#{#q_stringExample?.substring(#q_stringExample?.indexOf("apple"))}入力例
banana,apple,orange,apple,grape
出力例
apple,orange,apple,grape
指定文字の直前までを抽出
文字型データ内で、指定した文字列(以下のサンプルではカンマ)を探し、最後に出現する指定文字列(カンマ)の直前までの文字列を抽出します。文字型データ後方の不要な文字列を省く場合に便利です。
サンプル式
#{#q_stringExample?.substring(0, #q_stringExample?.lastIndexOf(","))}入力例
apple,orange,banana
出力例
apple,orange
先頭から指定範囲を抽出
文字型データ(複数行)に対して、各行の先頭から指定した文字数分の文字列を抽出します。
サンプル式
#{#joiner.join(#q_stringExample?.split(#NL)?.![substring(0,7)], #NL)}入力例
123456777 234567777 345677777
出力例
1234567 2345677 3456777
各行から指定文字列より後を抽出
文字型データ(複数行)の各行 から指定した文字列(以下のサンプルでは @ ) より後の文字列を抽出します。
サンプル式
#{#joiner.join(#q_stringExample?.split(#NL)?.![replaceFirst("^[^@]+@", "")], #NL)}入力例
anderson@sub.example.com bohr@mail.example.org curie@service.example.net dirac@secure.example.com einstein@dev.portal.example.org feynman@monitor.example.net
出力例
sub.example.com mail.example.org service.example.net secure.example.com dev.portal.example.org monitor.example.net
2.2 指定行の抽出
指定文字を含む行のみ抽出
指定した文字列(以下のサンプルでは error )を含む行のみを抽出します。
サンプル式
#{#joiner.join(#q_stringExample?.split(#NL)?.?[contains("error")], #NL)}入力例
error:1 OK:2 error:3 debug:4
出力例
error:1 error:3
空行を除去
文字数0の行(空行)を除外します。ログなどで混入した不要な空行を取り除きたい場合に便利です。
サンプル式
#{#joiner.join(#q_stringExample?.split(#NL)?.?[length() != 0], #NL)}入力例
line1 line2 line3
出力例
line1 line2 line3
最初に条件に該当する行を抽出
条件に合う行の内、最初に出現する行を抽出します。行の文字数などを判定して、一致した行だけを取り出す際に便利です。
サンプル式
#{#joiner.join(#q_stringExample?.split(#NL)?.^[length() >= 5], #NL)}入力例
123 12345 abcde 999999 abcd
出力例
12345
最後に該当する行を抽出
条件に合う行の内、最後に出現する行のみを抽出します。 行の文字数などを判定して、一致した一行だけを取り出す際に便利です。
サンプル式
#{#joiner.join(#q_stringExample?.split(#NL)?.$[length() >= 5], #NL)}入力例
123 12345 abcde 999999 abcd
出力例
999999
行の先頭および末尾が条件に合う行を抽出
指定した一つ目の文字列(以下のサンプルでは prefix )で開始し、指定した二つ目の文字列(以下のサンプルでは suffix )で終了する行だけを取り出します。
サンプル式
#{#joiner.join(#q_stringExample?.split(#NL)?.?[startsWith('prefix') || endsWith('suffix')], #NL)}入力例
prefix-abc some text suffix prefix and suffix middle line endswith suffix prefix
出力例
prefix-abc some text suffix prefix and suffix endswith suffix prefix
正規表現に合致する行を抽出
正規表現で、指定した形式に合致する行を抽出します。郵便番号や電話番号などの定型の情報を抽出するのに便利です。
サンプル式
#{#joiner.join(#q_stringExample?.split(#NL)?.?[matches('[0-9]{3}-[0-9]{4}')], #NL)}入力例
602-8043 6028043 ***-**** 602-80-43
出力例
602-8043
条件に当てはまる行を抽出した上で、指定文字より後を抽出
文字型データ(複数行)内で、指定した文字列(以下のサンプルでは @ )を含む行のみを抽出します。そして、各行から指定した文字列(以下のサンプルでは @ ) より後の文字列を抽出します。
サンプル式
#{#joiner.join(#q_stringSample?.split(#NL)?.?[contains("@")]?.![ replaceFirst("^[^@]+@", "") ], #NL)}入力例
anderson@sub.example.net bohr@mail.example.org mail.example curie@service.example.net
出力例
sub.example.net mail.example.org service.example.net
条件に当てはまる行を抽出した上で、指定文字直前までを抽出
文字型データ(複数行)内で、指定した文字列(以下のサンプルでは自社メールアドレス @mycompany.example.com )以外の行を抽出します。そして、指定した文字列(以下のサンプルでは @ )の直前までの文字列を抽出します。
サンプル式
#{#joiner.join(#q_stringSample?.split(#NL)?.?[!contains("@mycompany.example.com")]?.![ replaceFirst("@.*$", "") ], #NL)}入力例
alice@mycompany.example.com anderson@sub.example.net bohr@mycompany.example.com curie@service.example.net einstein@dev.portal.example.org
出力例
anderson curie einstein
2.3 文字列の一部置換
複数行文字列の置換
文字列に対して、指定した一つ目の文字列(以下のサンプルでは apple )が出現する全ての箇所を、指定した二つ目の文字列(以下のサンプルでは banana )で置き換えます。
サンプル式
#{#joiner.join(#q_stringExample?.split(#NL)?.![ replaceAll("apple","banana") ], #NL)}入力例
apple,orange,apple melon,apple
出力例
banana,orange,banana melon,banana
2.4 文字列情報の取得
文字数を取得
文字型データの文字数を取得します。 変換前後でどのくらい変化したかを調べるのに便利です。
サンプル式
#{#q_stringExample?.length}入力例
hello
出力例
5
複数行の行数を取得
文字型(複数行)データの行数を取得します。 空行も含まれる点に注意してください。
サンプル式
#{#q_stringExample?.split(#NL)?.length}入力例
line1 line2 line3
出力例
3
2.5 文字列を指定フォーマットに加工して出力
文字列に接頭文字・接尾文字付与
文字型(複数行)データの各行に共通の接頭文字や接尾文字を付与するサンプルです。リスト表示や HTML 表示に適した形式へ整形する際に活用できます。
サンプル式 1
#{#joiner.splitJoin(#q_stringExample, '<br>')}入力例
apple orange banana strawberry
出力例
apple<br>orange<br>banana<br>strawberry
サンプル式 2
#{#joiner.splitJoin(#q_string_multiple, '<li>', '</li>')}入力例
apple orange banana strawberry
出力例
<li>apple</li><li>orange</li><li>banana</li><li>strawberry</li>
サンプル式 3
#{#joiner.splitJoin(#q_string_multiple, '<li>', '</li>', #NL)} 入力例
apple orange banana strawberry
出力例
<li>apple</li> <li>orange</li> <li>banana</li> <li>strawberry</li>
XML形式への変換
複数行の文字列を <item> タグ形式にまとめるサンプルです。
行ごとに改行文字で分割し、それぞれの行に対して文字列を属性として<item>タグに組み込み、最後に改行文字を入れて再結合することで XML を動的に生成します。
サンプル式
<items>
#{#joiner.join(#q_stringExample?.split(#NL).![#this + '"display="' + #this], ' <item value= '',''/> ', #NL)}
</items>入力例
apple orange banana strawberry
出力例
<items> <item value="apple" display="apple"/> <item value="orange" display="orange"/> <item value="banana" display="banana"/> <item value="strawberry" display="strawberry"/> </items>
HTML形式への変換
Markdownテキストから HTML テキストに変換して出力するサンプルです。Markdown構文により簡潔に整えられた文書を、表やリストなどのHTMLとして動的に整形・表示できます。
サンプル式
#{#markdown.toHtml(#q_markdown_data)}入力例
| 商品名 | 価格 | 在庫 | |:---------|:----:|-----:| | ノート | ¥500 | 10 | | ペン | ¥100 | 50 | | 消しゴム | ¥150 | 30 |
出力例
<table> <thead> <tr> <th align="left">商品名</th> <th align="center">価格</th> <th align="right">在庫</th> </tr> </thead> <tbody> <tr> <td align="left">ノート</td> <td align="center">¥500</td> <td align="right">10</td> </tr> <tr> <td align="left">ペン</td> <td align="center">¥100</td> <td align="right">50</td> </tr> <tr> <td align="left">消しゴム</td> <td align="center">¥150</td> <td align="right">30</td> </tr> </tbody> </table>
エスケープされた文字列への変換
HTML、XML、JavaScript、JSON、Markdown などの形式で使用するために、特殊文字をエスケープされた文字列に変換するサンプルです。コードの安全な埋め込みや外部連携時のフォーマット調整するのに便利です。
サンプル式 1 (JavaScript エスケープされた文字列)
#{#escaper.escapeEcmaScript(#q_script_data)} "#escapeEcmaScript()" としても、 "#escaper.escapeEcmaScript()" と同様に動作します。
入力例
let greet = (name) => {
return “Congratulations! " + name;
};
console.log(greet(“Tom”)); // “Congratulations! Tom”出力例
let greet = (name) => {\nreturn \u201CCongratulations! \u201D + name;\n};\nconsole.log(greet(\u201CTom\u201D)); \/\/ \u201CCongratulations! Tom\u201Dサンプル式 2 (Json エスケープされた文字列)
#{#escaper.escapeJson(#q_json_data)} 入力例
[
{"Id" : "101", "Country" : "United Kingdom", "Currency" : "Pound"},
{"Id" : "102", "Country" : "Germany", "Currency" : "Euro"},
{"Id" : "103", "Country" : "Japan", "Currency" : "Yen"}
]出力例
[\n{\"Id\" : \"101\", \"Country\" : \"United Kingdom\", \"Currency\" : \"Pound\"},\n{\"Id\" : \"102\", \"Country\" : \"Germany\", \"Currency\" : \"Euro\"},\n{\"Id\" : \"103\", \"Country\" : \"Japan\", \"Currency\" : \"Yen\"}\n]サンプル式 3 (XML エスケープされた文字列)
#{#escaper.escapeXml(#q_xml_data)}"#escapeXml()" としても、 "#escaper.escapeXml()" と同様に動作します。
入力例
<continent name="Europe"> <country name="UK" language="English"> <name lang="EN">United Kingdom</name> <name lang="JA">英国</name> <currency>GBP</currency> </country> <country name="Germany" language="German"> <name lang="EN">Germany</name> <name lang="JA">ドイツ</name> <currency>EUR</currency> </country> </continent>
出力例
<continent name="Europe"> <country name="UK" language="English"> <name lang="EN">United Kingdom</name> <name lang="JA">英国</name> <currency>GBP</currency> </country> <country name="Germany" language="German"> <name lang="EN">Germany</name> <name lang="JA">ドイツ</name> <currency>EUR</currency> </country> </continent>
サンプル式 4 (HTML エスケープされた文字列)
#{#escaper.escapeHtml(#q_html_data)}入力例
<body> <h1>これは見出しです</h1> <p class="intro">これは段落です</p> <div class="section"> <h2>これは小見出しです</h2> <p>これはURLです</p> <p>https://example.com/search?query=apple&sort=asc</p> </div> </body>
出力例
<body> <h1>これは見出しです</h1> <p class="intro">これは段落です</p> <div class="section"> <h2>これは小見出しです</h2> <p>これはURLです</p> <p>https://example.com/search?query=apple&amp;sort=asc</p> </div> </body>
サンプル式 5 (Markdown エスケープされた文字列)
#{#escaper.escapeMarkdown(#q_markdown_data)}"#markdown.escape()" としても、 "#escaper.escapeMarkdown()" と同様に動作します。
入力例
| 商品名 | 価格 | 在庫 | |:---------|:----:|-----:| | ノート | ¥500 | 10 | | ペン | ¥100 | 50 | | 消しゴム | ¥150 | 30 |
出力例
| 商品名 | 価格 | 在庫 | |:---------|:----:|-----:| | ノート | ¥500 | 10 | | ペン | ¥100 | 50 | | 消しゴム | ¥150 | 30 |
ハッシュ文字列への変換
ハッシュ関数を用いて、特定の文字列から固定長のハッシュ値を生成するサンプルです。識別用IDの生成やデータ改ざん検知などに活用できます。
サンプル式
#{#sha256(processInstanceTitle)}入力例
作業依頼フロー
出力例
fd10a603dd04a136032a81248e28bcad7d4ac19e39a77cfadd52dae6d04076c6
2.6 文字列生成
ランダム文字列生成
指定した長さのランダムな英数字文字列(0-9a-zA-Z)を生成するサンプルです。パスワードや一意の識別子を自動生成したい場合に便利です。
サンプル式
#{#randomString(12)}出力例
pJBAzTDft8wT
2.7 ほかのデータ型を文字列として出力
選択型を文字列として出力
チェックボックスや選択リストの選択値(表示ラベルやID)を文字列として整形・出力するサンプルです。改行やHTMLタグで区切って可視化する際に便利です。
サンプル式 1(選択項目の表示ラベルを出力)
#{#joiner.join(#q_select_check, '<br>')}入力例
出力例
apple<br>orange<br>banana
サンプル式 2(選択項目のIDと表示ラベルを整形して出力)
#{#joiner.join(#q_select_check?.![value + ':' + display], '<li>', '</li>')}入力例
出力例
<li>1:apple</li><li>2:orange</li><li>3:banana</li>
サンプル式 3(選択項目のIDと表示ラベルをHTML形式で出力)
#{#joiner.join(#q_select_check, '<li>', '</li>', '<br>')}入力例
出力例
<li>1:apple</li><br><li>2:orange</li><br><li>3:banana</li>
テーブル型を文字列として出力
テーブル型データを文字列にまとめるサンプルです。
それぞれの行の値を抽出し、属性として縦棒と組み込み、最後に改行文字を入れて再結合することで整形された文字列を動的に生成します。帳票出力やログ出力への活用が可能です。テーブル型データ項目の詳細な仕様についてはテーブル型をご覧ください。
サンプル式 1
#{#joiner.join(#q_table?.rows?.![#this['name'] + '|' + #this['price'] ],#NL)}入力例
出力例
リンゴ|100 みかん|200
サンプル式 2
#{#joiner.join(#q_table?.rows?.!['交通費 : ' + #joiner.join(cols, ' | ')],#NL)}入力例
出力例
交通費:タクシー | 4300 | キャッシュ 交通費:飛行機 | 15000 | クレジットカード
3. 数値の整形と演算
#sformat() と記述することで、java.lang.String の format() メソッドを使用できます。これにより、数値型データを整形し、文字列として出力できます。また、「書式指定子」(フォーマット指定子)を使用することで、さまざまな形式に整形して出力できます。 基本的な指定方法は、 {パディング文字}{文字列全体の表示幅}.{小数点以下の表示幅}f です。 幅揃え文字(パディング文字)を指定すれば、"文字列全体の表示幅" に満たない出力桁数となる場合に、パディング文字が挿入されます。
数値データ(引数)が processInstanceId や processInstanceSequenceNumber といった整数型で固定されている形式の場合は、conversion文字は f ではなく d となり、基本的な指定方法は {文字列全体の表示幅}d となります。
小数点出力等の書式については、基盤のロケール設定に依存します:
https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/util/Formatter.html
3.1 数値の書式指定
EL 式を使って数値をさまざまな形式に整形するサンプルです。符号を付ける、桁数を固定するなど、用途に合わせて柔軟に設定できます。
符号の表示・小数点の指定
プラス/マイナスを必ず表示し、小数点以下を指定桁数に丸めるサンプルです。下記の例では、小数第2位まで表示し、常に符号(+/-)を付けています。
サンプル式
#{#sformat("%+.2f",#q_numExample)}入力例
3.14159
出力例
+3.14
ブランクパディング
出力の最小幅を指定し、必要に応じて空白で桁揃えを行います。下記のサンプルでは、小数点以下を表示せず、整数部のみを表示しています。桁を揃えて見やすく表示したい場合に活用できます。
サンプル式
JPY #{#sformat("% 4.0f",#q_numExample)}入力例 1
123456.78
出力例 1
JPY 123457
入力例 2
-1.234
出力例 2
JPY -1
桁区切り文字の挿入
数値にカンマ区切り(3桁ごと)を付与し、金額などの読みやすさを向上させたい場合に便利です。
サンプル式
JPY #{#sformat("%,4.0f", #q_numExample)}入力例 1
123456.78
出力例 1
JPY 123,457
入力例 2
1
出力例 2
JPY 1
ゼロパディング
出力文字数を固定し、足りない桁を先頭にゼロで補完します。
サンプル式
INVOICE-#{#sformat("%04.0f", #q_numExample)}入力例 1
123456.78
出力例 1
INVOICE-123457
入力例 2
1
出力例 2
INVOICE-0001
3.2 数値の演算
数値の四捨五入
指定桁数で数値を四捨五入するサンプルです。ここでは小数第2位まで表示するように設定し、マイナス符号の表示や小数点以下の整形を行っています。
サンプル式
#{#sformat("%.2f", #q_numExample)}入力例
-1.234
出力例
-1.23
数値の切り捨て
数値を厳密ではなく簡易的に丸める/切り捨てる方法のサンプルです。指定した数値型データが負なら 0.005 を加算し、正なら 0.005 を減算してから 小数第2位までの表記へ整形します。 厳密な切り捨てではありませんが、ざっくりと小数を丸めて表示したい場合に使えます。
サンプル式
#{#q_numExample < 0 ? #sformat("%.2f", (#q_numExample + 0.005)) : #sformat("%.2f", (#q_numExample - 0.005))}入力例
-1.789
出力例
-1.78
4. 日付/日時データの整形と比較操作
#dateFormatter と記述すると、 com.questetra.bpms.core.event.scripttask.DateFormatWrapper を使用できます。これにより、日付/日時データを変換、整形できます。#format() とすることで、java.text.SimpleDateFormat の format() メソッドの使用も可能です。
https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/text/SimpleDateFormat.html
4.1 日付/日時データの整形
日付型/日時型データを指定した書式の文字列に変換します。
yyyy年MM月dd日 への変換
サンプル式
#{#dateFormatter.format("yyyy年MM月dd日", #q_date)}入力例
2025-02-18
出力例
2025年02月18日
タイムゾーンを明記した日時の出力
日時データを特定のタイムゾーンに基づいて整形するサンプルです。時差を含んだ日時の表示や、他の地域と調整したい場合に便利です。
サンプル式 1
日時データを整形し、ワークフロー基盤のタイムゾーン情報を付加して表示するサンプルです。他の国や国際機関に連絡する際に便利です。
#{#dateFormatter.format('yyyy-MM-dd HH:mmz', #q_datetime)}入力例
2021-04-12 09:45
出力例
2021-04-12 09:45+0900
サンプル式 2
日時データを、ワークフロー基盤のタイムゾーンでの日時から、指定したタイムゾーンの日時に変換・整形し、タイムゾーン情報を付加して表示するサンプルです。特定の国に連絡する際に便利です。
#{#dateFormatter.format('GMT-0900', 'yyyy年MM月dd日 HH時mm分z', #q_datetime)}入力例
2021-04-12 09:45
出力例
2021年04月11日 15時45分-0900
4.2 日付の比較
文字型で記述された2つの日付を日付型に変換して比較し、どちらが先の日付か判定します。 文字型のままでは < や > は使えないため、必ず日付型にしてから比較してください。
2つの日付の前後判定
サンプル式
#{#dateFormatter.parse("yyyy-MM-dd", #q_date1) < #dateFormatter.parse("yyyy-MM-dd", #q_date2) ? "date1が前" : "date1が後または同日"}入力例(q_DateExample1)
2025-01-01
入力例(q_DateExample2)
2025-02-01
出力例
Date1が前
日付の整形と日付の比較との組合せ
2つの日付を比較し、古い方の日付を yyyy年MM月dd日 の形式に変換して出力します。
サンプル式
#{#dateFormatter.parse("yyyy-MM-dd", #q_date1) < #dateFormatter.parse("yyyy-MM-dd", #q_date2) ? #dateFormatter.format("yyyy年MM月dd日", #q_date1) : #dateFormatter.format("yyyy年MM月dd日", #q_date2)}入力例(q_DateExample1)
1998-07-24
入力例(q_DateExample2)
1996-06-23
出力例
1996年06月23日
4.3 日時の差の計算
2つの日時型データの差を計算します。
時間(Hour)単位で出力
2つの日時の差を計算し、その結果を時間(Hour)単位の文字列として出力します。以下のサンプル式では、小数第2位まで出力します。
サンプル式
#{#sformat("%.2f", (#q_TimeExample2.getTime() - #q_TimeExample1.getTime()) / 3600000.0)}入力例(q_TimeExample1)
2025-09-03 09:15
入力例(q_TimeExample2)
2025-09-03 17:30
出力例
8.25
コメント
0件のコメント
サインインしてコメントを残してください。