PHP で大きな XML ファイルを解析する必要があります。そのうちの 1 つは 6.5 MB で、さらに大きくなる可能性があります。私が読んだ SimpleXML 拡張機能は、ファイル全体をオブジェクトにロードしますが、これはあまり効率的ではない可能性があります。あなたの経験上、最善の方法は何ですか?
7 に答える
大きなファイルの場合は、DOM パーサーではなくSAX パーサーを使用する必要があります。
DOM パーサーを使用すると、ファイル全体を読み取り、メモリ内のオブジェクト ツリーにロードします。SAX パーサーを使用すると、ファイルを順番に読み取り、ユーザー定義のコールバック関数を呼び出してデータ (開始タグ、終了タグ、CDATA など) を処理します。
SAX パーサーを使用すると、自分で状態 (現在のタグなど) を維持する必要があるため、少し複雑になりますが、大きなファイルの場合は、メモリに関してはるかに効率的です。
私の見解:
https://github.com/prewk/XmlStreamer
ファイルのストリーミング中にすべての子をXMLルート要素に抽出する単純なクラス。pubmed.comの108MBXMLファイルでテスト済み。
class SimpleXmlStreamer extends XmlStreamer {
public function processNode($xmlString, $elementName, $nodeIndex) {
$xml = simplexml_load_string($xmlString);
// Do something with your SimpleXML object
return true;
}
}
$streamer = new SimpleXmlStreamer("myLargeXmlFile.xml");
$streamer->parse();
大きな XML ファイルでを使用する場合は、メソッドのオプションでフラグDOMDocument
を渡すことを忘れないでください。(オブジェクトの他のメソッドについても同様です)LIBXML_PARSEHUGE
load()
load
DOMDocument
$checkDom = new \DOMDocument('1.0', 'UTF-8');
$checkDom->load($filePath, LIBXML_PARSEHUGE);
(120mo XML ファイルで動作)
Eric Petroelje が推奨するように、SAX パーサーは、大きな XML ファイルに適しています。DOM パーサーは XML ファイル全体をロードし、xpath クエリを実行できるようにします。SAX (Simple API for XML) パーサーは一度に 1 行ずつ読み取り、処理のためのフック ポイントを提供します。
それは本当にあなたがデータで何をしたいかによって異なりますか?効果的に操作するには、すべてをメモリに格納する必要がありますか?
今日のコンピュータに関しては、6.5 MB はそれほど大きくありません。たとえば、次のことができます。ini_set('memory_limit', '128M');
ただし、データをストリーミングできる場合は、SAX パーサーの使用を検討することをお勧めします。それは本当にあなたの使用上のニーズに依存します.
SAX パーサーが最適です。整理整頓を怠ると、SAX の構文解析が乱雑になる可能性があることがわかりました。
私は STX (Streaming Transformations for XML) に基づくアプローチを使用して、大きな XML ファイルを解析しています。SAX メソッドを使用して SimpleXML オブジェクトを構築し、現在のコンテキスト (つまり、ルートと現在のノードの間のノードのみ) でデータを追跡します。次に、他の関数を使用して SimpleXML ドキュメントを処理します。
たまたま各行に要素が含まれていた大きな XML ファイル (StackOverflow データ ダンプ) を解析する必要がありました。この特定のケースでは、一度に 1 行ずつファイルを読み取り、SimpleXML を使用して各行を解析するだけで十分でした。私にとって、これには新しいことを学ぶ必要がないという利点がありました。