2019年12月30日月曜日

Kaleidox: Table

前回はKaleidoxの中軸となるRecordオブジェクトについて説明しました。

今回はRecordオブジェクトと同様にKaleidoxの中軸オブジェクトであるTableオブジェクトについて説明します。

Tableオブジェクトは文字通り表を記述するオブジェクトで、Recordオブジェクトの列にスキーマとヘッダ、フッタの情報を加えたものになっています。

準備

Tableをデータベース入出力で使用するための環境としてKaleidoxの初期化ファイルinit.kldに以下の設定をします。

この設定をしておくと、H2データベースのメモリデータベース上にpersonテーブルが作成され、2レコードが格納された状態になります。

* env

db.default.driver="org.h2.Driver"
db.default.url="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false"

* voucher

** person

#+caption: 特性一覧
|特性  | 名前 | 型     | 多重度 | ラベル  |
|------+------+--------+--------+---------|
| 属性 | id   | int    |      1 | User ID |
| 属性 | name | string |      1 | 名前    |
| 属性 | city | string |      ? | 市      |

* data

** person

*** x

100,Taro,Yokohama
200,Hanako,Kawasaki

* main

store-create 'person
store-insert 'person x
DATA区画

準備として用意したinit.kldでは以下のデータ区画を定義しています。

* data

** person

*** x

100,Taro,Yokohama
200,Hanako,Kawasaki

変数xにCSVで記述された表データを持つTableオブジェクトが束縛されます。

入力

Tableオブジェクトの入力方法として以下の方法について見ていきます。

  • データベース読込み
  • CSVファイル
  • LTSVファイル
  • XMLファイル
  • JSONファイル
  • HTMLファイル
データベース読込み

Kaleidoxでは、データベースアクセスの仕組みとして以下の2つを用意しています。

Store
データストア機能
SQL
SQLで直接データベースアクセス
Store

データストア機能を使うと、スキーマ定義といったメタ情報を登録することで、データベースに対してレコードベースのインタフェースでアクセスすることができます。

データストアからstore-selectで検索すると、検索結果がテーブルを記述するTableオブジェクトに格納されて返されます。

以下ではstore-selectに検索条件を指定せずテーブル名のみを指定しているので全件検索になります。(ただし、読込件数はデフォルト値の件数で制限されます。)

kaleidox> store-select 'person
Table[3x2]

読み込んだTableの詳細情報を表示すると以下になります。

kaleidox> :show
┏━━━┯━━━━━━┯━━━━━━━━┓
┃id │name  │city    ┃
┣━━━┿━━━━━━┿━━━━━━━━┫
┃100│Taro  │Yokohama┃
┃200│Hanako│Kawasaki┃
┗━━━┷━━━━━━┷━━━━━━━━┛

Tableはオブジェクトなのでプロパティまたはメソッドを使って必要な情報を取り出すことができます。

以下headメソッドを使用して先頭の要素を取り出しています。

kaleidox> .head
id:100 name:Taro city:Yokohama
kaleidox> :show
Record[2] name:Taro city:Yokohama
SQL

データストア機能を使わず直接SQLを使用してデータベース内のデータをTableとRecordとして取得することもできます。

sql関数でSQL文を指定するとSQLが発行されます。SELECT文の場合は結果がTableとして返ってきます。

kaleidox> sql "select * from person"
Table[3x1]
kaleidox> :show
Table[3x1]
┏━━━┯━━━━┯━━━━━━━━┓
┃ID │NAME│CITY    ┃
┣━━━┿━━━━┿━━━━━━━━┫
┃100│Taro│Yokohama┃
┗━━━┷━━━━┷━━━━━━━━┛
kaleidox> .head
ID:100 NAME:Taro CITY:Yokohama
CSVファイル

CSVファイルからテーブルを読み込むことができます。

以下のCSVファイルpersons.csvを用意します。

id,name,city
100,Taro,Yokohama
200,Hanako,Kawasaki

CSVファイルの読込みにはtable-load関数を用います。table-load関数の引数にCSVファイルのURLを指定します。ローカルファイルでもHTTP経由でのリモートファイルでも読込み可能です。

kaleidox> table-load file:persons.csv
Tabble[3x2]

showコマンドで内容を表示すると以下のようにTableオブジェクトとして読み込まれています。

kaleidox> :show
Table[3x2]
┏━━━┯━━━━━━┯━━━━━━━━┓
┃id │name  │city    ┃
┣━━━┿━━━━━━┿━━━━━━━━┫
┃100│Taro  │Yokohama┃
┃200│Hanako│Kawasaki┃
┗━━━┷━━━━━━┷━━━━━━━━┛
LTSVファイル

LTSVファイルからテーブルを読み込むことができます。

以下のLTSVファイルpersons.ltsvを用意します。

id:100 name:Taro city:Yokohama
id:200 name:Hanako city:Kawasaki

LTSVファイルの読込みにはtable-load関数を用います。table-load関数の引数にLTSVファイルのURLを指定します。ローカルファイルでもHTTP経由でのリモートファイルでも読込み可能です。

kaleidox> table-load file:persons.ltsv
Table[3x2]
kaleidox> :show
Table[3x2]
┏━━━┯━━━━━━┯━━━━━━━━┓
┃id │name  │city    ┃
┣━━━┿━━━━━━┿━━━━━━━━┫
┃100│Taro  │Yokohama┃
┃200│Hanako│Kawasaki┃
┗━━━┷━━━━━━┷━━━━━━━━┛
XMLファイル

XML文書から以下のいずれかの構造を読み取り、その情報に基づいてTableオブジェクトを生成することができます。

  • 表データ
  • レコードデータ
表データ

XML文書が以下のようにリスト構造になっている場合は表データとして解釈することができます。

<accounts>
  <account>
    <id>100</id>
    <name>Taro</name>
    <city>Yokohama</city>
  </account>
  <account>
    <id>200</id>
    <name>Hanako</name>
    <city>Kawasaki</city>
  </account>
</accounts>

