Java では、XML ドキュメントをネイティブに解析する方法が 2 つあります。つまり、 Dom 解析と Sax 解析です。
Dom 解析機能は強力で、操作中に XML ドキュメントがドキュメント オブジェクトの形式でメモリに読み込まれるため、小規模なドキュメントに適しています。
Sax の解析では、内容を 1 行ずつ、要素ごとに最初から最後まで読み取ります。変更するのはより不便ですが、大規模な読み取り専用ドキュメントに適しています。
この記事では主に Sax の構文解析について説明し、残りは後ほど説明します。
Sax はイベント駆動型のアプローチを使用してドキュメントを解析します。簡単に言うと、映画館で映画を観ているようなものです。最初から最後まで戻らずに見ることができます(前後に読むことができます)。
映画を観ている途中で、ストーリーや涙、肩を並べるような出来事に遭遇するたびに、その情報を受け取ったり処理したりするために脳と神経を総動員することになります。
同様に、Sax の解析プロセス中に、ドキュメントの先頭と末尾、および要素の先頭と末尾を読み取ると、いくつかのコールバック メソッドがトリガーされ、これらのコールバック メソッドで対応するイベント処理を実行できます。
4 つのメソッドは、 startDocument()、endDocument()、startElement()、endElementです。
さらに、ノードを読み取るだけでは十分ではなく、要素に含まれるコンテンツを注意深く処理するためにcharacters()メソッドも必要です。
これらのコールバック メソッドを集めることでクラスが形成され、これが必要なトリガーになります。
通常、ドキュメントは Main メソッドから読み込まれますが、ドキュメントはトリガーで処理されます。これは、いわゆるイベント駆動型の解析方法です。
上に示したように、トリガーではまずドキュメントの読み取りを開始し、次に要素を 1 つずつ解析し始め、各要素の内容がcharacters() メソッドに返されます。
次に、要素の読み取りを終了します。すべての要素が読み取られた後、ドキュメントの解析を終了します。
次に、トリガー クラスの作成を開始します。このクラスを作成するには、まず DefaultHandler を継承する必要があります。
SaxHandler を作成し、対応するメソッドをオーバーライドします。
パブリック クラス SaxHandler extends DefaultHandler {
/* このメソッドには 3 つのパラメータがあります
arg0 は返される文字配列であり、要素の内容が含まれます。
arg1 と arg2 はそれぞれ配列の開始位置と終了位置です*/
@オーバーライド
public voidcharacters(char[] arg0, int arg1, int arg2) throws SAXException {
文字列コンテンツ = new String(arg0, arg1, arg2);
System.out.println(コンテンツ);
super.characters(arg0, arg1, arg2);
}
@オーバーライド
public void endDocument() は SAXException をスローします {
System.out.println("/n...ドキュメントの解析を終了...");
super.endDocument();
}
/* arg0 は名前空間です
arg1 は名前空間を含むラベルです。名前空間がない場合は空です。
arg2 は名前空間のないラベルです*/
@オーバーライド
public void endElement(文字列 arg0, 文字列 arg1, 文字列 arg2)
SAXException をスローします {
System.out.println("解析要素の終了" + arg2);
super.endElement(arg0, arg1, arg2);
}
@オーバーライド
public void startDocument() は SAXException をスローします {
System.out.println("…………ドキュメントの解析を開始します………/n");
super.startDocument();
}
/*arg0 は名前空間です
arg1 は名前空間を含むラベルです。名前空間がない場合は空です。
arg2 は名前空間のないラベルです
arg3 は明らかに属性のコレクションです*/
@オーバーライド
public void startElement(String arg0, String arg1, String arg2,
属性 arg3) が SAXException をスローする {
System.out.println("要素の解析を開始" + arg2);
if (arg3 != null) {
for (int i = 0; i < arg3.getLength(); i++) {
// getQName() は属性名を取得するためのものです。
System.out.print(arg3.getQName(i) + "=/"" + arg3.getValue(i) + "/"");
}
}
System.out.print(arg2 + ":");
super.startElement(arg0, arg1, arg2, arg3);
}
}
インポート javax.xml.parsers.SAXParser;
インポート javax.xml.parsers.SAXParserFactory;
パブリック クラス TestDemo {
public static void main(String[] args) throws Exception {
// 1. SAXParserFactory オブジェクトをインスタンス化します。
SAXParserFactory ファクトリ = SAXParserFactory.newInstance();
// 2. パーサーを作成する
SAXParser パーサー = Factory.newSAXParser();
// 3. 解析する必要があるドキュメントを取得し、パーサーを生成し、最後にドキュメントを解析します
ファイル f = 新しい File("books.xml");
SaxHandler dh = new SaxHandler();
parser.parse(f, dh);
}
}
要素ブックの解析を開始します
本:
要素ブックの解析を開始します
id="001"本:
要素タイトルの解析を開始します
タイトル:ハリー・ポッター
要素のタイトルの解析を終了します
要素の作成者の解析を開始する
著者:J・K・ローリング
要素の解析終了の作成者
解析要素ブックの終了
要素ブックの解析を開始します
id="002"本:
要素タイトルの解析を開始します
タイトル:XML の学習
要素のタイトルの解析を終了します
要素の作成者の解析を開始する
著者:エリック・T・レイ
要素の解析終了の作成者
解析要素ブックの終了
要素の解析を終了するブック
…………文書の解析を終了…………
このプロセスをより明確に実行するために、SaxHandler を書き換えて元の XML ドキュメントを復元することもできます。
オーバーライドされた SaxHandler クラス:
パブリック クラス SaxHandler extends DefaultHandler {
@オーバーライド
public voidcharacters(char[] arg0, int arg1, int arg2) throws SAXException {
System.out.print(new String(arg0, arg1, arg2));
super.characters(arg0, arg1, arg2);
}
@オーバーライド
public void endDocument() は SAXException をスローします {
System.out.println("/n は解析を終了します");
super.endDocument();
}
@オーバーライド
public void endElement(文字列 arg0, 文字列 arg1, 文字列 arg2)
SAXException をスローします {
System.out.print("</");
System.out.print(arg2);
System.out.print(">");
super.endElement(arg0, arg1, arg2);
}
@オーバーライド
public void startDocument() は SAXException をスローします {
System.out.println("解析開始");
文字列 s = "<?xml バージョン =/"1.0/" エンコーディング =/"UTF-8/"?>";
System.out.println;
super.startDocument();
}
@オーバーライド
public void startElement(String arg0, String arg1, String arg2,
属性 arg3) が SAXException をスローする {
System.out.print("<");
System.out.print(arg2);
if (arg3 != null) {
for (int i = 0; i < arg3.getLength(); i++) {
System.out.print(" " + arg3.getQName(i) + "=/"" + arg3.getValue(i) + "/"");
}
}
System.out.print(">");
super.startElement(arg0, arg1, arg2, arg3);
}
}
見た目はかなり良くなり、復元すると解析プロセスがよりわかりやすくなります。