XMLパーサーに関する記事をいくつか読みましたが、SAXおよびDOM。
SAXはイベントベースで、DOMはツリーモデルです。 - これらの概念の違いがわかりません。
私が理解したことから、イベントベースとは、ある種のイベントがノードに発生することを意味します。特定のノードをクリックしたときのように、すべてのノードを同時にロードするのではなく、すべてのサブノードを表示します。しかし、DOM解析の場合は、すべてのノードをロードしてツリーモデルを作成します。
私の理解は正しいですか?
間違っている場合は訂正してください、またはイベントベースのツリーモデルを簡単な方法で説明してください。
まあ、あなたは近いです。
SAXでは、XMLが解析されているときにイベントが発生します。パーサーがXMLを解析しているときにタグの開始(例えば<something>
)に遭遇すると、それはtagStarted
イベントをトリガーします(実際のイベント名は異なる場合があります)。同様に、解析中にタグの終わりに到達すると(</something>
)、それはtagEnded
をトリガーします。 SAXパーサーを使用すると、これらのイベントを処理し、各イベントで返されるデータを理解する必要があります。
DOMでは、解析中に発生するイベントはありません。 XML全体が解析され、(XML内のノードの)DOMツリーが生成されて返されます。一度解析されると、ユーザはツリー内を移動して、XML内のさまざまなノードに以前に埋め込まれているさまざまなデータにアクセスできます。
一般に、DOMのほうが使いやすいですが、使用する前にXML全体を解析するというオーバーヘッドがあります。
ほんの少しの言葉で...
SAX (SimplementsAPI =XML):ストリームベースのプロセッサです。メモリ内にはごく一部しかなく、tagStarted()
などのイベント用のコールバックコードを実装することでXMLストリームを "スニッフィング"します。メモリをほとんど使用しませんが、xpathやuse xpathのような "DOM"はできません。木を横断します。
DOM (DocumentObjectModel):あなたは全部をメモリにロードします - それは巨大なメモリの独占者です。中サイズの文書でもメモリを増やすことができます。しかし、あなたはxpathを使うことができ、木などを横断することができます。
ここで簡単な言葉で:
DOM
ツリーモデルパーサ(オブジェクトベース)(ノードのツリー)。
DOMはファイルをメモリにロードしてからファイルを解析します。
構文解析の前にXMLファイル全体をロードするため、メモリーに制約があります。
DOMは読み書き可能です(ノードを挿入または削除できます)。
XMLコンテンツが小さい場合は、DOMパーサーを使用してください。
タグの検索とタグ内の情報の評価には、後方検索と前方検索が可能です。だからこれはナビゲーションの容易さを与えます。
実行時に遅くなります。
SAX
イベントベースのパーサ(イベントのシーケンス).
SAXはファイルの読み取り時にファイルを解析します。つまり、ノードごとに解析します。
XMLコンテンツをメモリに格納しないため、メモリの制約はありません。
SAXは読み取り専用です。つまり、ノードを挿入または削除することはできません。
メモリの内容が大きい場合はSAXパーサーを使用してください。
SAXはXMLファイルを上から下に読み、後方への移動はできません。
実行時間が短縮されました。
あなたは、DOMベースのモデルを正しく理解しています。 XMLファイルは全体としてロードされ、そのすべての内容は文書が表すツリーのインメモリ表現として構築されます。入力ファイルの大きさによっては、時間とメモリを消費する可能性があります。この方法の利点は、ドキュメントの任意の部分を簡単にクエリし、ツリー内のすべてのノードを自由に操作できることです。
DOMアプローチは通常、小さなXML構造(プラットフォームの処理能力とメモリ容量によって異なります)に使用されます。ロードされた後は、さまざまな方法で変更およびクエリを行う必要があります。
一方、SAXは事実上あらゆるサイズのXML入力を処理するように設計されています。 XMLフレームワークが文書の構造を把握し、すべてのノード、属性などに対して潜在的に多数のオブジェクトを準備するのに苦労するのではなく、SAXは完全にそれをあなたに任せます。
基本的には、先頭からの入力を読み取り、特定の「イベント」が発生したときに提供されたコールバックメソッドを呼び出すことです。イベントは、開始タグ、タグ内の属性、要素内のテキストの検索、または終了タグに遭遇することがあります。
SAXは頑固に入力を読み、それがこのやり方で見ていることをあなたに告げます。あなたが必要とするすべての状態情報を維持することはあなた次第です。通常これはある種のステートマシンを構築することを意味します。
このXML処理へのアプローチはもっと面倒ですが、非常に強力な場合もあります。ブログフィードからニュース記事のタイトルを抽出するだけの場合を考えます。 DOMを使ってこのXMLを読むと、たとえあなたがそれに興味を持っていなくても、XMLに含まれるすべての記事の内容、すべての画像などをメモリにロードするでしょう。
SAXを使用すると、 "startTag"イベントメソッドが呼び出されるたびに、要素名が(たとえば) "title"であるかどうかを確認できます。もしそうなら、あなたはあなたが次の "elementText"イベントがあなたに提供するものは何でも追加する必要があることを知っています。 "endTag"イベント呼び出しを受け取ったら、これが "title"の終了要素かどうかをもう一度確認します。その後は、入力が終了するか、 "title"という名前の別の "startTag"が表示されるまで、他のすべての要素を無視します。等々...
このようにして、メガバイトから数メガバイトのXMLを読み取ることができ、必要な少量のデータを抽出するだけです。
このアプローチのマイナス面は、もちろん、抽出する必要があるデータやXML構造がどれほど複雑であるかに応じて、もっと自分で帳簿を作成する必要があることです。さらに、XMLツリーの構造を変更することはできません。なぜなら、それを全体として手にすることは決してないからです。
したがって、一般的に、SAXは、特定の「クエリ」を念頭に置いて受け取る可能性のある大量のデータを処理するのに適していますが、変更する必要はありません。より高い資源需要の。
あなたはリンゴとナシを比較しています。 SAXは、シリアル化されたDOM構造を解析するparserです。さまざまなパーサーがあり、「イベントベース」とは構文解析方法のことです。
たぶん小さな要約をするべきです:
ドキュメントオブジェクトモデル(DOM)は、階層的なツリーベースのドキュメント構造を記述する抽象データモデルです。ドキュメントツリーはnodes、すなわち要素、属性、テキストノード(そして他のいくつか)から成ります。ノードには、親、兄弟、そして子供がいて、トラバースすることができます。JavaScriptを実行するのに慣れ親しんだすべてのこと(偶然にもDOMとは関係ありません)。
DOM構造は、シリアライズされた、すなわち、HTMLまたはXMLのようなマークアップ言語を使用してファイルに書き込まれることができる。したがって、HTMLファイルまたはXMLファイルには、「書き出された」バージョンまたは「平坦化された」バージョンの抽象ドキュメントツリーが含まれます。
ファイルからDOMツリーを操作したり表示したりするには、ファイルをdeserializeまたはparseにして抽象ツリーを再構築する必要があります。メモリ内。これが構文解析の始まりです。
今度は私達はパーサーの性質に来ます。解析する1つの方法は、文書全体を読み込み、再帰的にメモリ内にツリー構造を構築し、最後に結果全体をユーザーに公開することです。 (私はあなたがこれらのパーサーを「DOMパーサー」と呼ぶことができると思います。)それはユーザーにとって非常に便利でしょう(私はそれがPHPのXMLパーサーがするものであると思います)。
一方、event-based構文解析はSAXと同様にファイルを直線的に見て、出会ったときはいつでも単純にcall-backsにします。 「この要素は始まった」、「その要素は終わった」、「ここにあるテキスト」などのような構造的なデータです。これは、入力ファイルのサイズを気にせずに永遠に続くことができるという利点があります。ユーザーが実際の処理作業をすべて行う必要があるため(コールバックを提供するため)、低レベルです。元の質問に戻ると、「イベントベース」という用語は、パーサーがXMLファイルをトラバースするときに発生する構文解析イベントを指します。
ウィキペディアの記事 には、SAX構文解析の段階に関する詳細が多数記載されています。
この質問に対する一般的なQ&A指向の回答を提供します。
質問への回答
なぜXMLパーサーが必要なのですか?
アプリケーション内のすべてを最初から実行するのではなく、非常に低レベルで何かを実行するために「ヘルパー」プログラムまたはライブラリーが必要なので、XMLパーサーが必要です。これらの低レベルだが必要なことには、整形式性のチェック、DTDまたはスキーマに対する文書の検証(パーサーの検証のみ)、文字参照の解決、CDATAセクションの理解などがあります。 XMLパーサーはまさにそのような「ヘルパー」プログラムであり、それらはすべてこれらの仕事をします。 XMLパーサーを使用すると、これらの複雑な部分から保護され、パーサーによって実装されたAPIを介して高水準のプログラミングのみに集中することができ、その結果プログラミング効率が向上します。
SAXとDOMのどちらが優れていますか。
SAXとDOMパーサーの両方にはそれぞれ長所と短所があります。どちらが良いかは、アプリケーションの特性によって異なります(以下の質問を参照してください)。
DOMパーサーとSAXパーサーのどちらの方が速度が向上しますか。
SAXパーサーはより良い速度を得ることができます。
ツリーベースのAPIとイベントベースのAPIの違いは何ですか?
ツリーベースのAPIはツリー構造を中心としているため、Documentインターフェイス、Nodeインターフェイス、NodeListインターフェイス、Elementインターフェイス、Attrインターフェイスなど、ツリーのコンポーネント(DOMドキュメント)に対するインターフェイスを提供します。しかしこれとは対照的に、イベントベースのAPIはハンドラ上にインタフェースを提供します。 ContentHandlerインターフェース、DTDHandlerインターフェース、EntityResolverインターフェース、およびErrorHandlerインターフェースの4つのハンドラーインターフェースがあります。
DOMパーサーとSAXパーサーの違いは何ですか?
DOMパーサーとSAXパーサーは異なる方法で機能します。
DOMパーサーは、入力文書からメモリー内にツリー構造を作成してから、クライアントからの要求を待ちます。しかし、SAXパーサーは内部構造を作成しません。代わりに、入力文書のコンポーネントの発生をイベントとして受け取り、入力文書を読むときに何を読むかをクライアントに伝えます。 A
DOMパーサーは、クライアントが実際に必要とする量に関係なく、常にドキュメント全体をクライアントアプリケーションに提供します。しかし、SAXパーサーは常にクライアントアプリケーションにドキュメントの一部だけを提供します。
どのパーサが良いかをどうやって決めるのですか?
理想的には、優れたパーサは速く(時間効率がよく)、スペース効率が良く、機能が豊富で使いやすいものであるべきです。しかし、実際には、メインパーサのどれもが同時にこれらすべての機能を持っていません。たとえば、DOM Parserは機能が豊富です(メモリ内にDOMツリーを作成し、ドキュメントの任意の部分に繰り返しアクセスでき、DOMツリーを変更できるため)。ただし、ドキュメントが巨大な場合はスペース効率が悪くなります。そしてそれをどのように使うかを学ぶのに少し時間がかかります。ただし、SAXパーサーは、大きな入力文書の場合ははるかにスペース効率がよくなります(内部構造が作成されないため)。さらに、そのAPIは本当に単純なので、DOM Parserよりも速く実行され、習得が容易です。しかし、機能的な観点からは、提供される機能が少なくなるため、独自のデータ構造を作成するなど、ユーザー自身がより多くの面倒を見る必要があります。ところで、良いパーサは何ですか?答えは本当にあなたのアプリケーションの特性に依存すると思います。
SAXパーサーを使用する方がDOMパーサーを使用するよりも有利であり、またその逆の場合がある、実際のアプリケーションは何ですか? DOMパーサーとSAXパーサーの通常のアプリケーションは何ですか?
以下の場合、SAXパーサーを使用する方がDOMパーサーを使用するよりも有利です。
以下の場合、DOMパーサーを使用する方がSAXパーサーを使用するよりも有利です。
例(DOMパーサーまたはSAXパーサーを使用しますか?):
インストラクターが生徒の個人情報とクラスで得た点をすべて含むXML文書を持っているとします。そして、彼は現在、アプリケーションを使用して生徒に最終評点を割り当てています。彼が作りたがっているのは、SSNと成績のリストです。また、彼のアプリケーションでは、講師は生徒の個人情報とポイントを格納するために配列などのデータ構造を使用しないと仮定します。インストラクターがクラス平均以上を獲得した人にAを与え、他の人にBを与えることにした場合、彼のアプリケーションではDOMパーサーを使用するほうがよいでしょう。その理由は、文書全体が処理されるまでにクラスの平均がいくらであるかを知る方法がないためです。彼のアプリケーションでは、まずすべての生徒の得点を調べて平均を計算し、次に文書をもう一度調べて得た得点をクラスの平均と比較して各生徒に最終評点を割り当てる必要があります。 。ただし、90ポイント以上を獲得した生徒にはAを割り当て、他の生徒にはBを割り当てるという等級付けポリシーを講師が採用する場合は、おそらくSAXパーサーを使用したほうがよいでしょう。その理由は、各生徒に最終評点を割り当てるために、彼は文書全体が処理されるのを待つ必要がないということです。 SAXパーサーがこの学生の成績を読んだら、彼はすぐに成績を学生に割り当てることができます。上記の分析では、インストラクタは自分自身のデータ構造を作成しなかったと仮定しました。 SSNを格納するための文字列の配列やポイントを格納するための整数の配列など、独自のデータ構造を作成したとしたらどうでしょうか。この場合、SAXの方がメモリと時間の両方を節約することができ、それでも仕事を終わらせることができる前に、SAXがより良い選択だと思います。それでは、この例についてもう1つ検討してください。講師がリストを印刷せずに、元の文書を各学生の成績を更新して保存することを目的としている場合はどうなりますか。この場合、どのグレーディングポリシーを採用しているかに関係なく、DOMパーサーがより良い選択になるはずです。彼は自分自身のデータ構造を作成する必要はありません。彼がする必要があるのは、最初にDOMツリーを修正し(すなわち、値を 'grade'ノードに設定し)、次に修正したツリー全体を保存することです。 DOMパーサーの代わりにSAXパーサーを使用することを選択した場合は、この場合、仕事を終える前にDOMツリーとほぼ同じくらい複雑なデータ構造を作成する必要があります。
問題文:与えられたXML文書の要素である円に関するすべての情報を抽出するためのJavaプログラムを書きなさい。各circle要素には、カラー属性だけでなく、3つの子要素(つまり、x、y、およびradius)があるとします。サンプル文書を以下に示します。
<?xml version="1.0"?>
<!DOCTYPE shapes [
<!ELEMENT shapes (circle)*>
<!ELEMENT circle (x,y,radius)>
<!ELEMENT x (#PCDATA)>
<!ELEMENT y (#PCDATA)>
<!ELEMENT radius (#PCDATA)>
<!ATTLIST circle color CDATA #IMPLIED>
]>
<shapes>
<circle color="BLUE">
<x>20</x>
<y>20</y>
<radius>20</radius>
</circle>
<circle color="RED" >
<x>40</x>
<y>40</y>
<radius>20</radius>
</circle>
</shapes>
DOMparserを使ったプログラム
import Java.io.*;
import org.w3c.dom.*;
import org.Apache.xerces.parsers.DOMParser;
public class shapes_DOM {
static int numberOfCircles = 0; // total number of circles seen
static int x[] = new int[1000]; // X-coordinates of the centers
static int y[] = new int[1000]; // Y-coordinates of the centers
static int r[] = new int[1000]; // radius of the circle
static String color[] = new String[1000]; // colors of the circles
public static void main(String[] args) {
try{
// create a DOMParser
DOMParser parser=new DOMParser();
parser.parse(args[0]);
// get the DOM Document object
Document doc=parser.getDocument();
// get all the circle nodes
NodeList nodelist = doc.getElementsByTagName("circle");
numberOfCircles = nodelist.getLength();
// retrieve all info about the circles
for(int i=0; i<nodelist.getLength(); i++) {
// get one circle node
Node node = nodelist.item(i);
// get the color attribute
NamedNodeMap attrs = node.getAttributes();
if(attrs.getLength() > 0)
color[i]=(String)attrs.getNamedItem("color").getNodeValue();
// get the child nodes of a circle node
NodeList childnodelist = node.getChildNodes();
// get the x and y value
for(int j=0; j<childnodelist.getLength(); j++) {
Node childnode = childnodelist.item(j);
Node textnode = childnode.getFirstChild();//the only text node
String childnodename=childnode.getNodeName();
if(childnodename.equals("x"))
x[i]= Integer.parseInt(textnode.getNodeValue().trim());
else if(childnodename.equals("y"))
y[i]= Integer.parseInt(textnode.getNodeValue().trim());
else if(childnodename.equals("radius"))
r[i]= Integer.parseInt(textnode.getNodeValue().trim());
}
}
// print the result
System.out.println("circles="+numberOfCircles);
for(int i=0;i<numberOfCircles;i++) {
String line="";
line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")";
System.out.println(line);
}
} catch (Exception e) {e.printStackTrace(System.err);}
}
}
SAXparserによるプログラム
import Java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.Apache.xerces.parsers.SAXParser;
public class shapes_SAX extends DefaultHandler {
static int numberOfCircles = 0; // total number of circles seen
static int x[] = new int[1000]; // X-coordinates of the centers
static int y[] = new int[1000]; // Y-coordinates of the centers
static int r[] = new int[1000]; // radius of the circle
static String color[] = new String[1000]; // colors of the circles
static int flagX=0; //to remember what element has occurred
static int flagY=0; //to remember what element has occurred
static int flagR=0; //to remember what element has occurred
// main method
public static void main(String[] args) {
try{
shapes_SAX SAXHandler = new shapes_SAX (); // an instance of this class
SAXParser parser=new SAXParser(); // create a SAXParser object
parser.setContentHandler(SAXHandler); // register with the ContentHandler
parser.parse(args[0]);
} catch (Exception e) {e.printStackTrace(System.err);} // catch exeptions
}
// override the startElement() method
public void startElement(String uri, String localName,
String rawName, Attributes attributes) {
if(rawName.equals("circle")) // if a circle element is seen
color[numberOfCircles]=attributes.getValue("color"); // get the color attribute
else if(rawName.equals("x")) // if a x element is seen set the flag as 1
flagX=1;
else if(rawName.equals("y")) // if a y element is seen set the flag as 2
flagY=1;
else if(rawName.equals("radius")) // if a radius element is seen set the flag as 3
flagR=1;
}
// override the endElement() method
public void endElement(String uri, String localName, String rawName) {
// in this example we do not need to do anything else here
if(rawName.equals("circle")) // if a circle element is ended
numberOfCircles += 1; // increment the counter
}
// override the characters() method
public void characters(char characters[], int start, int length) {
String characterData =
(new String(characters,start,length)).trim(); // get the text
if(flagX==1) { // indicate this text is for <x> element
x[numberOfCircles] = Integer.parseInt(characterData);
flagX=0;
}
else if(flagY==1) { // indicate this text is for <y> element
y[numberOfCircles] = Integer.parseInt(characterData);
flagY=0;
}
else if(flagR==1) { // indicate this text is for <radius> element
r[numberOfCircles] = Integer.parseInt(characterData);
flagR=0;
}
}
// override the endDocument() method
public void endDocument() {
// when the end of document is seen, just print the circle info
System.out.println("circles="+numberOfCircles);
for(int i=0;i<numberOfCircles;i++) {
String line="";
line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")";
System.out.println(line);
}
}
}
実用的には:book.xml
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
</bookstore>
start element:abc
、end element:abc
のようなイベントベースとして提示します。このXML文書は、SAXパーサーを介して渡されると、次のような一連のイベントを生成します 。
start element: bookstore
start element: book with an attribute category equal to cooking
start element: title with an attribute lang equal to en
Text node, with data equal to Everyday Italian
....
end element: title
.....
end element: book
end element: bookstore
DOMはDocument Object Modelの略で、XML文書をツリー形式に表現したもので、各要素がツリーを表しています。 DOMパーサーはXMLファイルのインメモリーツリー表現を作成してそれを解析するので、Java.lang.OutOfMemoryError:Javaヒープスペースを回避するためには、より多くのメモリーが必要で、DOMパーサーのヒープサイズを増やすことをお勧めします。 XMLファイルが小さい場合はDOMパーサーを使用してXMLファイルを解析するのは非常に高速ですが、DOMパーサーを使用して大きいXMLファイルを読み込もうとすると、時間がかかる、または完全にロードできない可能性があります。 XML Dom Treeを作成するには多くのメモリが必要です。 JavaはDOM解析をサポートしており、DOMパーサーを使用してJavaでXMLファイルを解析できます。 DOMクラスはw3c.domパッケージにあり、DOM Parser for JavaはJAXP(Java API for XML Parsing)パッケージにあります。
JavaでのSAX XMLパーサー
SAXはXML構文解析のための単純なAPIを表します。これはイベントベースのXML解析であり、XMLファイルを段階的に解析するので、大規模なXMLファイルに適しています。 SAX XML Parserは、開始タグ、要素、または属性に遭遇したときにイベントを起動し、それに応じて解析が機能します。 Javaで大きなXMLファイルを解析するためにSAX XMLパーサーを使用することをお勧めします。これは、XMLファイル全体をJavaでロードする必要がなく、大きなXMLファイルを小さな部分で読み取ることができるためです。 JavaはSAXパーサーをサポートしており、SAXパーサーを使用してJavaで任意のxmlファイルを解析できます。ここでは、SAXパーサーを使用してxmlファイルを読み取る例について説明しました。 JavaでSAX Parserを使用する場合の1つの欠点は、SAX Parserを使用してJavaでXMLファイルを読み取ると、DOM Parserと比較してより多くのコードが必要になることです。
DOMとSAX XMLパーサーの違い
JavaにおけるDOMパーサーとSAXパーサーの間には、いくつかの高度な違いがあります。
1)DOMパーサーはxml文書全体をメモリーにロードしますが、SAXはXMLファイルのごく一部をメモリーにロードします。
2)DOMパーサーは、メモリー内のXML文書全体にアクセスするため、SAXよりも高速です。
3)JavaのSAXパーサーは、メモリーをあまり必要としないため、DOMパーサーよりも大きなXMLファイルに適しています。
4)DOMパーサーはDocument Object Modelで動作しますが、SAXはイベントベースのxmlパーサーです。
続きを読む: http://javarevisited.blogspot.com/2011/12/difference-between-dom-and-sax-parsers.html#ixzz2uz1bJQqZ
SAXとDOMの両方を使用してXML文書を解析します。どちらにも長所と短所があり、状況に応じてプログラミングで使用できます。
サックス:
ノードごとに解析
XMLをメモリに格納しません
ノードを挿入または削除できません
上から下への移動
DOM
処理前にXML文書全体をメモリーに保管します。
より多くのメモリを占有
ノードを挿入または削除できます
任意の方向に移動します。
ノードを見つける必要があり、挿入や削除が不要な場合は、SAX自体を使用することができます。それ以外の場合はDOMは、より多くのメモリを使用できます。
1)DOMパーサーはXML文書全体をメモリーにロードし、SAXはXMLファイルのごく一部をメモリーにロードします。
2)DOMパーサーは、メモリー内のXML文書全体にアクセスするため、SAXよりも高速です。
3)JavaのSAXパーサーは、メモリーをあまり必要としないため、DOMパーサーよりも大きなXMLファイルに適しています。
4)DOMパーサーは文書オブジェクトモデルで動作しますが、SAXはイベントベースのXMLパーサーです。
続きを読む: http://javarevisited.blogspot.com/2011/12/difference-between-dom-and-sax-parsers.html#ixzz498y3vPFR