table-make関数はXML文書の構造を解釈してTableオブジェクトとして読み込みます。

このXML文書をpersons.xmlとして用意してtable-make関数を呼び出すとTableオブジェクトとして読み込むことができます。

kaleidox> table-make file:persons.xml
Table[3x2]
kaleidox> :show
Table[3x2]
┏━━━┯━━━━━━┯━━━━━━━━┓
┃id │name  │city    ┃
┣━━━┿━━━━━━┿━━━━━━━━┫
┃100│Taro  │Yokohama┃
┃200│Hanako│Kawasaki┃
┗━━━┷━━━━━━┷━━━━━━━━┛
レコードデータ

XML文書が以下のようにレコード構造になっている場合はレコードデータとして解釈することができます。

<account>
  <id>100</id>
  <name>Taro</name>
  <city>Yokohama</city>
</account>

このXML文書をperson.xmlとして用意してtable-make関数を呼び出すとTableオブジェクトとして読み込むことができます。

レコード構造の場合は1レコードを持つTableオブジェクトとなります。

kaleidox> table-make file:person.xml
Table[3x1]
kaleidox> :show
Table[3x1]
┏━━━┯━━━━┯━━━━━━━━┓
┃id │name│city    ┃
┣━━━┿━━━━┿━━━━━━━━┫
┃100│Taro│Yokohama┃
┗━━━┷━━━━┷━━━━━━━━┛
JSONファイル

JSON文書から以下のいずれかの構造を読み取り、その情報に基づいてTableオブジェクトを生成することができます。

  • 表データ
  • レコードデータ
表データ

JSON文書が以下のように配列になっている場合は表データとして解釈することができます。

[{
  "id": "100",
  "name": "Taro",
  "city": "Yokohama"
},{
  "id": "200",
  "name": "Hanako",
  "city": "Kawasaki"
}]

このJSON文書をpersons.jsonとして用意してtable-make関数を呼び出すとTableオブジェクトとして読み込むことができます。

kaleidox> table-make file:persons.json
Table[3x2]
kaleidox> :show
Table[3x2]
┏━━━┯━━━━━━┯━━━━━━━━┓
┃id │name  │city    ┃
┣━━━┿━━━━━━┿━━━━━━━━┫
┃100│Taro  │Yokohama┃
┃200│Hanako│Kawasaki┃
┗━━━┷━━━━━━┷━━━━━━━━┛
レコードデータ

JSON文書が以下のようにレコード構造になっている場合はレコードデータとして解釈することができます。

{
  "id": "100",
  "name": "Taro",
  "city": "Yokohama"
}

このJSON文書をperson.jsonとして用意してtable-make関数を呼び出すとTableオブジェクトとして読み込むことができます。

レコード構造の場合は1レコードを持つTableオブジェクトとなります。

kaleidox> table-make file:person.json
Table[3x1]
kaleidox> :show
Table[3x1]
┏━━━┯━━━━┯━━━━━━━━┓
┃id │name│city    ┃
┣━━━┿━━━━┿━━━━━━━━┫
┃100│Taro│Yokohama┃
┗━━━┷━━━━┷━━━━━━━━┛
HTMLファイル

HTML文書からTableオブジェクトを生成することができます。この場合は、HTML文章内の表構造を抽出し、条件に適合するものをTableオブジェクトとして取り出します。

以下のHTMLファイルpersons.htmlにはtableタグによって表が1つ定義されています。

<html>
    <head>
<title>表サンプル</title>
    </head>
    <body>
<p>表のサンプルです</p>
<table>
   <thead>
<tr><th>id</th><th>name</th><th>city</th></tr>
   </thead>
   <tbody>
<tr><td>100</td><td>Taro</td><td>Yokohama</td></tr>
<tr><td>200</td><td>Hanako</td><td>Kawasaki</td></tr>
   </tbody>
</table>
    </body>
</html>

このHTMLファイルに対してtable-make関数を適用するとHTML文書内の表データをTableオブジェクトとして抽出することができました。

kaleidox> table-make file:persons.html
Table[3x2]
kaleidox> :show
Table[3x2]
┏━━━┯━━━━━━┯━━━━━━━━┓
┃id │name  │city    ┃
┣━━━┿━━━━━━┿━━━━━━━━┫
┃100│Taro  │Yokohama┃
┃200│Hanako│Kawasaki┃
┗━━━┷━━━━━━┷━━━━━━━━┛

出力

データストア機能を使ってTableのデータをデータベースに格納することができます。

以下ではstore-insert関数を使って、personテーブルにTableの情報を追加しています。

kaleidox> store-insert x
(101)
kaleidox> store-get 'person 101
ID:101 NAME:Hanako CITY:Kawasaki
kaleidox> store-select 'person
Table[3x2]
kaleidox> :show
Table[3x2]
┏━━━┯━━━━━━┯━━━━━━━━┓
┃id │name  │city    ┃
┣━━━┿━━━━━━┿━━━━━━━━┫
┃100│Taro  │Yokohama┃
┃101│Hanako│Kawasaki┃
┗━━━┷━━━━━━┷━━━━━━━━┛

参照

Tableの内容はRecordのシーケンスとして参照することができます。

準備

前述のinit.kldの設定によって、変数xにTableオブジェクトが束縛されています。

kaleidox> x
Table[3x2]
kaleidox> :show
Table[3x2]
┏━━━┯━━━━━━┯━━━━━━━━┓
┃id │name  │city    ┃
┣━━━┿━━━━━━┿━━━━━━━━┫
┃100│Taro  │Yokohama┃
┃200│Hanako│Kawasaki┃
┗━━━┷━━━━━━┷━━━━━━━━┛

このTableオブジェクトを参照の対象にします。

プロパティ取得

Tableオブジェクトのプロパティは以下のようにプロパティ名を指定して取得することができます。

以下ではTableオブジェクトのカラム数をプロパティwidthで、レコード数をプロパティheightで取得しています。

kaleidox> x.width
3
kaleidox> x.height
2
レコード操作

Tableオブジェクトの先頭レコードはプロパティheadで取得することができます。

