web-dev-qa-db-ja.com

PHPで大きなXMLを処理する最良の方法

大きなXMLファイルをphpで解析する必要があります。そのうちの1つは6.5 MBで、さらに大きくなる可能性があります。私が読んだSimpleXML拡張機能は、ファイル全体をオブジェクトにロードしますが、あまり効率的ではないかもしれません。あなたの経験では、最良の方法は何でしょうか?

27
Petruza

大きなファイルの場合、DOMパーサーではなく SAXパーサー を使用する必要があります。

DOMパーサーを使用すると、ファイル全体が読み込まれ、メモリ内のオブジェクトツリーに読み込まれます。 SAXパーサーを使用すると、ファイルを順次読み取り、ユーザー定義のコールバック関数を呼び出してデータ(開始タグ、終了タグ、CDATAなど)を処理します

SAXパーサーを使用すると、自分で状態を維持する必要があります(現在のタグなど)。これにより、少し複雑になりますが、大きなファイルの場合は、メモリの効率が大幅に向上します。

22
Eric Petroelje

私の見解:

https://github.com/prewk/XmlStreamer

ファイルのストリーミング中にすべての子をXMLルート要素に抽出する単純なクラス。 pubmed.comの108 MB XMLファイルでテスト済み。

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();
11
oskarth

大きなXMLファイルでDOMDocumentを使用する場合は、 _LIBXML_PARSEHUGE_ フラグをオプションのオプションに渡すことを忘れないでください。 load() メソッド。 (loadオブジェクトの他の DOMDocument メソッドにも同じことが適用されます)

_    $checkDom = new \DOMDocument('1.0', 'UTF-8');
    $checkDom->load($filePath, LIBXML_PARSEHUGE);
_

(120mo XMLファイルで動作)

7
COil

SAXパーサーは、Eric Petroeljeが推奨するように、大きなXMLファイルに適しています。 DOMパーサーはXMLファイル全体に読み込まれ、xpathクエリを実行できます。SAX(Simple API for XML)パーサーは一度に1行ずつ読み取るだけで、処理のフックポイントを提供します。

6
kenleycapps

それは本当にあなたがデータをどうしたいかに依存していますか?それを効果的に操作するには、メモリにすべて必要ですか?

今日のコンピューターでは、6.5 MBはそれほど大きくありません。たとえば、ini_set('memory_limit', '128M');

ただし、データをストリーミングできる場合は、 SAXパーサー の使用を検討してください。それは本当にあなたの使用ニーズに依存します。

3
gahooa

SAXパーサーを使用する方法です。整理整頓しないと、SAXの解析が煩雑になる可能性があることがわかりました。

私はSTX(Streaming Transformations for XML)に基づくアプローチを使用して、大きなXMLファイルを解析します。 SAXメソッドを使用してSimpleXMLオブジェクトを作成し、現在のコンテキスト(つまり、ルートと現在のノードの間のノードのみ)のデータを追跡します。その後、SimpleXMLドキュメントの処理に他の関数が使用されます。

2
Benedict Cohen

たまたま各行に要素がある大きなXMLファイル(StackOverflowデータダンプ)を解析する必要がありました。この特定のケースでは、一度に1行ずつファイルを読み取り、SimpleXMLを使用して各行を解析するだけで十分でした。私にとって、これには新しいことを学ぶ必要がないという利点がありました。

1
Liam