このページは福井県立大学の田中求之が2006年1月まで運用していた Mac のサーバ運用に関する会議室 「Web Scripter's Meeting」の記録です。情報が古くなっている可能性がありますのでご注意ください。

XMLとファイルメーカー6

発言者:今井真人
( Date Friday, April 30, 2004 23:29:20 )


XMLは自分ではあまり活用する気がなかったのですが、ファイルメーカー6に
XML形式(ウェブ経由)で入力できる機能があるのを発見して以来、テスト
を重ね何とか実用レベルまで、持っていくことに成功しました。この顛末を
書いて、広く意見を貰おうと思ってます。

今井真人 さんからのコメント
( Tuesday, May 04, 2004 23:29:54 )

ファイルメーカー6でXMLを使うに当たってXMLの文法が2つあります。

「FMPXMLRESULT」と「FMPDSORESULT」です。簡単なのは、FMPDSORESULT
の方でしたが、FMPXMLRESULTがどうやらファイルメーカー側の標準形式である
ようでしたので、FMPXMLRESULTを試すことにしました。

XML書き出し・読み出しをファイルメーカー6でテストしました。単なる読み書きは全く
問題ありません。ウェブからCGIでXMLを出力して、ファイルメーカー6にインポート
するような操作も順調です。CGIが出力するファイルはファイルメーカー6が書き出した
XMLファイルをそのまま利用しました。

XMLファイルを調べると文字コードはUTF8という使ったことがないコードなので面食らい
ました。そこで、私が使い慣れているシフトJISに変換(JEdit 4.0を利用)した後、
以下の文字を置き換えれば、問題ないだろうと安易に考えていました。

例、<?xml version="1.0" encoding="UTF-8" ?>
   ↓
  <?xml version="1.0" encoding="Shift_JIS" ?>

残念なことですがフィールド数が多くなると、ファイルメーカー6側から
エラーメッセージが出て読み取りできなくなりました。しかし、文字コードを
UTF8に戻すと全く問題なしにインポート・エクスポートできます。

どうやらUTF8であることが必須の条件のようです。


今井真人 さんからのコメント
( Wednesday, May 05, 2004 08:29:24 )

私はPerlを使っているので文字コードの変換というと、一番先に思いついたのは
jcode.plでした。しかし、UTF8に変換する機能が見当たりません。どうやら、
無理のようです。

→  jcode.pl official page

今井真人 さんからのコメント
( Wednesday, May 05, 2004 08:39:18 )

コマンドでそのまま使えるのは無いかと探してみると lv がありました。

例、(シフトJISファイルをUTF8に変換)
$ lv -Ou8 file.txt.sjis > file.txt.utf8

perlからは、`lv -Ou8 file.txt.sjis > file.txt.utf8`と書けば
使用上問題はありません。

しかし、CGIが複数のユーザから同時に呼び出されるような場合を想定
すると、一時ファイルの読み書きにおいてエラーが出ることが予想
されました。

→  LV Homepage

今井真人 さんからのコメント
( Wednesday, May 05, 2004 08:52:37 )

最終的にPerlからスマートにUTF8を出力するモジュールを探し出しました。ただし、
ウェブサーバに管理者権限でインストールしなくてはなりません。

Perlモジュールを今まで使ったことが無かったので、心配しましたがマニュアルを
読んで行うとMacOS Xにも簡単にインストールできたので、ちょっと安心です。

インストール例、(suになってから解凍されたディレクトリに移動後)
perl Makefile.PL
make
make test
make install


→  Unicode-Japanese-0.20

今井真人 さんからのコメント
( Wednesday, May 05, 2004 08:59:55 )

Unicode-Japanese-0.20を使ってUTF8を出力するのは、次のようにします。

例、(先に$strへシフトJISの文字コードを入れておく)
use Unicode::Japanese; # モジュールを使う宣言
print Unicode::Japanese->new($str, 'sjis')->get; # convert sjis -> utf8

今井真人 さんからのコメント
( Wednesday, May 05, 2004 09:17:39 )