kaleidox> x.head
id:100 name:Taro city:Yokohama
kaleidox> :show
Record[3] id:100 name:Taro city:Yokohama

また、先頭レコードを除いた残りのレコードを保持したTableオブジェクトはプロパティtailで取得することができます。

kaleidox> x.tail
Table[3x1]
kaleidox> :show
Table[3x1]
┏━━━┯━━━━━━┯━━━━━━━━┓
┃id │name  │city    ┃
┣━━━┿━━━━━━┿━━━━━━━━┫
┃200│Hanako│Kawasaki┃
┗━━━┷━━━━━━┷━━━━━━━━┛

Tableオブジェクトが空の場合はプロパティheadはnilを返します。

kaleidox> setq y x.tail
Table[3x1]
kaleidox> y.tail
Table[3x0]
kaleidox> :show
Table[3x0]
┏━━┯━━━━┯━━━━┓
┃id│name│city┃
┣━━┿━━━━┿━━━━┫
┗━━┷━━━━┷━━━━┛
kaleidox> .head
nil
スキーマ

Tableオブジェクトのスキーマ情報はプロパティschemaで取得することができます。

kaleidox> x.schema
Schema[3] id,int,1 name,string,1 city,string,?
kaleidox> :show
Schema[3]
┏━━━━┯━━━━━━━━┯━━━━━━━━━━━━┓
┃name│datatype│multiplicity┃
┣━━━━┿━━━━━━━━┿━━━━━━━━━━━━┫
┃id  │int     │1           ┃
┃name│string  │1           ┃
┃city│string  │?           ┃
┗━━━━┷━━━━━━━━┷━━━━━━━━━━━━┛

まとめ

今回はKaleidoxの中軸オブジェクトの一つであるTableについて説明しました。

データベースやCSVファイルといった外部リソースの情報をTableオブジェクトとして読込み、Recordオブジェクト単位で処理していくのがKaleidoxの基本処理モデルです。TableとRecordをハブにして各種の連携を進めていきます。

諸元

  • Kaleidox : 0.1.8

2019年11月30日土曜日

Kaleidox: Record

Kaleidoxはレコードを記述するRecordというオブジェクトを提供しています。

RecordはKaleidoxの中軸となるオブジェクトで、データ処理を行う場合などRecordをハブにして様々な連携を行うようになっています。

今回はRecordの使い方について説明します。

準備

Recordをデータベース入出力で使用するための環境としてKaleidoxの初期化ファイルinit.kldに以下の設定をします。

この設定をしておくと、H2データベースのメモリデータベース上にpersonテーブルが作成され、1レコードが格納された状態になります。

* env

db.default.driver="org.h2.Driver"
db.default.url="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"

* voucher

** person

#+caption: 特性一覧
|特性  | 名前 | 型     | 多重度 | ラベル  |
|------+------+--------+--------+---------|
| 属性 | id   | int    |      1 | User ID |
| 属性 | name | string |      1 | 名前    |
| 属性 | city | string |      ? | 市      |

* main

store-create 'person
store-insert 'person id:100,name:Taro,city:Yokohama

入力

LXSVによるリテラル記述とデータベース読込みでRecordを作成することができます。

LXSV

LXSVリテラルによってRecordを作成することができます。

kaleidox> name:Taro,city:Yokohama
name:Taro city:Yokohama

showコマンドで内容を表示すると2つのプロパティを持つRecordであることが分かります。

kaleidox> :show
Record[2] name:Taro city:Yokohama
データベース読込み

Kaleidoxでは、データベースアクセスの仕組みとして以下の2つを用意しています。

Store
データストア機能
SQL
SQLで直接データベースアクセス
Store

データストア機能を使うと、スキーマ定義といったメタ情報を登録することで、データベースに対してレコードベースのインタフェースでアクセスすることができます。

store-get関数ではデータベースのテーブルからデータをRecordとして読み込むことができます。

以下ではpersonテーブルからID 100のRecordを取得しています。

kaleidox> store-get 'person 100
ID:100 NAME:Taro CITY:Yokohama

データストアからstore-selectでRecordを検索すると、検索結果がテーブルを記述するTableオブジェクトに格納されて返されます。

以下ではstore-selectに検索条件を指定せずテーブル名のみを指定しているので全件検索になります。(ただし、読込件数はデフォルト値の件数で制限されます。)

kaleidox> store-select 'person
Table[3x1]

読み込んだTableの詳細情報を表示すると以下になります。

kaleidox> :show
Table[3x1]
┏━━━┯━━━━┯━━━━━━━━┓
┃id │name│city    ┃
┣━━━┿━━━━┿━━━━━━━━┫
┃100│Taro│Yokohama┃
┗━━━┷━━━━┷━━━━━━━━┛

Tableはオブジェクトなのでプロパティまたはメソッドを使って必要な情報を取り出すことができます。

ここではheadメソッドを使用して先頭の要素を取り出しています。この先頭の要素は本記事のテーマであるRecordとして取り出されます。

kaleidox> .head
id:100 name:Taro city:Yokohama
kaleidox> :show
Record[2] name:Taro city:Yokohama
SQL

データストア機能を使わず直接SQLを使用してデータベース内のデータをTableとRecordとして取得することもできます。

sql関数でSQL文を指定するとSQLが発行されます。SELECT文の場合は結果がTableとして返ってきます。

前述したとおり、Tableオブジェクトのheadメソッドを呼び出すと先頭の行がRecordとして返ってきます。

kaleidox> sql "select * from person"
Table[3x1]
kaleidox> :show
Table[3x1]
┏━━━┯━━━━┯━━━━━━━━┓
┃ID │NAME│CITY    ┃
┣━━━┿━━━━┿━━━━━━━━┫
┃100│Taro│Yokohama┃
┗━━━┷━━━━┷━━━━━━━━┛
kaleidox> .head
ID:100 NAME:Taro CITY:Yokohama

出力

データストア機能を使ってRecordをデータベースに格納することができます。

