はじめに SDKの用法 Java言語の基本 文字列の表示 文字列の連結,パッケージ化 char型の配列 型の変換 ループ ビット演算 シグニチャ 部分文字列 クラス階層 ファイルの入出力 ファイル内容の表示 バイト単位の入出力 行単位の入出力 SAX XML文書からESISへの変換 XML文書のツリー表現 DOM XML文書からESISへの変換 XML文書のツリー表現 XML文書のノード表現 XML文書の生成 XSL XSL変換 XSL:FO変換 XML文書からPDFへの変換 仕様の要約 ESIS DOM XSLT CSS サンプルデータ CARDS.DTD MYCARDS.XML BOOKS.DTD MYBOOKS.XML BOOKS.XSL TEXT.XSL
小文は,私(岸 和孝 )がXML中級セミナーで用いるJava入門テキストです。自習書ではありませんので,Java言語の文法は記述していません。したがって,プログラミング上で必要となる多くの技術情報については,該当する仕様書を参照してください。
現在,XML応用の急速な普及によって,多くのXML応用プログラムの開発が要請されています。XML応用では,従来のデータ処理方法とは異なる面が要求されます。
XML応用に向いたプログラミング言語としてはJavaを挙げることができます。次に述べるような特長を備えていることから,すでに多くのXML応用のライブラリー(製品や部品)やプログラムがJavaによって開発されています。
Javaは,Sun Microsystems社によって1991年に開発されたオブジェクト指向のプログラミング言語です。Javaは,C++をベースにしていますが,C++よりも単純で,学習が容易です。またJavaは,対話的なネットワーク向けプログラムで要求される安全性,堅牢性,高性能性を実現しております。Javaのソースは,プラットフォームに依存しない形で表現でき,それから得られるバイナリー(これはバイトコードと呼ばれます)は,異なるプラットフォームでも実行できるようにJVMJVM:Java Vartual Machine の下で実行します。XML応用に共通のライブラリーがJARJAR:Java ARchive として無償配付されています。こうしたことがXML応用への適用に向いている理由とされています。
このセミナーでは,SDKSDK:Java Software Development Kit (MS-WindowsではJ2SDKJ2SDK:Java 2 SDK, Standard Edition ,MacOSではMRJ SDK 2.2MRJ SDK 2.2:Mac OS Runtime for Java Software Development Kit )を用いながら,Java言語の基本を学んだ後に,XML応用に不可欠なSAXSAX:Simple API for XML とDOMDOM:Document Object Model を用いたJavaプログラムの構築方法について学びます。さらに,JavaによるXSL変換についても学びます。なお,J2SDKとMRJ SDK 2.2の実現は全く同じではありませんので,注意が必要です。さらにMRJ SDK 2.2には,まだ幾つかの不具合があるために,別のJavaコンパイラであるJakeを併用します。
ここで用いるリソースは,次のサイトから入手して解凍解凍:解凍結果で得られたJARファイルをさらに解凍してはなりません。なお,これらのJARファイルは2001年6月時点のものです。必要に応じて,上記の参考URLから最新のものを入手してください。 してください。
実習を始めるに当たって,SDKを使ったコンパイルと実行の方法について説明します。
MS-Windows J2SDKは,MS-DOSで実行します。先ず,スタートメニューのMS-DOSプロンプトからMS-DOSを呼び出すと,MS-DOSウィンドウが開きますので,そのMS-DOSの制御の下でJ2SDKを使っていきます。
J2SDKを使う上で必要となるMS-DOSコマンドは,次のものです。その詳細については,参考書を参照してください。
| MS-DOSコマンドの例 | 機能 |
|---|---|
| CD \XJ\1\1_1 | ディレクトリ"\XJ\1\1_1"へ切り替える。 |
| SET path=C:\J2SDK\bin | J2SDKのバイナリへのパス"C:\J2SDK\bin"を設定する。 |
| SET classpath=C:\XJ\lib\crimson.jar;C:\XJ\lib\jaxp.jar | 参照するJARファイルを"C:\XJ\lib\crimson.jar"と"C:\XJ\lib\jaxp.jar"に設定する。 |
| javac -d . Xml2EsisUsingSAX.java | javaソース"Xml2EsisUsingSAX.java"をコンパイルし,現在のディレクトリ"-d ."にバイトコード"Xml2EsisUsingSAX.class"を生成する。 |
| java Xml2EsisUsingSAX sample.xml | バイトコード"Xml2EsisUsingSAX.class"を引数"sample.xml"で実行する。 |
MS-Windows J2SDKでは,javaソース(拡張子が".java")は,javac(javaコンパイラ)によってコンパイルされます。例えば,"C:\J2SDK\bin\javac"によってjavaソースをコンパイルします。javaソースが"Xml2EsisUsingSAX.java"であれば,参照するJARファイルは"C:\XJ\lib\crimson.jar"と"C:\XJ\lib\jaxp.jar"ですので,次のようになります。コンパイル結果のバイトコード(拡張子が".class")は,現在のディレクトリ"-d ."に"Xml2EsisUsingSAX.class"として得られます。
SET classpath=C:\XJ\lib\crimson.jar;C:\XJ\lib\jaxp.jar;. javac -d . Xml2EsisUsingSAX.java
MS-Windows J2SDKでは,コンパイルで生成されたバイトコードは,java(Javaアプリケーションの起動コマンド)を介して実行します。例えば,"C:\J2SDK\bin\java"を介してバイトコードを実行します。コマンドラインは,バイトコードが"Xml2EsisUsingSAX.class"であれば,参照するJARファイルは"C:\XJ\lib\crimson.jar"と"C:\XJ\lib\jaxp.jar"ですので,次のようになります。なお,コマンド引数が必要な場合は,"sample.xml"のように続けて入力します。
SET classpath=C:\XJ\lib\crimson.jar;C:\XJ\lib\jaxp.jar;. java Xml2EsisUsingSAX sample.xml
こうした操作を簡便にするために,AUTOEXEC.BATにおいてPATHやclasspathを設定しておいたり,バッチファイルを用いることもできますが,MS-DOSの操作に慣れていない方は,コマンドで毎回指示したほうがいいでしょう。
MRJ SDK 2.2では,javaソースは,javacによってコンパイルされます。例えば,javaソースを"MyDisk:MRJ SDK 2.2:JDK Tools:javac"へドラッグ・アンド・ドロップします。ドラッグ・アンド・ドロップしたjavaソースが含まれたフォルダーがClasspath欄へ追加されます。参照するJARファイルがある場合は,Classpath欄に追加します。次に,Do Javacボタンを押すと,コンパイルが行われます。
Jakeによってもjavaソースをコンパイルできます。例えば,javaソースを"MyDisk:Jake1.2:Jake 1.2 (beta1)"へドラッグ・アンド・ドロップします。javaソースがSource Code欄へ追加されます。次に,Classpath欄に参照するJARファイルを追加します。compileボタンを押すと,コンパイルが行われます。この設定は保存できますので,次のコンパイルの時は,そのドキュメントをダブルクリックするだけで済みます。
MRJ SDK 2.2では,コンパイルで生成されたバイトコードは,JBinderyを介して実行します。例えば,javaバイトコードを"MyDisk:MRJ SDK 2.2:Application Builders:JBindery:JBindery"へドラッグ・アンド・ドロップします。コマンド引数が必要な場合は,Command:optional parameters欄に入力します。参照するJARファイルがある場合は,Classpath:Additions to class path欄に追加します。Runボタンを押すと,バイトコードが実行されます。
Java言語の基本を例題を通して学びます。
このプログラムは,文字列"Hello"と"Hi"を表示します。
| プログラム | sample1 |
| クラスパス | なし |
| コマンド引数 | なし |
class sample1 {
public static void main( String[] args ) {
System.out.println("Hello");
System.out.println("Hi");
System.exit(0);
}
}
| class クラス名 ブロック | 単純なクラス定義 |
| class sample1 { } | sample1のクラス定義 |
| 型指定 メソッド名( パラメタ ... ) ブロック | メソッド定義 |
| public static void main( String[] args ) { } | main()のメソッド定義 |
| void | 戻り値を返さない |
| static | クラスメソッド |
| public | 外部から呼び出せる(公開) |
| main( String[] args ) | main()メソッド |
| 型指定 配列変数名[] | 配列変数 |
| String[] args | String型配列の変数args |
| args | コマンドラインのパラメタ |
| クラス名.クラスメソッド名( 値, ... ) | クラスメソッド |
| System.out.println(); | Systemクラスの標準出力(改行付き) |
| "こんにちわ" | 文字列リテラル |
このプログラムは,いろいろな文字列を表示します。
| プログラム | sample2 |
| クラスパス | なし |
| コマンド引数 | なし |
import other.*;
class sample2 {
public static void main( String[] args ) {
String Hello = "Hello", lo = "lo";
System.out.println( "Hello" );
System.out.println( "Hel" + "lo" );
System.out.println( "Hel" + lo );
System.out.println( sample2x.hello );
System.out.println( other.sample2x.hello );
System.exit(0);
}
}
class sample2x {
static String hello = "Hi";
}
package other;
public class sample2x {
public static String hello = "Yes";
}
| import パッケージ; | パッケージのpublicクラスをすべてインポート |
| import other.*; | otherのpublicクラスをすべてインポート |
| クラス名 変数名, ... ; | クラス型の変数宣言 |
| String Hello; | String型の変数名Hello |
| String Hello = "Hello"; | 変数名Helloへの初期値代入 |
| "Hel" + "lo" | 文字列リテラルどうしの連結 |
| "Hel" + lo | 文字列リテラルと変数の連結 |
| package パッケージ; | このファイルをパッケージに所属させる |
| package other; | sample2x.javaをotherに所属させる |
| sample2x.hello | 同じパッケージ内にあるクラス変数 |
| other.sample2x.hello | パッケージother内のクラス変数 |
このプログラムは,コマンドラインから任意の文字列を入力すると,それを一文字づつ表示します。
| プログラム | sample3 |
| クラスパス | なし |
| コマンド引数 | 文字列 |
class sample3 {
public static void main( String[] args ) {
String a = args[0];
System.out.println( "String : " + a );
char[] chars = a.toCharArray();
System.out.println( "char[0]: " + chars[0] );
System.out.println( "char[1]: " + chars[1] );
System.out.println( "char[2]: " + chars[2] );
System.out.println( "char[3]: " + chars[3] );
System.out.println( "char[4]: " + chars[4] );
System.out.println( "char : " + java.lang.String.valueOf( chars ) );
System.exit(0);
}
}
| char[] | char型(基本型)の配列 |
| オブジェクト.メソッド名( 値, ... ) | インスタンスメソッド |
| オブジェクト.クラスメソッド名( 値, ... ) | クラスメソッド |
| クラス名.クラスメソッド名( 値, ... ) | クラスメソッド |
| a.toCharArray() | 変数a(Stringオブジェクト)に附随するtoCharArrayメソッド(char型配列として取り出す)を呼ぶ |
| java.lang.String.valueOf( chars ) | 変数chars(基本型,オブジェクトではない)をvalueOfメソッド(String型へ変換)に引き渡す |
このプログラムは,コマンドラインから任意の文字列を入力すると,それが数値であれば数値として表示します。
| プログラム | sample4 |
| クラスパス | なし |
| コマンド引数 | 文字列 |
class sample4 {
public static void main( String[] args ) throws NumberFormatException {
String a = args[0];
try {
try {
int i = java.lang.Integer.parseInt( a );
System.out.println( "int: " + java.lang.Integer.toString( i ) );
}
catch ( NumberFormatException e ) {
long l = java.lang.Long.parseLong( a );
System.out.println( "long: " + java.lang.Long.toString( l ) );
}
}
catch ( NumberFormatException e ) {
System.out.println( "String: " + a );
}
System.exit(0);
}
}
| throws NumberFormatException | NumberFormatException(数値形式の例外)を投げる可能性がある |
| java.lang.Integer.parseInt( a ) | 変数a(基本型)をparseIntメソッド(int型として解析)に引き渡す |
| java.lang.Long.parseLong( a ) | 変数a(基本型)をparseLongメソッド(long型として解析)に引き渡す |
| java.lang.Integer.toString( i ) | 変数i(基本型)をtoStringメソッド(String型へ変換)に引き渡す |
| try ブロック catch ( 例外指定 ) ブロック | ガードされたブロックと例外の受け止め |
| catch ( NumberFormatException e ) | 受け止める例外指定とそのスタックトレース |
このプログラムは,コマンドラインから幾つかの文字列を入力すると,それらを表示します。
| プログラム | sample5 |
| クラスパス | なし |
| コマンド引数 | 文字列[文字列]... |
class sample5 {
public static void main( String[] args ) {
for ( int i = 0; i < args.length; i++ )
System.out.println( "args[" + i +"]: " + args[i] );
System.exit(0);
}
}
| for ( 初期化 ; テスト ; 再設定 ) ブロック | forループ |
| for ( int i = 0; ) | 初期化:int型のローカル変数iを0とする |
| for ( ; i < args.length; ) | テスト:変数iがパラメタの配列の要素数よりも小さいか |
| for ( ; ; i++ ) | 再設定:変数iを1だけインクリメントする |
| 配列変数[添字] | 配列の要素を参照する |
| 配列変数.length | 配列の要素数 |
| args[i] | 配列変数argsのi番目の要素を参照する |
| 条件 ? 値1 : 値2 | 条件が真の時に値1をとり,偽の時に値2をとる |
| System.out.print(); | Systemクラスの標準出力(改行なし) |
このプログラムは,コマンドラインから数値を入力すると,それをバイトとして扱い,結果を表示します。
| プログラム | sample6 |
| クラスパス | なし |
| コマンド引数 | 数値 |
class sample6 {
public static void main(String[] args) {
int n = java.lang.Integer.parseInt( args[0] );
System.out.println( " n :" + n );
int a[] = new int[n];
System.out.println("a[" + a.length + "]" );
byte b = (byte)n;
System.out.println( " b :" + b );
int i = ~b;
System.out.println( " b :" + Integer.toHexString(b) );
System.out.println( "~b :" + Integer.toHexString(i) );
i = b << 4;
System.out.println( "b :" + Integer.toHexString(b) );
System.out.println( "b<<4:" + Integer.toHexString(i) );
System.exit(0);
}
}
| 型指定 配列変数名[] = new 型指定[要素数]; | 新しい配列オブジェクトの生成 |
| int a[] = new int[n]; | n個の要素からなるint型配列変数a |
| (型名)式 | キャスト |
| (byte)n | int型変数nをbyte型へ変換する |
| byte b | byte型の変数b |
| ~b | 変数b全体をNOTする |
| b << 4 | 変数b全体を4ビットだけ左へシフトする |
| Integer.toHexString(b) | 変数bを16進文字列へ変換する |
このプログラムは,コマンドラインから1個から3個までの数値を入力すると,その最大値を表示します。
| プログラム | sample7 |
| クラスパス | なし |
| コマンド引数 | 数値[ 数値[ 数値 ]] |
public class sample7 {
int max(int x) {
return x;
}
int max(int x, int y) {
return ( x > y ) ? x : y;
}
int max(int x, int y, int z) {
if ( x > y && x > z) return x;
else if ( y > x && y > z) return y;
else return z;
}
public static void main(String[] args) {
int i, j, k;
sample7 test = new sample7();
switch ( args.length ) {
case 1 :
i = java.lang.Integer.parseInt( args[0] );
System.out.println( "max(x): " + test.max( i ) );
break;
case 2 :
i = java.lang.Integer.parseInt( args[0] );
j = java.lang.Integer.parseInt( args[1] );
System.out.println( "max(x,y): " + test.max( i, j ) );
break;
case 3 :
i = java.lang.Integer.parseInt( args[0] );
j = java.lang.Integer.parseInt( args[1] );
k = java.lang.Integer.parseInt( args[2] );
System.out.println( "max(x,y,z): " + test.max( i, j, k ) );
break;
default :
System.out.println( "failed" );
break;
}
System.exit(0);
}
}
| switch ( 式 ) ブロック | ブロック内のcaseによる場合分け |
| case 値 : 文 | 値に等しい時に,この文を実行する |
| default : 文 | ブロック内のすべてのcaseに一致しない時に,この文を実行する |
| break | forなどのループやswitchのブロックから脱出する |
| クラス名 変数名 = new クラス名[値, ...]; | 新しいインスタンスの生成 |
| sample7 test = new sample7(); | クラスsample7のインスタンスtestの生成 |
| 戻り値の型 メソッド名(型, 引き数, ...) ブロック | メソッド定義 |
| int max(int x, int y, int z) { } | x,y,zのうちの最大値を返すメソッド |
| クラス名.クラスメソッド名( 値, ... ) | クラスメソッド |
| test.max( i, j, k ) | i,j,kのうちの最大値 |
| if ( 条件 ) ブロック1 else ブロック2 | 条件が真の時にブロック1を実行し,偽の時にブロック2を実行する |
| return | 値を戻す |
| 値1 > 値2 | 値1が値2より大きいか |
| 値1 && 値2 | 値1と値2との論理ANDをとる |
このプログラムは,コマンドラインから任意の文字列,その部分文字列の開始位置と終了位置を入力すると,その部分文字列を表示します。
| プログラム | sample8 |
| クラスパス | なし |
| コマンド引数 | 文字列 開始位置 終了位置 |
class sample8 {
public static void main( String[] args ) {
System.out.println( "string :" + args[0] );
System.out.println( "start position:" + args[1] );
System.out.println( "end position :" + args[2] );
String str = args[0];
int start = java.lang.Integer.parseInt( args[1] );
int end = java.lang.Integer.parseInt( args[2] );
char c1 = str.charAt( start );
char c2 = str.charAt( end - 1 );
System.out.println( "starting char :" + c1 );
System.out.println( "ending char :" + c2 );
char buffer[] = new char[ end - start ];
str.getChars( start, end, buffer, 0 );
System.out.println( "sub-string :" + buffer );
System.exit(0);
}
}
| オブジェクト.メソッド名( 値, ... ) | インスタンスメソッド |
| str.charAt( start ) | 変数strの(Stringオブジェクト)の指定桁位置の文字を取り出す |
| str.getChars( start, end, buffer, 0 ) | 変数strの(Stringオブジェクト)の部分文字列を取り出す |
このプログラムは,スーパークラス,サブクラスを利用して,ある配列の内容を表示します。
| プログラム | sample9 |
| クラスパス | なし |
| コマンド引数 | なし |
class Point {
int x, y;
Point( int x, int y ) {
this.x = x;
this.y = y;
}
public String toString() {
return ( "x=" + x + ", y=" + y );
}
}
interface Colorable {
void setColor( int color );
}
class ColoredPoint extends Point implements Colorable {
int color;
ColoredPoint( int x, int y, int color ) {
super( x, y );
setColor( color );
}
public void setColor( int color ) {
this.color = color;
}
public String toString() {
return super.toString() + ", color=" + color;
}
}
class sample9 {
public static void main( String[] args ) {
Point[] cp = new ColoredPoint[4];
cp[0] = new ColoredPoint(1, 2, 0);
cp[1] = new ColoredPoint(3, 4, 1);
cp[2] = new ColoredPoint(5, 6, 2);
ColoredPoint[] cpa = ( ColoredPoint[] ) cp;
System.out.println( "cpa.length: " + cpa.length );
for (int i = 0; i < cpa.length - 1; i++)
System.out.println( "cpa[" + i + "]: " + cpa[i] );
System.exit(0);
}
}
| クラス名( パラメタ, ... ) | コンストラクタ定義 |
| Point( int x, int y ) | コンストラクタPointの定義 |
| this.オブジェクト | カレントオブジェクトを参照する |
| super.オブジェクト | スーパークラスのオブジェクトを参照する |
| this.x = x | Pointの変数xにコンストラクタのパラメタxを代入する |
| super.toString() | PointのtoString()メソッドを参照する |
| super( 値, ... ) | スーパークラスのコンストラクタを呼ぶ |
| this( 値, ... ) | クラスのコンストラクタを呼ぶ |
| interface インタフェース名 ブロック | インタフェース定義 |
| interface Colorable { } | インタフェースColorableの定義 |
| extends スーパークラス名 ブロック | スーパークラス定義 |
| class ColoredPoint extends Point | クラスColoredPointはスーパークラスPointのサブクラスとなる |
| implements インタフェース名, ... | インタフェースを実現する |
| class ColoredPoint implements Colorable | クラスColoredPointはインタフェースColorableを実現する |
Java応用の基本となるファイルの入出力を例題を通して学びます。
このプログラムは,コマンドラインで指定したファイルの内容を入力し,それをそのまま表示します。
| プログラム | DisplayFile |
| クラスパス | なし |
| コマンド引数 | 入力ファイル名 |
import java.io.*;
public class DisplayFile {
public static void main( String[] args ) {
if ( args.length != 1 ) {
System.err.println( "USAGE: java FileOperationByByte inputfile");
System.exit(1);
}
try {
DataInput data;
String text;
int lineNo;
data = new DataInputStream( new FileInputStream( args[0] ) );
lineNo = 1;
while ( ( text = data.readLine() ) != null ) {
System.out.println( lineNo + " " + text.length() + " " + text );
lineNo++;
}
}
catch( IOException e ) {
System.err.println( "Error detected:" + e.getMessage() );
System.exit(1);
}
System.exit(0);
}
}
| import java.io.*; | java.ioパッケージのインポート |
| DataInput | インタフェース |
| FileInputStream | 抽象クラスInputStreamのサブクラスFileInputStream |
| DataInputStream | 抽象クラスInputStreamのサブクラスFilterInputStreamのサブクラスDataInputStream |
| data.readLine() | 行末符号までのデータを行単位に読み込む |
| null | この場合はEOF(ファイルの終了)を表す |
| catch( IOException e ) { } | 入出力例外の受け止め |
このプログラムは,バイト単位の入出力を用いて,コマンドラインで指定した入力ファイルから出力ファイルへ内容を複製し,同時にその内容を表示します。
| プログラム | FileOperationByByte |
| クラスパス | なし |
| コマンド引数 | 入力ファイル名 出力ファイル名 |
import java.io.*;
public class FileOperationByByte {
public static void main( String[] args ) {
if ( args.length != 2 ) {
System.err.println( "USAGE: java FileOperationByByte inputfile Outputfile");
System.exit(1);
}
if ( new File( args[1] ).exists() ) {
System.err.println( "Error: OutputFile already existed");
System.exit(1);
}
DataInput in;
DataOutput out;
byte b;
int lineNo;
int charPos;
try {
in = new DataInputStream( new FileInputStream( args[0] ) );
out = new DataOutputStream( new FileOutputStream( args[1] ) );
try{
lineNo = 1;
charPos = 1;
System.out.print( lineNo + "\t" + charPos + "\t" );
while ( true ) {
b = in.readByte();
charPos++;
switch ( b ) {
case 0x0a : // '\n'
System.out.println( "\\n" );
lineNo++;
System.out.print( lineNo + "\t" + charPos + "\t" );
break;
case 0x0d : // '\r'
System.out.println( "\\r" );
lineNo++;
System.out.print( lineNo + "\t" + charPos + "\t" );
break;
case 0x09 : // '\t'
System.out.print( "\\t" );
break;
default :
System.out.print( (char)b );
break;
}
out.writeByte( b );
}
}
catch( IOException e ) {
System.out.println( "Error detected: " + e.getMessage() );
System.exit(1);
}
}
catch( IOException e ) {
System.err.println( "Error detected: " + e.getMessage() );
System.exit(1);
}
System.exit(0);
}
}
| '文字' | 文字リテラル |
| \\ | \(本来はバックスラッシュ)を表す文字エスケープ記号 |
| \n | LF符号を表す文字エスケープ記号 |
| \r | CR符号を表す文字エスケープ記号 |
| DataOutput | インタフェース |
| FileOutputStream | 抽象クラスOutputStreamのサブクラスFileOutputStream |
| DataOutputStream | 抽象クラスOutputStreamのサブクラスFilterOutputStreamのサブクラスDataOutputStream |
| in.readByte() | データをバイト単位に読み込む |
| out.writeByte( b ) | データをバイト単位に書き出す |
このプログラムは,行単位の入出力を用いて,コマンドラインで指定した入力ファイルから出力ファイルへ内容を複製します。
| プログラム | FileOperationByLine |
| クラスパス | なし |
| コマンド引数 | 入力ファイル名 出力ファイル名 |
import java.io.*;
public class FileOperationByLine {
public static void main( String[] args ) {
if ( args.length != 2 ) {
System.err.println( "USAGE: FileOperationByLine inputfile Outputfile");
System.exit(1);
}
if ( new File( args[1] ).exists() ) {
System.err.println( "Error: OutputFile already existed");
System.exit(1);
}
try {
BufferedReader reader;
PrintWriter writer;
String text;
reader = new BufferedReader( new FileReader( args[0] ) );
writer = new PrintWriter( new FileWriter( args[1] ) );
try {
for ( text = reader.readLine(); null != text; text = reader.readLine() ) {
writer.println( text );
System.out.println( text );
}
}
finally {
writer.close();
}
}
catch( IOException e ) {
System.err.println( "Error detected: " + e.getMessage() );
System.exit(1);
}
System.exit(0);
}
}
| BufferedReader | Readerのサブクラス |
| PrintWriter | Writerのサブクラス |
| FileReader | InputStreamReaderのサブクラス |
| FileWriter | OutputStreamWriterのサブクラス |
| finally ブロック | 後始末 |
SAXSAX:Simple API for XML を例題を通して学びます。SAXは,XML文書データを順次に読み取りながら個別の処理を行うようにした応用プログラムインターフェースで,少ない記憶容量で大きな文書を扱うのに適しています。
このプログラムは,xml.orgが開発したSAXを用いて,XML文書インスタンスを入力し,ESIS形式 で表示します。
| プログラム | Xml2EsisUsingSAX |
| クラスパス | crimson.jar,jaxp.jar |
| コマンド引数 | 入力ファイル名 |
import org.xml.sax.*;
import javax.xml.parsers.*;
import java.io.*;
public class Xml2EsisUsingSAX extends HandlerBase {
static String fileName;
private int level;
private String[ ] nest = new String[ 100 ];
public static void main( String[] args ) throws Exception {
if ( args.length != 1 ) {
System.err.println( "USAGE: java Xml2EsisUsingSAX xmlfile" );
System.exit(1);
}
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating( true );
SAXParser saxParser = factory.newSAXParser();
Parser parser = saxParser.getParser();
Xml2EsisUsingSAX handler = new Xml2EsisUsingSAX( );
parser.setDocumentHandler( handler );
fileName = args[0];
parser.parse( fileName );
System.exit(1);
}
catch ( Exception e) {
System.out.println( "Error detected: " + e.getMessage() );
System.exit(1);
}
}
public void startDocument( ) {
level = 0;
}
public void endDocument( ) {
System.out.println( "C" );
}
public void startElement( String qname, AttributeList atts ) {
if ( atts != null ) {
for ( int i = 0; i < atts.getLength(); i++ ) {
System.out.println( "A" + atts.getName(i) + " TOKEN " + atts.getValue(i) );
}
}
System.out.println( "(" + qname );
nest[ level ] = qname;
nest[ level + 1 ] = null;
level++;
}
public void endElement( String qname ) {
level--;
System.out.println( ")" + qname );
}
public void characters( char ch[], int start, int length ) {
// fix me !
String text = new String(ch, start, length ).replace( '\n', '~' );
System.out.println( "-" + text );
nest[ level ] = "#text";
nest[ level + 1 ] = null;
}
public void processingInstruction( String target, String data ) {
System.out.println( "?" + target + " " + data );
nest[ level ] = target;
nest[ level + 1 ] = null;
}
}
| SAXParserFactory.newInstance() | 使用するパーザーを指定しインスタンス化する |
| SAXParser | SAXの基本インタフェース |
| parser.setDocumentHandler( handler ) | イベントハンドラーを登録する |
| parser.parse() | XML文書を構文解析する |
| startDocument() { } | 文書の開始を読み込んだ時に呼び出されるメソッドに上書きされる |
| endDocument() { } | 文書の終了を読み込んだ時に呼び出されるメソッドに上書きされる |
| startElement() { } | 要素の開始を読み込んだ時に呼び出されるメソッドに上書きされる |
| endElement() { } | 要素の終了を読み込んだ時に呼び出されるメソッドに上書きされる |
| characters() { } | 内容を読み込んだ時に呼び出されるメソッドに上書きされる |
| processingInstruction() { } | 処理命令を読み込んだ時に呼び出されるメソッドに上書きされる |
このプログラムは,変数levelを用いて要素のツリーを字下げで表現し出力するように,Xml2EsisUsingSAXを書き換えたものです。
| プログラム | Xml2TreeUsingSAX |
| クラスパス | crimson.jar,jaxp.jar |
| コマンド引数 | XMLファイル 結果ファイル |
import org.xml.sax.*;
import javax.xml.parsers.*;
import java.io.*;
public class Xml2TreeUsingSAX extends HandlerBase {
static String fileName;
private int level;
private String[ ] nest = new String[ 100 ];
static PrintWriter writer;
public static void main( String[] args ) {
if ( args.length != 2 ) {
System.err.println( "USAGE: java Xml2TreeUsingSAX xmlfile outputfile");
System.exit(1);
}
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating( true );
SAXParser saxParser = factory.newSAXParser();
Parser parser = saxParser.getParser();
Xml2TreeUsingSAX handler = new Xml2TreeUsingSAX( );
parser.setDocumentHandler( handler );
writer = new PrintWriter( new FileWriter( args[1] ) );
fileName = args[0];
parser.parse( fileName );
writer.close();
System.exit(0);
}
catch ( Exception e) {
System.out.println( "Error detected :" + e.getMessage() );
System.exit(1);
}
}
public void startDocument( ) {
level = 0;
}
public void endDocument( ) {
;
}
public void startElement( String qname, AttributeList atts ) {
writer.println( indent( level ) + qname );
nest[ level ] = qname;
nest[ level + 1 ] = null;
level++;
}
public void endElement( String qname ) {
level--;
}
public void characters( char ch[], int start, int length ) {
// fix me
String text = new String(ch, start, length ).replace( '\n', '~' );
writer.println( "\t" + text );
nest[ level ] = "#text";
nest[ level + 1 ] = null;
}
/*
public void processingInstruction( String target, String data ) {
writer.println( indent( level ) + "?" + target + " " + data );
nest[ level ] = target;
nest[ level + 1 ] = null;
}
*/
public String indent( int n ) {
String s;
for ( s = ""; n > 0; n-- )
s += " ";
return s;
}
}
DOMDOM:Document Object Model を例題を通して学びます。DOM は,XML文書データを一旦すべて読み取って記憶上にノードツリーとして展開し,その後,個別の処理を行うようにした応用プログラムインターフェースで,文書を構造的に扱うのに適しています。
このプログラムは,W3Cが開発したDOMとSun Microsysystemsが開発したJAXPJAXP:Java API for XML Parsing を用いて,XML文書インスタンスを入力し,ESIS形式 で表示します。
| プログラム | Xml2EsisUsingDOM |
| クラスパス | crimson.jar,jaxp.jar |
| コマンド引数 | XMLファイル |
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.*;
public class Xml2EsisUsingDOM {
private int level = 0;
private String[ ] nest = new String[ 100 ];
static PrintStream out = System.out;
Xml2EsisUsingDOM() { }
public void makeDocTree( String docName ) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse( new FileInputStream( docName ) );
Element elem = doc.getDocumentElement();
makeNodeTree( elem );
}
public void makeNodeTree( Node node ) throws Exception {
printNodeData( node );
NodeList nl = node.getChildNodes();
int numberOfChildren = nl.getLength();
level++;
if ( numberOfChildren > 0 ) {
for ( int i = 0; i < numberOfChildren; i++ ) {
makeNodeTree( nl.item( i ) );
}
}
level--;
// fix me
if ( ! nest[ level ].substring( 0, 1 ).equals( "#" ) ) {
out.println( ")" + nest[ level ] );
}
}
public void printNodeData( Node node ) throws Exception {
String nodeName = node.getNodeName();
int nodeType = node.getNodeType();
String nodeValue = node.getNodeValue();
nest[ level ] = nodeName;
nest[ level + 1 ] = null;
switch ( nodeType ) {
case Node.CDATA_SECTION_NODE :
break;
case Node.COMMENT_NODE :
break;
case Node.DOCUMENT_FRAGMENT_NODE :
break;
case Node.DOCUMENT_NODE :
break;
case Node.DOCUMENT_TYPE_NODE :
break;
case Node.ELEMENT_NODE :
NamedNodeMap attlist = node.getAttributes();
if ( attlist != null ) {
for ( int i = 0; i < attlist.getLength(); i++ ) {
Node it = attlist.item( i );
if ( it.getNodeType() != Node.ATTRIBUTE_NODE ) {
System.err.println( "Internal error: " + nodeName );
}
out.println( "A" + it.getNodeName() + " TOKEN " + it.getNodeValue() );
}
}
out.println( "(" + nodeName );
break;
case Node.ENTITY_NODE :
break;
case Node.ENTITY_REFERENCE_NODE :
out.println( "&" + nodeName );
break;
case Node.NOTATION_NODE :
out.println( "N" + nodeName );
break;
case Node.PROCESSING_INSTRUCTION_NODE :
out.println( "?" + nodeName + " " + nodeValue );
break;
case Node.TEXT_NODE :
if ( nodeValue != null ) {
// fix me
String newNodeValue = nodeValue.replace( '\n', '~' );
out.println( "-" + newNodeValue );
}
break;
}
}
public static void main( String[ ] args ) {
if ( args.length != 1 ) {
System.err.println( "USAGE: java Xml2EsisUsingDOM xmlfile");
System.exit(1);
}
try {
Xml2EsisUsingDOM tree = new Xml2EsisUsingDOM();
tree.makeDocTree( args[ 0 ] );
System.exit(0);
}
catch ( Exception e) {
out.println( "Error detected: " + e.getMessage() );
System.exit(1);
}
}
}
| DocumentBuilderFactory | XML文書からDOMオブジェクトツリーを生成するパーザーが得られるようにするAPIを定義するクラス |
| DocumentBuilderFactory.newInstance() | DocumentBuilderFactoryの新しいインスタンスを作る |
| DocumentBuilder | XML文書からDOM文書インスタンスを得るためのAPIを定義するクラス |
| dbf.newDocumentBuilder() | 現在設定されている条件を用いてDocumentBuilderの新しいインスタンスを作る |
| db.parse() | XML文書として与えられたInputStreamの内容を構文解析し,新しいDOM文書オブジェクトを返す |
| Document | 完全なXML文書のルートノード |
| Node | 大半のオブジェクトを表すインタフェース |
| NodeList | 順に並べたノードの集まりを表すインタフェース |
| Element | 文書内の要素を表すインタフェース |
| NamedNodeMap | 名前でアクセスできるノードの集まりを表すインタフェース |
| doc.getDocumentElement() | 文書docのルート要素を返す |
| node.getChildNodes() | ノードnodeのすべての子を順に並べたNodeListオブジェクトを返す |
| node.getNodeName() | ノードnodeのノード名を返す |
| node.getNodeType() | ノードnodeのノード型を返す |
| node.getNodeValue() | ノードnodeのノード値を返す |
| node.getAttributes() | ノードnodeのすべての属性を順に並べたNamedNodeMapオブジェクトを返す |
このプログラムは,変数levelを用いて要素のツリーを字下げで表示するように,Xml2EsisUsingDOMを書き換えたものです。
| プログラム | Xml2TreeUsingDOM |
| クラスパス | crimson.jar,jaxp.jar |
| コマンド引数 | XMLファイル |
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.*;
public class Xml2TreeUsingDOM {
private int level = 0;
private String[ ] nest = new String[ 100 ];
static PrintStream out = System.out;
Xml2TreeUsingDOM() { }
public void makeDocTree( String docName ) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse( new FileInputStream( docName ) );
Element elem = doc.getDocumentElement();
makeNodeTree( elem );
}
public void makeNodeTree( Node node ) throws Exception {
printNodeData( node );
NodeList nl = node.getChildNodes();
int numberOfChildren = nl.getLength();
level++;
if ( numberOfChildren > 0 ) {
for ( int i = 0; i < numberOfChildren; i++ ) {
makeNodeTree( nl.item( i ) );
}
}
level--;
}
public void printNodeData( Node node ) throws Exception {
String nodeName = node.getNodeName();
int nodeType = node.getNodeType();
String nodeValue = node.getNodeValue();
nest[ level ] = nodeName;
nest[ level + 1 ] = null;
switch ( nodeType ) {
case Node.DOCUMENT_NODE :
break;
case Node.DOCUMENT_TYPE_NODE :
break;
case Node.ELEMENT_NODE :
out.println( indent( level ) + nodeName );
break;
case Node.PROCESSING_INSTRUCTION_NODE :
out.println( indent( level ) + "?" + nodeName + " " + nodeValue );
break;
case Node.TEXT_NODE :
if ( nodeValue != null ) {
// fix me
String newNodeValue = nodeValue.replace( '\n', '~' );
out.println( "\t" + newNodeValue );
}
break;
}
}
public String indent( int n ) {
String s;
for ( s = ""; n > 0; n-- )
s += " ";
return s;
}
public static void main( String[ ] args ) {
if ( args.length != 1 ) {
System.err.println( "USGAE: java Xml2TreeUsingDOM xmlfile");
System.exit(1);
}
try {
Xml2TreeUsingDOM tree = new Xml2TreeUsingDOM();
tree.makeDocTree( args[ 0 ] );
System.exit(0);
}
catch ( Exception e) {
out.println( "Error detected: " + e.getMessage() );
System.exit(1);
}
}
}
このプログラムは,DOMとして記憶された文書のツリーのノード情報を表示するように,Xml2EsisUsingDOMを書き換えたものです。
| プログラム | DumpTreeUsingDOM |
| クラスパス | crimson.jar,jaxp.jar |
| コマンド引数 | XMLファイル |
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.*;
public class DumpTreeUsingDOM {
private int level = 0;
static PrintStream out = System.out;
DumpTreeUsingDOM() { }
public void makeDocTree( String docName ) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse( new FileInputStream( docName ) );
Element elem = doc.getDocumentElement();
printNodeAllInfo( 'n', 0, elem );
}
public void printNodeAllInfo( char nodeT, int nodeN, Node node ) throws Exception {
if ( node == null ) { out.println( indent( level ) + level + " " + "node is null." ); return; }
String nodeName = node.getNodeName();
out.print( indent( level ) + level + " " );
switch ( nodeT ) {
case 'n' :
out.print( "(" + nodeN + ")" );
break;
case 'a' :
out.print( "[" + nodeN + "]" );
break;
default :
out.print( "???" );
break;
}
out.print( " " + nodeName + " " );
int type = node.getNodeType();
String nodeType = "";
switch (type) {
case Node.ELEMENT_NODE :
nodeType = "ELEMENT_NODE"; break;
case Node.ATTRIBUTE_NODE :
nodeType = "ATTRIBUTE_NODE"; break;
case Node.TEXT_NODE :
nodeType = "TEXT_NODE"; break;
case Node.CDATA_SECTION_NODE :
nodeType = "CDATA_SECTION_NODE"; break;
case Node.ENTITY_REFERENCE_NODE :
nodeType = "ENTITY_REFERENCE_NODE"; break;
case Node.ENTITY_NODE :
nodeType = "ENTITY_NODE"; break;
case Node.PROCESSING_INSTRUCTION_NODE :
nodeType = "PROCESSING_INSTRUCTION_NODE"; break;
case Node.COMMENT_NODE :
nodeType = "COMMENT_NODE"; break;
case Node.DOCUMENT_NODE :
nodeType = "DOCUMENT_NODE"; break;
case Node.DOCUMENT_TYPE_NODE :
nodeType = "DOCUMENT_TYPE_NODE"; break;
case Node.DOCUMENT_FRAGMENT_NODE :
nodeType = "DOCUMENT_FRAGMENT_NODE"; break;
case Node.NOTATION_NODE :
nodeType = "NOTATION_NODE"; break;
default :
nodeType = "?"; break;
}
out.print( nodeType + " " );
String nodeValue = node.getNodeValue();
String newNodeValue;
if ( nodeValue != null ) {
newNodeValue = nodeValue.replace( '\n', '~' );
}
else {
newNodeValue = "";
}
out.println( "|" + newNodeValue + "|" );
boolean hasAttributes = node.hasAttributes();
if ( hasAttributes ) {
NamedNodeMap nameNodeMap = node.getAttributes();
int numberOfNodes = nameNodeMap.getLength();
out.println( indent( level ) + " " + nodeName + "'s attributes: " + numberOfNodes );
level++;
if ( numberOfNodes > 0 ) {
for ( int i = 0; i < numberOfNodes; i++ ) {
printNodeAllInfo( 'a', i, nameNodeMap.item( i ) );
}
}
level--;
}
boolean hasChildNodes = node.hasChildNodes();
if ( hasChildNodes ) {
NodeList nodeList = node.getChildNodes();
int numberOfChildren = nodeList.getLength();
out.println( indent( level ) + " " + nodeName + "'s children: " + numberOfChildren );
level++;
if ( numberOfChildren > 0 ) {
for ( int i = 0; i < numberOfChildren; i++ ) {
printNodeAllInfo( 'n', i, nodeList.item( i ) );
}
}
level--;
}
}
public String indent( int n ) {
String s;
for ( s = ""; n > 0; n-- )
s += " ";
return s;
}
public static void main( String[ ] args ) {
if ( args.length != 1 ) {
System.err.println( "USAGE: java DumpTreeUsingDOM xmlfile");
System.exit(1);
}
try {
DumpTreeUsingDOM tree = new DumpTreeUsingDOM();
tree.makeDocTree( args[ 0 ] );
System.exit(0);
}
catch ( Exception e) {
out.println( "Error detected: " + e.getMessage() );
System.exit(1);
}
}
}
このプログラムは,ESIS形式 の文書データからDOMとしてXML文書を生成します。これは,実用的なプログラムではありませんが,線状のESISのストリームとツリー状のDOMとの関係や,DOMを構造的にアクセスする際の手法が確認できます。-vオプションを指定すると,詳細な進行状況を表示します。
| プログラム | HandleTreeUsingDOM |
| クラスパス | crimson.jar,jaxp.jar |
| コマンド引数 | ESISファイル[-v] |
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.*;
import java.util.*;
public class HandleTreeUsingDOM {
static boolean verbose = false;
static PrintStream out = System.out;
static final int maxOfArrayOfNode = 100;
static final int maxOfArrayOfOccur = 1000;
static final int maxOfArrayOfAttr = 10;
static String arrayOfNodeName[] = new String[maxOfArrayOfNode];
static int arrayOfOccur[] = new int[maxOfArrayOfOccur];
static String arrayOfAttr[] = new String[maxOfArrayOfAttr];;
static int currLevel = 0;
static int traceLevel = 0;
static int indexOfAttr = 0;
static int level = 0;
HandleTreeUsingDOM() { }
public Document makeDocTree( String docName ) throws Exception {
char command;
String operands;
DocumentType doctype = null;
Document doc = null;
Node root = null;
Node parent = null;
Node curr = null;
Element element = null;
Element currElement = null;
String parentName;
String elementName;
String contents;
Text text;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
DOMImplementation di = db.getDOMImplementation();
BufferedReader reader = new BufferedReader( new FileReader( docName ) );
currLevel = -1;
try {
for ( String line = reader.readLine(); null != line; line = reader.readLine() ) {
command = line.charAt( 0 );
operands = line.substring( 1, line.length() );
if ( verbose ) out.println( "ESIS: "+command+" "+operands );
switch ( command ) {
case '(':
elementName = operands;
if ( currLevel == -1 ) {
currLevel = 0;
arrayOfOccur[currLevel] = 0;
arrayOfOccur[currLevel+1] = -1;
arrayOfNodeName[currLevel] = elementName;
if ( verbose ) out.println( " "+currLevel+"("+arrayOfOccur[currLevel]+") "+elementName );
doctype = di.createDocumentType( elementName, "", "" );
doc = di.createDocument( "", elementName, doctype );
root = doc.getDocumentElement();
curr = root;
element = (Element) root;
if ( verbose ) out.println( " root:"+root.getNodeName() );
}
else {
currLevel++;
arrayOfOccur[currLevel]++;
arrayOfOccur[currLevel+1] = -1;
arrayOfNodeName[currLevel] = elementName;
if ( verbose ) out.println( " "+currLevel+"("+arrayOfOccur[currLevel]+") "+elementName );
parentName = arrayOfNodeName[currLevel-1];
if ( verbose ) out.println( " parent:"+(currLevel-1)+"("+arrayOfOccur[currLevel-1] +") "+parentName);
parent = moveToParent( doc, currLevel-1, arrayOfOccur[currLevel-1], parentName );
if ( verbose ) out.println( " moveToParent... "+parent.getNodeName() );
element = doc.createElement( elementName );
if ( verbose ) out.println( " createElement... "+element.getNodeName() );
curr = parent.appendChild( element );
currElement = (Element) curr;
if ( verbose ) out.println( " appendChild... "+parent.getNodeName()+" <= "+currElement.getNodeName() );
if ( indexOfAttr > 0 ) {
String arrayOfToken[] = new String[100];
for ( int i = 0; i < indexOfAttr; i++ ) {
if ( verbose ) out.println( " ("+i+") "+arrayOfAttr[i] );
StringTokenizer ts = new StringTokenizer( arrayOfAttr[i] );
int j = 0;
while ( ts.hasMoreTokens() )
arrayOfToken[j++] = ts.nextToken();
Attr attr = doc.createAttribute( arrayOfToken[0] );
if ( verbose ) out.println( " createAttribute... "+attr.getName() );
currElement.setAttributeNode( attr );
if ( verbose ) out.println( " setAttributeNode... "+currElement.getNodeName()+" <= "+attr.getName() );
if ( arrayOfToken[1].equals( "TOKEN" ) ) {
// fix me
attr.setValue( arrayOfToken[2] );
if ( verbose ) out.println( " setValue...|"+arrayOfToken[2]+"|" );
}
}
}
indexOfAttr = 0;
}
break;
case ')' :
elementName = operands;
if ( verbose ) out.println( " "+currLevel+"("+arrayOfOccur[currLevel]+") "+elementName );
currLevel--;
break;
case 'A' :
arrayOfAttr[indexOfAttr++] = operands;
if ( verbose ) out.println( " "+currLevel+"["+arrayOfOccur[currLevel]+"] "+operands );
break;
case '-' :
contents = operands;
currLevel++;
arrayOfOccur[currLevel]++;
arrayOfOccur[currLevel+1] = -1;
arrayOfNodeName[currLevel] = "#text";
if ( verbose ) out.println( " "+currLevel+"("+arrayOfOccur[currLevel]+") "+contents );
parentName = arrayOfNodeName[currLevel-1];
if ( verbose ) out.println( " parent:"+(currLevel-1)+"("+arrayOfOccur[currLevel-1] +") "+parentName);
parent = moveToParent( doc, currLevel-1, arrayOfOccur[currLevel-1], parentName );
if ( verbose ) out.println( " moveToParent... "+parent.getNodeName() );
text = doc.createTextNode( contents );
if ( verbose ) out.println( " createTextNode... "+text.getNodeName() );
parent.appendChild( text );
if ( verbose ) out.println( " appendChild... "+parent.getNodeName() );
currLevel--;
break;
default :
break;
}
}
}
catch ( DOMException e ) {
e.printStackTrace();
System.exit(1);
}
finally {
reader.close();
return( doc );
}
}
public Node moveToParent( Document doc, int level, int occur, String parentName ) {
if ( verbose )
out.println( " moveToParent(doc"+", "+level+", "+occur+", "+parentName+" )" );
traceLevel = 0;
Node node = doc.getDocumentElement();
if ( verbose ) out.println( " root:"+node.getNodeName() );
if ( traceLevel == level
&& parentName.equals( arrayOfNodeName[traceLevel] )
) {
if ( verbose ) out.println( " found:"+node.getNodeName() );
return( node );
}
traceLevel++;
boolean look = true;
Node child = null;
while ( look ) {
if ( verbose ) out.println( " traceLevel:"+traceLevel );
NodeList nodeList = node.getChildNodes();
boolean hasChildNodes = node.hasChildNodes();
if ( hasChildNodes ) {
int numberOfChildren = nodeList.getLength();
if ( verbose ) out.println( " numberOfChildren:"+numberOfChildren );
if ( numberOfChildren > 0 ) {
child = nodeList.item( arrayOfOccur[traceLevel] );
String childName = child.getNodeName();
int childType = child.getNodeType();
if ( verbose ) out.println( " "+currLevel+"("+arrayOfOccur[currLevel] +") child:"+childName+", type:"+childType+", array:"+arrayOfNodeName[traceLevel] );
if ( childName.equals( arrayOfNodeName[traceLevel] )
&& parentName.equals( childName ) ) {
if ( verbose ) out.println( " found:"+child.getNodeName() );
look = false;
break;
}
else {
traceLevel++;
if ( verbose ) out.println( " next:"+child.getNodeName() );
node = child;
continue;
} // if
} // if
} // if
} // while
if ( verbose ) out.println( " return:"+child.getNodeName() );
return( child );
}
public void printAllInfoOfDOM( Document doc ) throws Exception {
try {
Node root = doc.getDocumentElement();
level = 0;
out.println( "" );
printNodeAllInfo( 'n', 0, root );
}
catch ( DOMException e ) {
e.printStackTrace();
System.exit(1);
}
}
public void printNodeAllInfo( char nodeT, int nodeN, Node node ) throws Exception {
if ( node == null ) { out.println( indent( level ) + level + " " + "node is null." ); return; }
String nodeName = node.getNodeName();
out.print( indent( level ) + level + " " );
switch ( nodeT ) {
case 'n' :
out.print( "(" + nodeN + ")" );
break;
case 'a' :
out.print( "[" + nodeN + "]" );
break;
default :
out.print( "???" );
break;
}
out.print( " " + nodeName + " " );
int type = node.getNodeType();
String nodeType = "";
switch (type) {
case Node.ELEMENT_NODE :
nodeType = "ELEMENT_NODE"; break;
case Node.ATTRIBUTE_NODE :
nodeType = "ATTRIBUTE_NODE"; break;
case Node.TEXT_NODE :
nodeType = "TEXT_NODE"; break;
case Node.CDATA_SECTION_NODE :
nodeType = "CDATA_SECTION_NODE"; break;
case Node.ENTITY_REFERENCE_NODE :
nodeType = "ENTITY_REFERENCE_NODE"; break;
case Node.ENTITY_NODE :
nodeType = "ENTITY_NODE"; break;
case Node.PROCESSING_INSTRUCTION_NODE :
nodeType = "PROCESSING_INSTRUCTION_NODE"; break;
case Node.COMMENT_NODE :
nodeType = "COMMENT_NODE"; break;
case Node.DOCUMENT_NODE :
nodeType = "DOCUMENT_NODE"; break;
case Node.DOCUMENT_TYPE_NODE :
nodeType = "DOCUMENT_TYPE_NODE"; break;
case Node.DOCUMENT_FRAGMENT_NODE :
nodeType = "DOCUMENT_FRAGMENT_NODE"; break;
case Node.NOTATION_NODE :
nodeType = "NOTATION_NODE"; break;
default :
nodeType = "?"; break;
}
out.print( nodeType + " " );
String nodeValue = node.getNodeValue();
String newNodeValue;
if ( nodeValue != null ) {
newNodeValue = nodeValue.replace( '\n', '~' );
}
else {
newNodeValue = "";
}
out.println( "|" + newNodeValue + "|" );
boolean hasAttributes = node.hasAttributes();
if ( hasAttributes ) {
NamedNodeMap nameNodeMap = node.getAttributes();
int numberOfNodes = nameNodeMap.getLength();
out.println( indent( level ) + " " + nodeName + "'s attributes: " + numberOfNodes );
level++;
if ( numberOfNodes > 0 ) {
for ( int i = 0; i < numberOfNodes; i++ ) {
printNodeAllInfo( 'a', i, nameNodeMap.item( i ) );
}
}
level--;
}
boolean hasChildNodes = node.hasChildNodes();
if ( hasChildNodes ) {
NodeList nodeList = node.getChildNodes();
int numberOfChildren = nodeList.getLength();
out.println( indent( level ) + " " + nodeName + "'s children: " + numberOfChildren );
level++;
if ( numberOfChildren > 0 ) {
for ( int i = 0; i < numberOfChildren; i++ ) {
printNodeAllInfo( 'n', i, nodeList.item( i ) );
}
}
level--;
}
}
public String indent( int n ) {
String s;
for ( s = ""; n > 0; n-- )
s += " ";
return s;
}
public static void main( String[ ] args ) {
if ( args.length == 0 || args.length > 2 ) {
System.err.println( "USAGE: java HandleTreeUsingDOM esisfile [-v]");
System.exit(1);
}
if ( args.length == 2 )
verbose = ( args[1].equals( "-v" ) ? true : false );
try {
HandleTreeUsingDOM tree = new HandleTreeUsingDOM();
Document doc = tree.makeDocTree( args[0] );
tree.printAllInfoOfDOM( doc );
System.exit(0);
}
catch ( Exception e) {
out.println( "Error detected: "+e.getMessage() );
System.exit(1);
}
}
}
XSLを学びます。
このプログラムは,XML文書をスタイルシートに従ってXSL変換(XSLT )します。
| プログラム | RunXSLT |
| クラスパス | crimson.jar,jaxp.jar,xalan.jar,xerces-1.2.3.jar |
| コマンド引数 | XMLファイル スタイルシート[ 出力形式[ エンコーディング ]] |
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import java.io.File;
public class RunXSLT {
public static void main(String[] args) throws Exception {
File xmlFile = new File( args[0] );
File xslFile = new File( args[1] );
if ( args.length < 2 || args.length > 4 ) {
System.err.println( "USAGE: java RunXSLT xmlfile xslfile [method [encoding] ]");
System.exit(1);
}
try {
Source xml = new StreamSource( xmlFile );
Source xsl = new StreamSource( xslFile );
Result out = new StreamResult( System.out );
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer( xsl );
if ( args.length >= 3 ) {
t.setOutputProperty( OutputKeys.METHOD, args[2] );
}
else {
t.setOutputProperty( OutputKeys.METHOD, "html" );
}
if ( args.length == 4 ) {
t.setOutputProperty( OutputKeys.ENCODING, args[3] );
}
else {
t.setOutputProperty( OutputKeys.ENCODING, "Shift_JIS" );
}
t.transform( xml, out );
System.exit(0);
}
catch ( Exception e ) {
e.printStackTrace();
System.exit(1);
}
}
}
このプログラムは,フォーマッティングオブジェクトで表現されたFOファイルをPDFへ変換し結果ファイルへ出力します。
| プログラム | RunXSLFO |
| クラスパス | crimson.jar,fop-0.17.0-jp.jar,jaxp.jar,xalan.jar,xerces-1.2.3.jar |
| コマンド引数 | FOファイル 結果ファイル |
import org.w3c.dom.*;
import javax.xml.parsers.*;
import org.apache.fop.apps.*;
import org.apache.fop.render.*;
import org.apache.fop.fo.*;
import org.apache.fop.svg.*;
import java.io.*;
public class RunFO {
public static void main( String[ ] args ) {
if ( args.length != 2 ) {
System.err.println( "USAGE: java RunFO fofile outFile");
System.exit(1);
}
try {
OutputStream outFile = new FileOutputStream( args[1] );
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse( new FileInputStream( args[0] ) );
Driver driver = new Driver( );
driver.setRenderer( "org.apache.fop.render.pdf.PDFRenderer", "1.0" );
driver.addElementMapping( "org.apache.fop.fo.StandardElementMapping" );
driver.addElementMapping( "org.apache.fop.svg.SVGElementMapping" );
driver.addPropertyList( "org.apache.fop.fo.StandardPropertyListMapping" );
driver.addPropertyList( "org.apache.fop.svg.SVGPropertyListMapping" );
driver.buildFOTree( doc );
driver.setOutputStream( outFile );
driver.format();
driver.render();
System.exit(0);
}
catch ( Exception e ) {
e.printStackTrace();
System.exit(1);
}
}
}
このプログラムは,XML文書をスタイルシートに従ってフォーマッティングオブジェクトに変換し,次いでFOファイルをPDFへ変換し結果ファイルへ出力するように,RunXSLTとRunFOを合わせたものです。
| プログラム | RunXSLFO |
| クラスパス | crimson.jar,fop-0.17.0-jp.jar,jaxp.jar,xalan.jar,xerces-1.2.3.jar |
| コマンド引数 | ソースファイル スタイルシート 変換結果 |
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import org.apache.fop.apps.*;
import org.apache.fop.render.*;
import org.apache.fop.fo.*;
import org.apache.fop.svg.*;
import java.io.*;
public class RunXSLFO {
static int level = 0;
static PrintStream writer = System.out;
public static void main( String[ ] args ) {
if ( args.length != 5 ) {
System.err.println( "USAGE: java RunXSLFO xmlfile xslfile fofile encoding outFile");
System.exit(1);
}
try {
// XSLT
Source xml = new StreamSource( new File( args[0] ) );
Source xsl = new StreamSource( new File( args[1] ) );
Result fo = new StreamResult( new File( args[2] ) );
String encoding = args[3];
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer( xsl );
t.setOutputProperty( OutputKeys.METHOD, "xml" );
t.setOutputProperty( OutputKeys.ENCODING, encoding );
t.transform( xml, fo );
// FOP
OutputStream outFile = new FileOutputStream( args[4] );
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse( new FileInputStream( args[2] ) );
Driver driver = new Driver( );
driver.setRenderer( "org.apache.fop.render.pdf.PDFRenderer", "1.0" );
driver.addElementMapping( "org.apache.fop.fo.StandardElementMapping" );
driver.addElementMapping( "org.apache.fop.svg.SVGElementMapping" );
driver.addPropertyList( "org.apache.fop.fo.StandardPropertyListMapping" );
driver.addPropertyList( "org.apache.fop.svg.SVGPropertyListMapping" );
driver.buildFOTree( doc );
driver.setOutputStream( outFile );
driver.format();
driver.render();
System.exit(0);
}
catch ( Exception e ) {
e.printStackTrace( writer );
System.exit(1);
}
}
}
ESISESIS:Element Structure Information Set,要素構造情報集合 は,ISO/IEC 13673で定義されたSGMLデータ表現形式であり,通常,SGMLパーザーから出力されます。ESISにはSGML宣言,文書型定義,文書インスタンスの各々の情報がすべて含まれていますので,PerlやJavaなどによる後処理が容易です。次の表はその一部です。
| コマンド | オペランド | 意味 |
|---|---|---|
| ( | 共通識別子 | この共通識別子を持つ要素が開始したことを表わす。この要素の属性は,Aコマンドで指定される。 |
| ) | 共通識別子 | この共通識別子を持つ要素が終了したことを表わす。 |
| - | データ | このデータを表わす。 |
| ? | データ | このデータを含む処理命令を表わす。 |
| A | 属性名 IMPLIED | 属性名が省略され,その値が#IMPLIEDであることを表わす。 |
| A | 属性名 CDATA 文字データ | 属性名の内容型がCDATAであることと,その値を文字データで表わす。 |
| A | 属性名 NOTATION 記法名 | 属性名の内容型がNOTATIONであることと,その記法名を表わす。 |
| A | 属性名 ENTITY 一般実体名 ... | 属性名の内容型がENTITYまたはENTITIESであることと,その一般実体名のリストを表わす。各実体名は,Iコマンド,Eコマンド,Sコマンドで指定される。 |
| A | 属性名 TOKEN 字句 ... | 属性名の内容型がその他の属性で,字句のリストが値を表わす。 |
| & | 外部データ実体名 | この外部データ実体名を持つ外部データ実体への参照を表わす。外部データ実体名は,Eコマンドで指定される。 |
DOMDOM:Document Object Model は,文書をノードの集まりで記憶しています。次の表は,関数で取り出せるノードの情報を表わします。
| ノード | getNodeType() | getNodeName() | getNodeValue() | getAttributes() |
|---|---|---|---|---|
| Element | ELEMENT_NODE | タグ名 | null | NameNodeMap |
| Attr | ATTRIBUTE_NODE | 属性名 | 属性値 | null |
| Text | TEXT_NODE | #text | 内容 | null |
| CDATASection | CDATA_SECTION_NODE | #cdata-section | 内容 | null |
| EntityReference | ENTITY_REFERENCE_NODE | 実体参照名 | null | null |
| Entity | ENTITY_NODE | 実体名 | null | null |
| ProcessingInstruction | PROCESSING_INSTRUCTION_NODE | ターゲット名 | 名前を除く内容 | null |
| Comment | COMMENT_NODE | #comment | 内容 | null |
| Document | DOCUMENT_NODE | #document | null | null |
| DocumentType | DOCUMENT_TYPE_NODE | 文書型名 | null | null |
| DocumentFragment | DOCUMENT_FRAGMENT_NODE | #document-fragment | null | null |
| Notation | NOTATION_NODE | 記法名 | null | null |
XSLTXSLT:XSL Transformation,XSL変換 は,XSL仕様の前段に相当します。タグの変換をスタイルシート(変換規則の並び)として表わします。次の表はその一部です。
| 変換規則 | 変換の機能 |
|---|---|
| <xsl:template match="パターン"> 変換規則の並び </xsl:template> | パターンで指定された要素が出現した場合に,その変換規則の並びを適用する。 |
| <xsl:value-of select="パターン"/> | パターンで指定された要素の内容をここに挿入する。 |
| <xsl:attribute name="属性名"> 属性値 </xsl:attribute> | 直前の要素に対して属性(属性名="属性値")を追加する。 |
| <xsl:if test="パターン"> 変換規則の並び </xsl:if> | パターンで指定された要素が出現した場合,あるいはパターンの比較式が真である場合に,その変換規則の並びを適用する。 |
| <xsl:choose> 場合分けの並び </xsl:choose> | 場合分けを表わす。 |
| <xsl:when test="パターン"> 変換規則の並び </xsl:when> | <xsl:when>は,パターンで指定された要素が出現した場合,あるいはパターンの比較式が真である場合に,その変換規則の並びを適用する。これは場合の数だけ指定する。 |
| <xsl:otherwise> 変換規則の並び </xsl:otherwise> | <xsl:otherwise>は,場合分けの<xsl:when>すべてに一致しない場合に,その変換規則の並びを適用する。 |
| <xsl:for-each select="パターン"> 変換規則の並び </xsl:for-each> | パターンで指定された要素が反復して出現する度に,変換規則の並びを繰り返し適用する。 |
CSSCSS:Cascade Style Sheet,段階スタイルシート は,HTML文書の既定の表示を変更します。次の表はその一部です。
| 特性名 | 特性値 | 意味 |
|---|---|---|
| display | block, inline, list-item, none | 表示の仕方 |
| font-family | 名前 | フォントのファミリ名 |
| font-size | 長さ | フォントのサイズ |
| font-style | normal, italic, oblique | フォントのスタイル |
| line-height | 行の高さ | |
| color | 文字色 | |
| background-color | 色 | 背景色 |
| text-indent | 長さ | 字下げ |
| text-align | left, right, justify, center | 行揃え |
| margin-left | 長さ | 左マージン |
| margin-right | 長さ | 右マージン |
| border-width | 長さ | 境界の線幅 |
| border-color | 色 | 境界の線色 |
CARDS.DTDは,幾つかの個人情報から成る名簿の文書型を定義します。
<!ELEMENT CARDS (CARD+) --名簿--> <!ELEMENT CARD (NAME,ORG?,STATUS?,ADDR,PHONE?) --個人情報--> <!ELEMENT NAME (FAMILY,FIRST) --姓名--> <!ELEMENT FAMILY (#PCDATA) --姓--> <!ELEMENT FIRST (#PCDATA) --姓--> <!ELEMENT ORG (#PCDATA) --組織--> <!ELEMENT STATUS (#PCDATA) --役職--> <!ELEMENT ADDR (#PCDATA) --住所--> <!ELEMENT PHONE (CITY, #PCDATA) --電話番号--> <!ELEMENT CITY (#PCDATA) --市外局番-->
MYCARDS.XMLは,CARDS型で表わされた名簿の一例を表わしている文書インスタンスです。
<?xml version="1.0" encoding="Shift_JIS"?> <?xml-stylesheet type="text/xsl" href="CARDS.XSL"?> <!DOCTYPE BOOKS SYSTEM "CARDS.DTD"> <CARDS> <CARD> <NAME><FAMILY>岸</FAMILY><FIRST>和孝</FIRST></NAME> <ORG>飯豊山書林</ORG> <ADDR>福島県喜多方市松山町鳥見山字下堰下4608</ADDR> <PHONE><CITY>0241</CITY>22-3981</PHONE> </CARD> <CARD> <NAME><FAMILY>北条</FAMILY><FIRST>時宗</FIRST></NAME> <ORG>鎌倉幕府</ORG> <STATUS>執権</STATUS> <ADDR>武蔵国鎌倉鶴岡</ADDR> </CARD> </CARDS>
BOOKS.DTDは,幾つかの書誌情報から成る図書目録の文書型を定義します。
<!ELEMENT BOOKS (BOOK+) --図書目録--> <!ELEMENT BOOK (TITLE,(AUTHOR|TRANSLATOR),PUBLISHER,DATE,ISBN) --書誌情報--> <!ELEMENT TITLE (#PCDATA) --表題--> <!ATTLIST TITLE TITLE CDATA #IMPLIED --原題-- SYLL CDATA #REQUIRED --振り仮名--> <!ELEMENT AUTHOR (#PCDATA) --著者--> <!ELEMENT TRANSLATOR (#PCDATA) --訳者--> <!ATTLIST TRANSLATOR AUTHOR CDATA #IMPLIED --原著者--> <!ELEMENT PUBLISHER (#PCDATA) --出版者--> <!ATTLIST PUBLISHER PUBLISHER CDATA #IMPLIED --原書出版者--> <!ELEMENT DATE (#PCDATA) --発行日--> <!ATTLIST DATE DATE CDATA #IMPLIED --原書発行日--> <!ELEMENT ISBN (#PCDATA) --国際標準図書番号-->
MYBOOKS.XMLは,BOOKS型で表わされた図書目録の一例を表わしている文書インスタンスです。
<?xml version="1.0" encoding="Shift_JIS"?> <?xml-stylesheet type="text/xsl" href="BOOKS.XSL"?> <!DOCTYPE BOOKS SYSTEM "BOOKS.DTD"> <BOOKS> <BOOK><TITLE SYLL="ぱずるほうかい">パズル崩壊</TITLE><AUTHOR>法月綸太郎</AUTHOR><PUBLISHER>集英社</PUBLISHER><DATE>1999/9/25</DATE><ISBN>4-08-747098-9</ISBN></BOOK> <BOOK><TITLE TITLE="SAVAGES" SYLL="ひんしのもり,ゆうしのやり">瀕死の森,勇士の槍</TITLE><TRANSLATOR AUTHOR="Joe Kane">池田真紀子</TRANSLATOR><PUBLISHER PUBLISHER="The Spieler Agency">新潮社</PUBLISHER><DATE DATE="1995">1999/2/1</DATE><ISBN>4-10-218211-X</ISBN></BOOK> <BOOK><TITLE SYLL="そうるとぴょんやん">ソウルと平壌</TITLE><AUTHOR>萩原遼</AUTHOR><PUBLISHER>文藝春秋</PUBLISHER><DATE>1998/10/10</DATE><ISBN>4-16-726004-2</ISBN></BOOK> <BOOK><TITLE SYLL="たにうちろくろうてんらんかい">谷内六郎展覧会</TITLE><AUTHOR>谷内六郎</AUTHOR><PUBLISHER>新潮社</PUBLISHER><DATE>1982/5/25</DATE><ISBN>4-10-125206-8</ISBN></BOOK> <BOOK><TITLE TITLE="UNNATURAL EXPOSURE" SYLL="せっしょく">接触</TITLE><TRANSLATOR AUTHOR="Patricia D. Cornwell">相原真理子</TRANSLATOR><PUBLISHER PUBLISHER="International Creative Management">講談社</PUBLISHER><DATE DATE="1997">1997/12/15</DATE><ISBN>4-06-263659-X</ISBN></BOOK> </BOOKS>
BOOKS.XSLは,MYBOOKS.XMLをHTML文書へ変換するためのスタイルシートです。
<?xml version="1.0" encoding="Shift_JIS"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <HTML> <HEAD> <TITLE>図書目録</TITLE> </HEAD> <BODY> <TABLE BORDER="1"> <TR> <TH>書名</TH> <TH>著者・訳者</TH> <TH>出版者<BR/>(原出版者)</TH> <TH>発行年<BR/>(原発行年)</TH> <TH>ISBN番号</TH> </TR> <xsl:for-each select="BOOKS/BOOK"> <xsl:sort select="TITLE/@SYLL" lang="ja" data-type="text" order="ascending"/> <TR> <TD> <FONT SIZE="+1" COLOR="BLUE"> <xsl:value-of select="TITLE"/> </FONT> <xsl:if test="TITLE/@TITLE"> <BR/>原題:<xsl:value-of select="TITLE/@TITLE"/> </xsl:if> </TD> <TD> <xsl:choose> <xsl:when test="AUTHOR"> <xsl:value-of select="AUTHOR"/> 著 </xsl:when> <xsl:when test="TRANSLATOR"> <xsl:value-of select="TRANSLATOR"/> 訳 <BR/><xsl:value-of select="TRANSLATOR/@AUTHOR"/> 著 </xsl:when> </xsl:choose> </TD> <TD> <xsl:value-of select="PUBLISHER"/> <xsl:if test="PUBLISHER/@PUBLISHER"> <BR/>(<xsl:value-of select="PUBLISHER/@PUBLISHER"/>) </xsl:if> </TD> <TD> <xsl:value-of select="DATE"/> <xsl:if test="DATE/@DATE"> <BR/>(<xsl:value-of select="DATE/@DATE"/>) </xsl:if> </TD> <TD> <xsl:value-of select="ISBN"/> </TD> </TR> </xsl:for-each> </TABLE> </BODY> </HTML> </xsl:template> </xsl:stylesheet>
TEXT.XSLは,このHTML文書(java_xml.htm)をPDFへ変換するためのスタイルシートです。
<?xml version="1.0" encoding="Shift_JIS"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <!-- 書誌情報 --> <xsl:variable name="cover-title"><xsl:value-of select="html/head/title"/></xsl:variable> <xsl:variable name="cover-subtitle"><xsl:value-of select="html/body/span[@class='cover-subtitle']"/></xsl:variable> <xsl:variable name="cover-issue"><xsl:value-of select="html/body/span[@class='cover-issue']"/></xsl:variable> <xsl:variable name="cover-author"><xsl:value-of select="html/body/span[@class='cover-author']"/></xsl:variable> <xsl:variable name="cover-status"><xsl:value-of select="html/body/span[@class='cover-status']"/></xsl:variable> <!-- テンプレート --> <xsl:template match="/"> <xsl:processing-instruction name="cocoon-format">type="text/xslfo"</xsl:processing-instruction> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> <!-- ページの条件 --> <fo:layout-master-set> <fo:simple-page-master master-name="A4-1" page-width="210mm" page-height="297mm" margin-top="20mm" margin-bottom="20mm" margin-left="30mm" margin-right="20mm"> <fo:region-body margin-top="0mm"/> <fo:region-before extent="10mm"/> </fo:simple-page-master> <fo:simple-page-master master-name="A4-2" page-width="210mm" page-height="297mm" margin-top="20mm" margin-bottom="20mm" margin-left="30mm" margin-right="20mm"> <fo:region-body margin-top="10mm"/> <fo:region-before extent="10mm"/> </fo:simple-page-master> <fo:page-sequence-master master-name="basic" > <fo:repeatable-page-master-alternatives> <fo:conditional-page-master-reference master-name="A4-1" page-position="first"/> <fo:conditional-page-master-reference master-name="A4-2" page-position="rest"/> <fo:conditional-page-master-reference master-name="A4-2"/> </fo:repeatable-page-master-alternatives> </fo:page-sequence-master> </fo:layout-master-set> <!-- 表紙 --> <fo:page-sequence master-name="basic"> <fo:flow flow-name="xsl-region-body"> <!-- 表題 --> <fo:block font-size="40pt" font-family="Osaka" background-color="black" color="white" text-align="center" margin-left="20mm" margin-right="20mm" space-before.optimum="50mm" padding-top="10mm" padding-bottom="10mm"> <xsl:value-of select="html/head/title"/> </fo:block> <!-- 副題 --> <fo:block font-family="Osaka" font-size="20pt" text-align="center" space-before.optimum="30mm"> <xsl:copy-of select="$cover-subtitle"/> </fo:block> <!-- 発行日 --> <fo:block font-size="16pt" font-family="Osaka" text-align="center" space-before.optimum="60mm"> <xsl:copy-of select="$cover-issue"/> </fo:block> <!-- 著者 --> <fo:block font-size="20pt" font-family="Osaka" text-align="center" space-before.optimum="20mm"> <xsl:copy-of select="$cover-author"/> </fo:block> <!-- 役職 --> <fo:block font-size="16pt" font-family="Osaka" text-align="center" space-before.optimum="20mm"> <xsl:copy-of select="$cover-status"/> </fo:block> </fo:flow> </fo:page-sequence> <!-- 本文 --> <fo:page-sequence master-name="basic" initial-page-number="1"> <fo:static-content flow-name="xsl-region-before"> <fo:block text-align="end" font-size="10pt" font-family="Osaka"> <xsl:value-of select="html/head/title"/> <fo:page-number/> </fo:block> </fo:static-content> <fo:flow flow-name="xsl-region-body"> <xsl:apply-templates select="html/body"/> </fo:flow> </fo:page-sequence> <!-- 奥付 --> <fo:page-sequence master-name="basic"> <fo:flow flow-name="xsl-region-body"> <fo:block border-width="0.5mm" background-color="lime" break-before="page" space-before.optimum="100mm" margin-left="40mm" margin-right="40mm" text-align="start"> <fo:block font-family="Osaka" font-size="12pt" line-height="14pt" text-align="center"> <xsl:copy-of select="$cover-title"/> </fo:block> <fo:block font-family="Osaka" font-size="10pt" line-height="12pt" text-align="center"> - <xsl:copy-of select="$cover-subtitle"/> - </fo:block> <fo:block font-family="Osaka" font-size="10pt" line-height="14pt" text-align="center"> (C) <xsl:copy-of select="$cover-issue"/> </fo:block> <fo:block font-family="Osaka" font-size="12pt" line-height="14pt" text-align="center"> <xsl:copy-of select="$cover-author"/> </fo:block> </fo:block> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> <!-- 章の見出し --> <xsl:template match="html/body/h1"> <fo:block font-size="18pt" font-family="Osaka" line-height="20pt" text-align="center" space-before.optimum="8pt" space-after.optimum="8pt" break-before="page"> 第<xsl:number/>章 <xsl:apply-templates/> </fo:block> </xsl:template> <!-- 節の見出し --> <xsl:template match="html/body/h2"> <fo:block font-size="16pt" font-family="Osaka" line-height="18pt" text-align="start" text-indent="-10pt" margin-left="-10pt" space-before.optimum="8pt" space-after.optimum="8pt"> <xsl:number level="any" count="h1"/>.<xsl:number level="any" from="h1" count="h2"/> <xsl:apply-templates/> </fo:block> </xsl:template> <!-- 項の見出し --> <xsl:template match="html/body/h3"> <fo:block font-size="14pt" font-family="Osaka" line-height="16pt" text-align="start" text-indent="-10pt" margin-left="-10pt" space-before.optimum="8pt" space-after.optimum="8pt"> <xsl:apply-templates/> </fo:block> </xsl:template> <xsl:template match="html/body/h4"> <fo:block font-size="12pt" font-family="Osaka" line-height="14pt" text-align="start" text-indent="-10pt" margin-left="-6pt" space-before.optimum="8pt" space-after.optimum="8pt"> <xsl:apply-templates/> </fo:block> </xsl:template> <!-- 段落 --> <xsl:template match="html/body/p"> <fo:block font-size="12pt" font-family="Osaka" line-height="14pt" text-align="justify" text-indent="12pt" space-before.optimum="4pt" space-after.optimum="4pt"> <xsl:apply-templates/> </fo:block> </xsl:template> <xsl:template match="html/body/pre"> <xsl:choose> <!-- 目次 --> <xsl:when test="@class[.='toc']"> <fo:block font-size="16pt" font-family="Osaka" line-height="18pt" text-align="center"> 目次 </fo:block> <fo:table space-before.optimum="8pt" space-after.optimum="8pt"> <fo:table-column column-width="160mm"/> <fo:table-body> <fo:table-row> <fo:table-cell background-color="white"> <fo:block font-size="12pt" font-family="Osaka" line-height="14pt" white-space-collapse="false"> <xsl:apply-templates/> </fo:block> </fo:table-cell> </fo:table-row> </fo:table-body> </fo:table> </xsl:when> <!-- ソースコード --> <xsl:when test="@class[.='code']"> <fo:table space-before.optimum="8pt" space-after.optimum="8pt"> <fo:table-column column-width="160mm"/> <fo:table-body> <fo:table-row> <fo:table-cell background-color="lightblue"> <fo:block font-size="12pt" font-family="Osaka" line-height="14pt" white-space="pre" white-space-collapse="false"> <xsl:apply-templates/> </fo:block> </fo:table-cell> </fo:table-row> </fo:table-body> </fo:table> </xsl:when> <!-- 画面表示内容 --> <xsl:when test="@class[.='window']"> <fo:table space-before.optimum="8pt" space-after.optimum="8pt"> <fo:table-column column-width="160mm"/> <fo:table-body> <fo:table-row> <fo:table-cell background-color="yellow"> <fo:block font-size="12pt" font-family="Osaka" line-height="14pt" white-space-collapse="false"> <xsl:apply-templates/> </fo:block> </fo:table-cell> </fo:table-row> </fo:table-body> </fo:table> </xsl:when> </xsl:choose> </xsl:template> <!-- テーブル --> <xsl:template match="html/body/table"> <fo:table space-before.optimum="8pt" space-after.optimum="8pt"> <xsl:apply-templates select="span"/> <fo:table-body> <xsl:apply-templates select="tr"/> </fo:table-body> </fo:table> </xsl:template> <xsl:template match="html/body/table/tr"> <fo:table-row> <xsl:apply-templates/> </fo:table-row> </xsl:template> <xsl:template match="html/body/table/tr/th"> <fo:table-cell border-width="0.5mm" background-color="aqua"> <fo:block font-family="Osaka" font-size="10pt" text-align="center"> <xsl:apply-templates/> </fo:block> </fo:table-cell> </xsl:template> <xsl:template match="html/body/table/tr/td"> <fo:table-cell border-width="0.5mm" background-color="pink"> <fo:block font-family="Osaka" font-size="10pt"> <xsl:apply-templates/> </fo:block> </fo:table-cell> </xsl:template> <!-- 箇条書き --> <xsl:template match="html/body/ul"> <fo:list-block space-before.optimum="8pt" space-after.optimum="8pt"> <xsl:apply-templates/> </fo:list-block > </xsl:template> <xsl:template match="html/body/ul/li"> <fo:list-item> <fo:list-item-label> <fo:block> <fo:inline font-family="Osaka">・</fo:inline> </fo:block> </fo:list-item-label> <fo:list-item-body> <fo:block font-family="Osaka"> <xsl:apply-templates/> </fo:block> </fo:list-item-body> </fo:list-item> </xsl:template> <xsl:template match="html/body/dl"> <fo:list-block space-before.optimum="8pt" space-after.optimum="8pt"> <xsl:apply-templates/> </fo:list-block > </xsl:template> <xsl:template match="html/body/dl/dt"> <fo:list-item> <fo:list-item-label> <fo:block> <fo:inline font-family="Osaka">・</fo:inline> </fo:block> </fo:list-item-label> <fo:list-item-body> <fo:block font-family="Osaka"> <xsl:apply-templates/> </fo:block> </fo:list-item-body> </fo:list-item> </xsl:template> <xsl:template match="html/body/dl/dt/dd"> <fo:list-item font-family="Osaka" margin-left="12pt"> <fo:list-item-label> <fo:block> <fo:inline font-family="Osaka">-</fo:inline> </fo:block> </fo:list-item-label> <fo:list-item-body> <fo:block> <xsl:apply-templates/> </fo:block> </fo:list-item-body> </fo:list-item> </xsl:template> <xsl:template match="//span"> <xsl:choose> <!-- テーブルのカラム幅 --> <xsl:when test="@class[.='column-width']"> <fo:table-column> <xsl:attribute name="column-width"><xsl:value-of select="."/></xsl:attribute> </fo:table-column> </xsl:when> <!-- 脚注 --> <xsl:when test="@class[.='footnote']"> <fo:footnote> <fo:inline font-family="Osaka" font-size="6pt" color="green" vertical-align="super"> [<xsl:number level="any" from="h1"/>]</fo:inline> <fo:footnote-body> <fo:block font-family="Osaka" font-size="10pt" color="green" text-indent="-20pt" margin-left="-5pt"> [<xsl:number level="any" from="h1"/>]<xsl:apply-templates/> </fo:block> </fo:footnote-body> </fo:footnote> </xsl:when> </xsl:choose> </xsl:template> <!-- リンク --> <xsl:template match="//a"> <xsl:choose> <xsl:when test="substring(@href,1,4)='http'"> <fo:inline> <fo:basic-link color="blue"> <xsl:attribute name="external-destination"><xsl:value-of select="@href"/></xsl:attribute> <xsl:apply-templates/> </fo:basic-link> </fo:inline> </xsl:when> <xsl:when test="substring(@href,1,3)='ftp'"> <fo:inline> <fo:basic-link color="blue"> <xsl:attribute name="external-destination"><xsl:value-of select="@href"/></xsl:attribute> <xsl:apply-templates/> </fo:basic-link> </fo:inline> </xsl:when> <xsl:when test="substring(@href,1,6)='mailto'"> <fo:inline white-space="nowrap"> <fo:basic-link color="blue"> <xsl:attribute name="external-destination"><xsl:value-of select="@href"/></xsl:attribute> <xsl:apply-templates/> </fo:basic-link> </fo:inline> </xsl:when> <xsl:when test="substring(@href,1,1)='#'"> <fo:inline> <fo:basic-link color="blue"> <xsl:attribute name="internal-destination"><xsl:value-of select="substring(@href,2)"/></xsl:attribute> <xsl:apply-templates/> </fo:basic-link> </fo:inline> </xsl:when> <xsl:when test="@name"> <fo:inline> <xsl:attribute name="id"><xsl:value-of select="@name"/></xsl:attribute> <xsl:apply-templates/> </fo:inline> </xsl:when> <xsl:otherwise> ???<xsl:apply-templates/>??? </xsl:otherwise> </xsl:choose> </xsl:template> <!-- 外部画像 --> <xsl:template match="//img"> <fo:inline> <fo:external-graphic> <xsl:attribute name="src">file:<xsl:value-of select="@src"/></xsl:attribute> </fo:external-graphic> </fo:inline> </xsl:template> <!-- 上付き文字 --> <xsl:template match="//sup"> <fo:inline font-family="Osaka" font-size="6pt" vertical-align="super"> <xsl:apply-templates/> </fo:inline> </xsl:template> <!-- 下付き文字 --> <xsl:template match="//sub"> <fo:inline font-family="Osaka" font-size="6pt" vertical-align="sub"> <xsl:apply-templates/> </fo:inline> </xsl:template> <!-- テキスト内容 --> <xsl:template match="text()"> <xsl:value-of select="."/> </xsl:template> </xsl:stylesheet>
処理に先立って,このHTML文書(java_xml.htm)の先頭に次の宣言を追加しXML文書としてください。
<?xml version="1.0" encoding="Shift_JIS"?>
このHTML文書では,冊子形式を表わすためにHTML文書型に次のような拡張解釈を与えています。ウェブブラウザーにおいてこれらがPDFと(全く同じにはなりませんが)同様なスタイルで表示されるようにCSS によって指示しています。
| HTMLタグ |
|---|
| <span class="cover-subtitle">副題</span> |
| <span class="cover-issue">発行日</span> |
| <span class="cover-author">著者</span> |
| <span class="cover-status">役職</span> |
| <span class="column-width">テーブルのカラム幅</span> |
| <span class="footnote">脚注</span> |
| <pre class="toc">目次の区画</pre> |
| <pre class="code">ソースコードの区画</pre> |