print Unicode::Japanese->new($str, 'sjis')->get;
と毎回使うのは、わかりにくいような気もしたので、Perlのサブルーチンにして使います。

サブルーチン例、
sub printUTF8 {
  print Unicode::Japanese->new($_[0], 'sjis')->get;
};

使い方の例、(PerlはシフトJISで記入されていると仮定)
&printUTF8("シフトJISだけど、UTF8に変換されます");

今井真人 さんからのコメント
( Wednesday, May 05, 2004 10:13:20 )

道具が揃ってきたので、XMLを出力するCGIを考えてみます。最終的に出力する
XMLは次のようなものを想定します。フィールド数2つ、データのレコード数
2つのシンプルなXMLファイルです。なお、シフトJISで記入されていますが
実際には、UTF8でないとファイルメーカー6には受け付けられません。

<?xml version="1.0" encoding="UTF-8" ?>
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
     <ERRORCODE>0</ERRORCODE>
     <PRODUCT BUILD="2003/02/05" NAME="FileMaker Pro" VERSION="6.0Jv4"/>
     <DATABASE DATEFORMAT="yyyy.M.d" LAYOUT="" NAME="名称未設定.fp5" RECORDS="1" TIMEFORMAT="k:mm:ss "/>
     <METADATA>
          <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="文字1" TYPE="TEXT"/>
          <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="数字1" TYPE="NUMBER"/>
     </METADATA>
     <RESULTSET FOUND="2">
          <ROW MODID="0" RECORDID="1">
               <COL>
                    <DATA>文字</DATA>
               </COL>
               <COL>
                    <DATA>123</DATA>
               </COL>
          </ROW>
          <ROW MODID="0" RECORDID="1">
               <COL>
                    <DATA>テキスト</DATA>
               </COL>
               <COL>
                    <DATA>456</DATA>
               </COL>
          </ROW>
     </RESULTSET>
</FMPXMLRESULT>

長官 さんからのコメント
( Wednesday, May 05, 2004 11:58:50 )

現在perl安定版は5.8.xですが、UTF-8は標準で使えるようです。
Jcode相当のEncodeも標準添付のようです。

→  Encode module

今井真人 さんからのコメント
( Wednesday, May 05, 2004 19:21:41 )

>現在perl安定版は5.8.xですが、UTF-8は標準で使えるようです。

長官さんからコメントが付いてますねぇ。早速調べてみました。

MacOS 10.3.3のターミナルでperl -v とタイプすると
>This is perl, v5.8.1-RC3 built for darwin-thread-multi-2level
>(with 1 registered patch, see perl -V for more detail)
>
>Copyright 1987-2003, Larry Wall

ということで、Perlのバージョンは5.8.1以上のようで対象でした。

Encodeを使ってUTF8を出力するのは、次のようにします。

例、(先に$strへシフトJISの文字コードを入れておく)
use Encode qw/encode decode/; # モジュールを使う宣言
print decode('shiftjis', $str); # convert sjis -> utf8

→  search.cpan.org: Encode::JP - Japanese Encodings

今井真人 さんからのコメント
( Wednesday, May 05, 2004 20:12:04 )

XMLのヘッダ部分は、そのまま出力するだけなので簡単です。Perlで書くなら、
こんな具合でしょう。

$xml_header = <<"EOM";
<?xml version="1.0" encoding="UTF-8" ?>
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
     <ERRORCODE>0</ERRORCODE>
     <PRODUCT BUILD="2003/02/05" NAME="FileMaker Pro" VERSION="6.0Jv4"/>
     <DATABASE DATEFORMAT="yyyy.M.d" LAYOUT="" NAME="名称未設定.fp5" RECORDS="1" TIMEFORMAT="k:mm:ss "/>
     <METADATA>
EOM
&printUTF8( $xml_header );

今井真人 さんからのコメント
( Wednesday, May 05, 2004 20:32:28 )

EncodeモジュールはどうやらPerl 5.7.3以上でないと使えないので、旧式なシステムだと
Unicode-Japanese-0.20を利用することもありそうです。