以下ではstore-insert関数を使って、personテーブルにRecordを追加しています。

kaleidox> store-insert 'person id:101,name:Hanako,city:Kawasaki
(101)
kaleidox> store-get 'person 101
ID:101 NAME:Hanako CITY:Kawasaki
kaleidox> store-select 'person
Table[3x2]
kaleidox> :show
Table[3x2]
┏━━━┯━━━━━━┯━━━━━━━━┓
┃id │name  │city    ┃
┣━━━┿━━━━━━┿━━━━━━━━┫
┃100│Taro  │Yokohama┃
┃101│Hanako│Kawasaki┃
┗━━━┷━━━━━━┷━━━━━━━━┛

参照

Recordの内容はプロパティとして参照することができます。

以下のように変数にpにRecordを束縛します。

kaleidox> setq p id:100,name:Taro,city:Yokohama
id:100 name:Taro city:Yokohama
プロパティ取得

プロパティ取得は以下のようにオブジェクトのプロパティを参照することで行なえます。

kaleidox> p.name
"Taro"
XPath

XPathを使ってRecordからプロパティ取得することもできます。

kaleidox> /name p
"Taro"

まとめ

今回はKaleidoxの中軸オブジェクトであるRecordについて説明しました。

次回はもう一つの中軸オブジェクトであるTableについて説明する予定です。

諸元

  • Kaleidox : 0.1.7

2019年10月31日木曜日

Kaleidox: LXSV

Kaleidoxはレコードを記述するRecordというデータ型を提供しています。

このRecordをテキストとして入出力するためのテキストフォーマットとしてLXSVを開発しました。LXSVを使うことでkaleidoxプログラム内でRecordをリテラルとして記述できます。

LXSVはLTSV(Labeled Tab-separeted Values)的なフォーマットを拡張したもので以下の特徴があります。

  • Kaleidoxプログラム内でリテラルとして記述可能
  • LTSVの概ね上位互換
  • 区切り記号を選択することができる

LXSVフォーマット

LXSVはUnicodeによるテキストフォーマットで区切り記号によってキーと値の対の列によるレコードと、改行コードで区切られたレコードの列を表現できます。

例えば以下のようなテキストがLXSVです。

name:Taro,city:Yokohama
name:Hanako,city:Kawasaki

このテキストではキーと値の対の区切り記号として「:」、キーと値の対の間の区切り記号として「,」を用いています。

キーと値の対の区切り記号は「:」固定ですが、キーと値の対の間の区切り記号は以下のルールによって決められます。

  • TAB、SPACE、「,」、「;」の中で最初に登場した文字を区切り記号とする。

このため以下のLXSVはすべて同じデータ構造を記述しています。

区切り記号: TAB

name:Taro city:Yokohama
name:Hanako city:Kawasaki

区切り記号: SPACE

name:Taro city:Yokohama
name:Hanako city:Kawasaki

区切り記号: ,

name:Taro,city:Yokohama
name:Hanako,city:Kawasaki

区切り記号: ;

name:Taro;city:Yokohama
name:Hanako;city:Kawasaki

区切り記号の入力

値の中にTAB, SPACE, 「,」, 「;」といった区切り記号を入れたい場合、以下の3つの方法があります。

  • 区切り記号の使い分け
  • 「"」で囲んで文字列として記述する。
区切り記号の使い分け

区切り記号を可変にしている理由の1つは区切り記号を値に入れたい場合の文字エスケープを回避することを可能にするためです。

name:Taro;city:Yokohama,Kawasaki
name:Hanako;city:Kawasaki,Yokohama

たとえば以下のように値の中に値の列を記述することも可能になります。ここではLXSVの区切り記号に「;」を使っています。そして、値の中の区切り記号に「,」を使っています。

name:Taro;city:Yokohama,Kawasaki
name:Hanako;city:Kawasaki,Yokohama
文字列

値の中にTAB, SPACE, 「,」, 「;」といった区切り記号を入れたい場合には、前述したように別の区切り記号を使うのが有効ですが、別の方法として「"」を使って文字列を指定することもできます。

name:Taro;city:"Yokohama,Kawasaki"
name:Hanako;city:"Kawasaki,Yokohama"

「"」を使って文字列を記述する場合は、「\n」や「\r」といったエスケープ文字を使って文字列に制御文字を入れることができます。また「”」の文字列内に「"」を入れる場合は「\"」として「\」を使ってエスケープします。

name:Taro;city:"Yokohama\nKawasaki"
name:Hanako;city:"Kawasaki\"Yokohama"

LXSVリテラル

Kaleidoxではレコードを記述するRecordというデータ型を提供しています。このRecordをリテラルとして記述する時にLXSVを用います。

kaleidox> name:Taro,city:Yokohama
name:Taro,city:Yokohama
kaleidox> :show
Record[2] name:Taro,city:Yokohama
文字列リテラルでの入力

Recordを文字列に対する修飾を使って入力することができます。文字列に対する修飾は文字列リテラルの前に修飾を示すプレフィックスを指定します。Recordの場合は「record」です。

以下のように使用します。

kaleidox> record"name:Taro,city:Yokohama"
name:Taro,city:Yokohama
kaleidox> :show
Reord[2] name:Taro,city:Yokohama

KaleidoxではLXSVのデータ型も用意されています。このデータ型を使う場合には修飾を示すプレフィックスとして「lxsv」を指定します。

kaleidox> lxsv"name:Taro,city:Yokohama"
name:Taro,city:Yokohama
kaleidox> :show
Lxsv[2] name:Taro,city:Yokohama

まとめ

Recordを使用するための前提となるLXSVについてご紹介しました。

次回はRecordの具体的な使い方について説明する予定です。

諸元

  • Kaleidox : 0.1.6

2019年9月30日月曜日

Kaleidox: JSON

Kaleidoxでは、実用的に利用できるアクション言語としてXML, HTML, JSON, CSV, Excelといったクラウドアプリケーションで使用する各種データ形式を簡単に扱えるようになっています。

前々回、前回とXMLとHTMLの操作方法について紹介しました。

今回はJSONの操作方法について紹介します。

JSONリテラル

例として以下のJSON文書を考えます。

また、このJSON文書を格納したJSONファイルをfile.jsonとして用意します。

{
  "id": "0001",
  "name": "taro",
  "point": 100
}
リテラル記述

KaleidoxではJSON文書をそのままリテラルとして記述することができます。

REPLでも以下のように直接入力することができます。

kaleidox> {
  "id": "0001",
  "name": "taro",
  "point": 100
}
{\n  "id": "0001",\n  "name": "taro",\n  "point": 100\n}
ファイル入力

REPLでJSON文書が格納されているJSONファイルからJSON文書を取り込む時は以下のようにJSONファイルのURLを記述すればOKです。

kaleidox> file:sample.json
{\n  "id": "0001",\n  "name": "taro",\n  "point": 100\n}\n

この例はプロトコルに「file」を指定してローカルファイルを読み込んでいますが、「http」を指定してリモートファイルを読み込むこともできます。

kaleidox> http://example.com/sample.json
{\n  "id": "0001",\n  "name": "taro",\n  "point": 100\n}\n

XPath

KaleidoxではJSON文書に対してXPathでパス検索をかけることができます。

{
  "id": "0001",
  "name": "taro",
  "point": 100
}

まずJSONファイルsample.jsonに対してXPath「@name」で検索すると以下になります。

JSON文書にある属性nameの値を取得することができました。

kaleidox> @name file:sample.json
"taro"

次にXPath「/name」で検索すると以下になります。こちらもJSON文書にある属性nameの値を取得することができました。

JSONにはXMLにある属性と要素の区別がないので、要素に対する検索ですがJSONの属性に対しても有効になっています。

kaleidox> /name file:sample.json
"taro"

XSLT

KaleidoxはJSON文書をXML文書にみたててXSLT変換を行うことができます。

サンプルとして使用しているJSON文書です。

{
  "id": "0001",
  "name": "taro",
  "point": 100
}

このJSON文書に対して提供するXSL記述は以下になります。

<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html"></xsl:output>

  <xsl:template match="/">
    <HTML>
    <BODY>
    <xsl:apply-templates/>
    </BODY>
    </HTML>
  </xsl:template> 

  <xsl:template match="record">
    <TABLE>
      <THEAD>
        <TR>
          <TH>ID</TH>
          <TH>Name</TH>
   <TH>Point</TH>
        </TR>
      </THEAD>
      <TBODY>
 <TR>
   <TD><xsl:value-of select="id"/></TD>
   <TD><xsl:value-of select="name"/></TD>
   <TD><xsl:value-of select="point"/></TD>
 </TR>
      </TBODY>
    </TABLE>
  </xsl:template> 
</xsl:stylesheet>

XMLやHTMLの場合と同様にXSLファイルに続けてJSONファイルを指定するとXSL変換が行われます。

kaleidox> file:sample.xsl file:sample.json
<HTML><BODY><TABLE><THEAD><TR><TH>ID</TH>
<TH>Name</TH><TH>Point</TH></TR>...

変換後のXML文書を詳細を表示すると以下になります。

無事XSLTでJSONファイルをHTML文書に変換することができました。

kaleidox> :show:print
<HTML><BODY><TABLE><THEAD><TR><TH>ID</TH>
<TH>Name</TH><TH>Point</TH></TR></THEAD>
<TBODY><TR><TD>0001</TD><TD>taro</TD>
<TD>100</TD></TR></TBODY></TABLE>
</BODY></HTML>

Table

XMLやHTMLと同様にJSON文書で記述した表情報をTableデータとして扱うことができます。

サンプルとして使用しているJSON文書です。

{
  "id": "0001",
  "name": "taro",
  "point": 100
}

このJSON文書に対してtable-make関数を適用します。

kaleidox> table-make file:sample.json
Table[3x1]

その結果、幅3、高さ1の表を得ることができました。

この表の内容をshowコマンドで表示すると以下になります。無事HTMLの表の内容を取得できています。

kaleidox> :show
Table[3x1]
┏━━━━┯━━━━┯━━━━━┓
┃id  │name│point┃
┣━━━━┿━━━━┿━━━━━┫
┃0001│taro│100  ┃
┗━━━━┷━━━━┷━━━━━┛

JSON文書がJson Objectの場合は1行のテーブルに変換されます。

レコードシーケンス

JSON文書がJson Objectの配列だった場合は配列の長さ分の行を持ったテーブルに変換されます。

まずJson Objectの配列を持ったJSON文書を用意します。

[{
  "id": "0001",
  "name": "taro",
  "point": 100
},{
  "id": "0002",
  "name": "hanako",
  "point": 200
}]

このJSON文書に対してtable-make関数を適用します。

kaleidox> table-make file:sample-table.json
Table[3x2]

その結果、幅3、高さ2の表を得ることができました。

この表の内容をshowコマンドで表示すると以下になります。無事HTMLの表の内容を取得できています。

kaleidox> :show:print
┏━━━━┯━━━━━━┯━━━━━┓
┃id  │name  │point┃
┣━━━━┿━━━━━━┿━━━━━┫
┃0001│taro  │100  ┃
┠────┼──────┼─────┨
┃0002│hanako│200  ┃
┗━━━━┷━━━━━━┷━━━━━┛

まとめ

今回はJSONの操作について説明しました。

JSONではXPath(パス検索)はXSLT(データ変換)といったXMLで用意されている便利な機能が基本機能として提供されていません。

KaleidoxではJSON文書をXML文書として操作可能にすることで、XMLの便利な機能をJSON文書にも適用できるようにしました。

前々回、前回、今回でXML、HTML、JSONの操作方法についてみてきました。

KaleidoxではXML、HTML、JSONについて詳細を意識することなくシームレスに操作することができることを確認できました。

次回はこのメカニズムの土台となっているRecordについてみていく予定です。

諸元

  • Kaleidox : 0.1.5

2019年8月25日日曜日

Kaleidox: HTML