長官 さんからのコメント
( Wednesday, May 05, 2004 21:00:44 )

perl 5.6とかだとJcode.pmありますね。

→  Jcode.pm

今井真人 さんからのコメント
( Sunday, May 09, 2004 12:07:32 )

残りのものをサラッと済ませます。ファイルメーカーに登録されている
フィールドが多くなると記述が面倒くさいので、次のようにまとめて
書いてます。

$xml_setOfField = <<"EOM";
文字1,TEXT
数字1,NUMBER
EOM

@xml_field = split(/\n/,$xml_setOfField);
foreach $i(0..$#xml_field){
  @xml_item = split(/,/,$xml_field[$i]);
  &printUTF8( "<FIELD EMPTYOK=\"YES\" MAXREPEAT=\"1\" NAME=\"$xml_item[0]\" TYPE=\"$xml_item[1]\"/>\n" );
}

今井真人 さんからのコメント
( Sunday, May 09, 2004 12:17:01 )

<RESULTSET FOUND="2">の「2」はレコード数を表します。

例えば、$xml_data_orgにコンマ区切りでデータを入れておいたとして、
$xml_data_org = <<"EOM";
文字,123
テキスト,456
EOM

@xml_data = split(/\n/,$xml_data_org);
$xml_data_count = $#xml_data++;
&printUTF8( "<RESULTSET FOUND=\"$xml_data_count\">\n" );

とします。

今井真人 さんからのコメント
( Sunday, May 09, 2004 12:18:58 )

なにやら、スラッシュの扱いが怪しいので、再掲。

<RESULTSET FOUND="2">の「2」はレコード数を表します。

例えば、$xml_data_orgにコンマ区切りでデータを入れておいたとして、
$xml_data_org = <<"EOM";
文字,123
テキスト,456
EOM

@xml_data = split(/\n/,$xml_data_org);
$xml_data_count = $#xml_data++;
&printUTF8( "<RESULTSET FOUND=\"$xml_data_count\">\n" );

とします。

今井真人 さんからのコメント
( Sunday, May 09, 2004 12:38:34 )

$xml_data_orgのデータは上記のままだったとして、レコード記述は

@xml_data = split(/\n/,$xml_data_org);
foreach $i(0..$#xml_data) {
    @xml_data_item = split(/,/,$xml_data[$i]);
    print "<ROW MODID=\"0\" RECORDID=\"1\">";
    foreach $j(0..$#xml_data_item){
        print "<COL><DATA>";
        &printUTF8( $xml_data_item[$j] );
        print "</DATA></COL>";
    };
    print "</ROW>\n";
};

とします。

今井真人 さんからのコメント
( Sunday, May 09, 2004 12:44:15 )

<RESULTSET FOUND="2">の部分が、動かないと思うので再掲。

<RESULTSET FOUND="2">の「2」はレコード数を表します。

例えば、$xml_data_orgにコンマ区切りでデータを入れておいたとして、
$xml_data_org = <<"EOM";
文字,123
テキスト,456
EOM

@xml_data = split(/\n/,$xml_data_org);
$xml_data_count = $#xml_data++;
print "<RESULTSET FOUND=\"$xml_data_count\">\n";

とします。

今井真人 さんからのコメント
( Sunday, May 09, 2004 12:52:58 )

こうやって作成したCGIを、ファイルメーカーと連携させて使ってます。

今までだと、ウェブアプリケーションのデータをブラウザ経由でCSV出力させた後
ファイルメーカーで読み込み印刷してました。

XMLを使った手順では、ファイルメーカーがCGIからのXML出力を直接読み印刷
できるようになりました。

今井真人 さんからのコメント
( Wednesday, November 30, 2005 16:59:53 )

ファイルメーカーのデベロッパー版(バージョン8では、Advanced版)を使うと、
再配布可能なアプリケーションを作ることができます。

通信機能が削られてしまうので、ほぼ使い道がないと思ってましたが、ウェブ経由のXML
読み込みは生きています。

私の開発したCGIなどの印刷処理においては、クライアント無制限で使えるというわけです。