Kaleidoxでは、実用的に利用できるアクション言語としてXML, HTML, JSON, CSV, Excelといったクラウドアプリケーションで使用する各種データ形式を簡単に扱えるようになっています。

前回はこの中でXMLの操作方法について紹介しました。

今回はHTMLの操作方法について紹介します。

HTMLリテラル

HTMLは元々SGMLベースですが、XMLベースのXHTMLもあります。

XHTMLのみを対象にするとXML処理的には楽ですが、実際のところはSGMLベースのHTMLが主流なのでこちらの方も扱えないといけません。

Kaleidoxでは、SGMLベース、XMLベースのどちらのHTMLもHTMLデータとして扱い、内部的にはDOMで操作しています。

まず以下のHTML文書を考えます。XML的な観点ではすこしブロークンですが、このような形のタグ構造も扱える必要があります。

<b>HTML文書

HTMLリテラルは、文字列リテラルのプレフィックスにHTMLをつけたものになります。

kaleidox> html"""<b>HTML文書"""
<html><head xmlns="http://www.w3.org/1999/xhtml"/><body><b>HTML文書\n</b></b...

showコマンドを使うとHTML全体を表示することができます。

kaleidox> :show
SHtml: <html><head xmlns="http://www.w3.org/1999/xhtml"/><body><b>HTML文書
</b></body></html>

元のHTMLの内容はB要素のみのHTMLの断片ですが、読み込み時にはHTML要素から始まる本格的なHTML文書になっています。これは、HTMLに対するXSLTなどの処理が統一的に行えるように必要な情報を補完しているためです。

ファイル

ファイルに格納されているHTMLは、URIを指定して取り込むことができます。

kaleidox> file:sample.html
<html><head xmlns="http://www.w3.org/1999/xhtml"/><body><b>HTML文書\n</b></b...
kaleidox> :show
SHtml: <html><head xmlns="http://www.w3.org/1999/xhtml"/><body><b>HTML文書
</b></body></html>

XPath

HTMLに対してもXMLと同様にXPathによるアクセスを行うことができます。

まず、HTML文書を読み込みます。

kaleidox> file:sample.html
<html><head xmlns="http://www.w3.org/1999/xhtml"/><body><b>HTML文書\n</b></b...

HTML文書がスタックに積まれたので、これに対してXPath「htmlbody/b」を適用します。

kaleidox> /html/body/b
"HTML文書\n"

XPathを適用の結果、B要素の内容である「HTML文書」を取り出すことができました。

XPathの式の直後にHTMLファイルを指定しても同じ結果を得ることができます。

kaleidox> /html/body/b file:sample.html
"HTML文書\n"

XSLT

HTMLに対してもXMLと同様にXSLTによる変換を行うことができます。

XSLTに使用するXSL文書として以下のものを用意しました。

HTML文書の一部を変更する目的の典型的なXSL文書です。ここではB要素をI要素に変換するXSL文書になっています。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:template match="b">
    <i><xsl:value-of select="."/></i>
  </xsl:template>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

それではXSL文書をHTMLに適用してみましょう。

XSLT文書のファイル名の後ろにHTML文書名を指定します。すると内部的にはxslt関数が実行され、XSLT変換が行われます。

kaleidox> file:sample.xsl file:sample.html
<html><head xmlns="http://www.w3.org/1999/xhtml"/><body><i>HTML文書\n</i></b...

実行結果のHTML文書をshowコマンドで表示すると以下のようになりました。無事B要素がI要素に変換されています。

kaleidox> :show
SHtml: <html><head xmlns="http://www.w3.org/1999/xhtml"/><body><i>HTML文書
</i></body></html>

スクレイピング

KaleidoxはHTML文書内の表データを抽出する機能を提供しています。

まず表を記述したHTML文書を用意します。

<html>
    <head>
 <title>表サンプル</title>
    </head>
    <body>
 <p>表のサンプルです</p>
 <table>
     <thead>
  <tr><th>A</th><th>B</th></tr>
     </thead>
     <tbody>
  <tr><td>1</td><td>11</td></tr>
  <tr><td>2</td><td>12</td></tr>
  <tr><td>3</td><td>13</td></tr>
     </tbody>
 </table>
    </body>
</html>

このHTML文書に対してtable-make関数を適用します。

kaleidox> table-make file:table.html
Table[2x3]

その結果、幅2、高さ3の表を得ることができました。

この表の内容をshowコマンドで表示すると以下になります。無事HTMLの表の内容を取得できています。

kaleidox> :show:print
┏━┯━━┓
┃A│B ┃
┣━┿━━┫
┃1│11┃
┠─┼──┨
┃2│12┃
┠─┼──┨
┃3│13┃
┗━┷━━┛

まとめ

今回はXMLの操作について説明しました。

次回はJSONの操作方法についてみていく予定です。

諸元

  • Kaleidox : 0.1.4

2019年7月29日月曜日

Kaleidox: XML

アクション言語を実用的に使用するにはXML, HTML, JSON, CSV, Excelといったクラウドアプリケーションで使用する各種データ形式を容易に扱えるようになっている必要があります。これらのデータをプログラム内に取り込んだり、データ形式間の相互運用が簡単にできることが重要です。

Kaleidoxでは各種データ形式の個々の操作性と、これらのデータ形式間の相互運用の両面について最適な記述が可能となるような言語機能を提供しています。

ここではまずXMLの操作についてみていきます。

XMLリテラル

KaleidoxはXMLを第一級の言語要素として考えていることもあり、リテラルで記述することができます。

以下のXMLを考えます。

<account>
  <id>0001</id>
  <name>taro</name>
  <point>100</point>
</account>

まずKaleidoxプログラムですが、以下のように上記XMLを直接XMLリテラルとして記述することができます。

<account>
  <id>0001</id>
  <name>taro</name>
  <point>100</point>
</account>

上記プログラムをsample.kに格納して実行すると以下のようになります。

$ kaleidox sample.k
<account>
  <id>0001</id>
  <name>taro</name>
  <point>100</point>
</account>

XMLリテラルで記述されたXML文書がそのまま評価され、評価結果がXML文書として出力されました。

REPL

REPLで同様の処理を行うと以下のようになります。

kaleidox> <account>
  <id>0001</id>
  <name>taro</name>
  <point>100</point>
</account>
<account>\n  <id>0001</id>\n  <name>taro</name>\n  <point>100</point>\n</acco...

プロンプトからXML文書を入力しています。

通常REPLのプロンプトからは改行を区切りとした一行の式を入力しますが、XMLやJSONなどの構造を持つリテラルはリテラル内に改行が入っていても入力することができます。

kaleidox> :show
<account>
  <id>0001</id>
  <name>taro</name>
  <point>100</point>
</account>

ファイルから読み込む場合はURLを指定します。

kaleidox> file:sample.xml
<account>\n  <id>0001</id>\n  <name>taro</name>\n  <point>100</point>\n</acco...

読み込み結果をshowコマンドで表示すると以下になります。

kaleidox> :show
Xml(String)
<account>
  <id>0001</id>
  <name>taro</name>
  <point>100</point>
</account>

XPath

XML文書を処理する場合にはXPathによるXML文書内のデータアクセスが極めて有効です。

KaleidoxではXPathによるXML文書アクセスを行うことができます。

kaleidox> <account>
  <id>0001</id>
  <name>taro</name>
  <point>100</point>
</account>
<account>\n  <id>0001</id>\n  <name>taro</name>\n  <point>100</point>\n</acco...
kaleidox> /account/name
"taro"

XSLT

XML文書の操作ではXSLTによる変換も重要です。

変換対象のXML文書として前出のものを使用します。ファイルsample.xmlに格納しています。

<account>
  <id>0001</id>
  <name>taro</name>
  <point>100</point>
</account>

XML文書を閲覧用のHTML文書に変換するXSLです。ファイルsample.xslに格納します。

<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html"></xsl:output>

  <xsl:template match="/">
    <HTML>
    <BODY>
    <xsl:apply-templates/>
    </BODY>
    </HTML>
  </xsl:template> 

  <xsl:template match="account">
    <TABLE>
      <THEAD>
        <TR>
          <TH>Name</TH>
   <TH>Value</TH>
        </TR>
      </THEAD>
      <TBODY>
 <TR>
   <TD><xsl:value-of select="id"/></TD>
   <TD><xsl:value-of select="name"/></TD>
   <TD><xsl:value-of select="point"/></TD>
 </TR>
      </TBODY>
    </TABLE>
  </xsl:template> 
</xsl:stylesheet>

XSLT変換はxslt関数で行うことができます。

引数にはXSLリテラルまたはXSL文書URL、XMLリテラルまたはXML文書URLを指定します。

以下ではXSL文書URLとXML文書URLを指定しています。xslt関数実行の結果、XML文書を変換したHTML文書に得ることができました。

kaleidox> xslt file:sample.xsl file:sample.xml
<HTML><BODY><TABLE><THEAD><TR><TH>Name</TH><TH>Value</TH></TR></THEAD><TB...
kaleidox> :show:print
<HTML><BODY><TABLE><THEAD><TR><TH>Name</TH><TH>Value</TH></TR></THEAD><TBODY><TR><TD>0001</TD><TD>taro</TD><TD>100</TD></TR></TBODY></TABLE></BODY></HTML>

関数を省略してもXSLファイルが先頭の場合はxslt関数が実行されます。

kaleidox> file:sample.xsl file:sample.xml
<HTML><BODY><TABLE><THEAD><TR><TH>Name</TH><TH>Value</TH></TR></THEAD><TB...

Record

Kaleidoxはレコード/テーブル指向の言語なので、各種データをレコードに変換すると、より柔軟にデータ操作を行うことができます。

record-make関数でXMLからレコードを生成する事ができます。record-make関数はスキーマを与えなくてもXML文書の内容からレコードのスキーマを推測します。

kaleidox> record-make file:sample.xml
id:1,name:taro,point:100

Table

XMLをテーブルに変換することで、Kaleidoxが提供するテーブル操作機能を使ってデータ操作を行うことができます。

table-make関数でXMLからテーブルを生成することができます。table-make関数はスキーマを与えなくてもXML文書の内容からレコードのスキーマを推測します。

kaleidox> table-make file:sample.xml
Table[3x1]

生成されたテーブルデータを表示するためにshowコマンドを実行すると以下の情報が表示されます。

kaleidox> :show
Table[3x1]
┏━━━━┯━━━━┯━━━━━┓
┃id  │name│point┃
┣━━━━┿━━━━┿━━━━━┫
┃0001│taro│100  ┃
┗━━━━┷━━━━┷━━━━━┛
リスト

データ列を記述するXML文書として以下のものをsample-list.xmlとして用意します。

<accounts>
  <account>
    <id>0001</id>
    <name>taro</name>
    <point>100</point>
  </account>
  <account>
    <id>0002</id>
    <name>hanako</name>
    <point>200</point>
  </account>
</accounts>

ここからtable-make関数を使ってテーブルを生成します。

kaleidox> table-make file:sample-list.xml
Table[3x2]

生成した結果のテーブルは以下になります。

kaleidox> :show:print
┏━━━━┯━━━━━━┯━━━━━┓
┃id  │name  │point┃
┣━━━━┿━━━━━━┿━━━━━┫
┃0001│taro  │100  ┃
┠────┼──────┼─────┨
┃0002│hanako│200  ┃
┗━━━━┷━━━━━━┷━━━━━┛

まとめ

今回はXMLの操作について説明しました。

次回以降、HTML, JSON, CSV, Excelの順にデータ操作方法についてみていく予定です。

諸元

  • Kaleidox : 0.1.3

2019年6月2日日曜日

Kaleidox

前回SimpleModeling構想の中核のプロダクトとして開発中のアクション言語(Action Language)であるkaledidoxを紹介しました。

今回はこのkaleidoxのざっくりとした概要について説明します。

特徴

Kaleidoxは以下のプログラミング言語からヒントを得ています。

  • Lisp + Shell Script + Forth + COBOL

ベースとなるのはLispで、基本的にはLispインタープリターがプログラムを解釈実行する構造になっています。

Shell Scriptは、アクション言語として簡単なパイプライン構造でデータ操作を中心としたプログラミングが可能となるように、Shell Script的な文法をLispに対するシンタクスシュガーとして実現しています。

Forthは古のスタック指向言語ですがShell Script的文法と組み合わせてパイプライン・プログラミングを実現するために、Forth的なスタック操作の機能を提供しています。

COBOLは(1)レコード指向、(2)Divisionによる区画を参考にしています。

ソースコード

KaleidoxはGitHubで開発しています。

インストール

Kaleidoxは開発の初期であることもあり簡単にインストール可能なリリース版は用意していません。

興味のある方はソースコードからビルドしてみてください。

以下の手順でビルドすることができます。

$ sbt universal:packageBin

targetuniversalkaleidox-0.1.2.zip というファイルが作成されるのでこれを展開してインストールします。

sbtの機能を使って、debian, rpm, docker, graalvmのインストールパッケージを作成することも可能です。

Hello World

まずkaleidoxの簡単な使い方としてREPLによる実行をしてみます。

コンソールから引数なしでkaleidoxを起動するとREPLのプロンプトが表示されます。

$ kaleidox
kaleidox> 

kaleidoxはLispなので式を評価することでプログラムを実行します。

最も簡単な式はリテラルです。最も重要なリテラルである文字列を入力してみます。

kaleidox> "Hello World"
Hello World

評価の結果、文字列がそのまま返ってきます。

簡単な計算

次は関数の評価です。+関数で足し算を行ってみます。

kaleidox> (+ 1 2)
3

上記は普通のLispの関数評価ですが、kaleidoxの文法では以下のように括弧を外す表記ができるようになっています。

kaleidox> + 1 2
3

この例だけでは分かりづらいかもしれませんが、この文法によりShell Script的にプログラムを書くことができるようになっています。

まとめ

今回はかkaleidoxのざっくりした概要とインストール、Hello Worldまで紹介しました。

次回はJson, XML周りの扱いについて紹介する予定です。

諸元

  • Kaleidox : 0.1.2

2019年5月18日土曜日

SimpleModeling

Modegramming Styleブログではモデリングとプログラミングの一体化を目指してModegrammingというコンセプトを提唱しています。

このModegrammingを実現するための技術体系としてまとめようとしているのがSimpleModelingです。

SimpleModelingでは仕様定義と実装が一体化したモデル駆動開発の実現を目指して、方法論の整備とツールの開発を行っています。

SimpleModelingの基本的な方法論については以下の本にまとめています。

SimpleModelingの枠組みの中で、ここまでで以下のツールを開発してきました。

SimpleModelingによる方法論をモデル駆動開発につなげているツールとしてsimplemodelerを開発していましたが、この開発を通じて見えてきたのが自動生成したアプリケーションの動作基盤となるクラウドプラットフォームです。モデル駆動開発のための重要な要素技術としてクラウドアプリケーションプラットフォーム(以下CAP)が必要という認識にいたりました。

このCAPとしてを業務向けに開発を進めてきたものが Prefer Cloud です。Prefer CloudはPrefer Cloud Platform(以下PCP)というCAP上で動作しています。2012年から足掛け8年ほど開発を進め、一応の軌道に乗ってきました。

そこで、PCPの開発は進めつつ、次の活動としてモデル駆動開発を実現するためのSimpleModelingを再始動することにしました。

モデリング

オブジェクト指向開発方法論(OOAD)の一旦の完成時期を2004年だとすると、すでに15年が経過しており、その間にさまざまな技術革新がありました。

モデリングに関しては関数型言語の進化を取り込んだObject-Functional Analysis and Designの整備が必要だと考えています。

この問題に関しては以前から検討を続けており以下のような記事で検討を続けてきました。

また、クラウド環境を取り巻く以下のようなの新技術をカバーできるようにメタモデルの拡張やプロファイルの整備も行う必要があるでしょう。

  • AI
  • IoT
  • RPA
  • FinTech

プロダクト

SimpleModelingを支えるプロダクトとして以下のものを開発中です。いずれもOSSとして展開しています。

  • smartdox : 文書処理系 (前出)
  • simplemodeler : モデルコンパイラ (前出)
  • kaleidox :: アクション言語
  • arcadia :: ウェブ・フレームワーク
kaleidox

kaleidoxはオブジェクトモデリングとプログラミングをシームレスに連携させることを目的とするアクション言語です。

アクション言語はモデル駆動開発を成立させるミッシングリンクを埋める要の技術ではないか、というのが最近の技術的な興味で、これを具象化するためのアクション言語としてkaleidoxを開発してみました。

スクリプト言語としても面白いものに仕上がっていると思います。機能が多岐に渡るので次回以降少しずつ紹介していく予定です。

arcadia

モデル駆動開発を進める際にネックとなるのがWebフロントです。

サーバーサイドのサービスはRESTサーバーとして実現する場合、モデル駆動開発との相性がよい形で実現しやすいですが、Webフロントに関してはスクラッチの開発になるケースが多いと思います。

画面デザインの調整などどうしてもスクラッチ開発せざるを得ない部分もありますが、ビジネスルールの適用(パラメタの値域など)やアプリケーションロジックとのREST連携などモデル駆動開発の恩恵を得られると考えられるパーツも多いと思います。

モデル駆動開発では、後者の部分は自動生成しつつスクラッチ開発の画面部分との連携をとるためのフレームワークが必要となってくると考えています。

このようなモデル駆動開発向けWebフレームワークとして開発したものがarcadiaです。

kaleidoxの機能を一通りご紹介した後、arcadiaについても紹介していこうと思います。

まとめ

SimpleModelingの全体構想とプロダクトについてご紹介しました。

次回以降は当面SimpleModelingの中核プロダクトであるkaleidoxについて取り上げていく予定です。