5

私はしようとしていて、次のことをするのに助けが必要です:

大きな XML ファイル (4 GB) を PHP でストリーム解析したいと考えています。ファイル全体をメモリにロードするため、単純な XML や DOM を使用できないため、ファイルをストリーミングできるものが必要です。

PHPでこれを行うにはどうすればよいですか?

私がやろうとしているのは、一連の<doc>要素をナビゲートすることです。そして、その子の一部を新しい xml ファイルに書き込みます。

解析しようとしている XML ファイルは次のようになります。

<feed>
    <doc>
        <title>Title of first doc is here</title>
        <url>URL is here</url>
        <abstract>Abstract is here...</abstract>
        <links>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
       </link>
    </doc>
    <doc>
        <title>Title of second doc is here</title>
        <url>URL is here</url>
        <abstract>Abstract is here...</abstract>
        <links>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
       </link>
    </doc>
</feed>

要素とその子<doc>を除く、各要素のすべての子を新しい XML ファイルに取得/コピーしようとしています。<links>

したがって、新しい XML ファイルは次のようになります。

<doc>
    <title>Title of first doc is here</title>
    <url>URL is here</url>
    <abstract>Abstract is here...</abstract>
</doc>
<doc>
    <title>Title of second doc is here</title>
    <url>URL is here</url>
    <abstract>Abstract is here...</abstract>
</doc>

ストリーミング、ストリーム解析、元の XML ファイルのストリーム読み取り、およびその内容の一部を PHP で新しい XML ファイルに書き込む際に、あらゆる助けをいただければ幸いです。

4

2 に答える 2

4

大学受験はこちら。これは、ファイルが使用されており、ファイルに書き込みたいと想定しています。

<?php

$interestingNodes = array('title','url','abstract');
$xmlObject = new XMLReader();
$xmlObject->open('bigolfile.xml');

$xmlOutput = new XMLWriter();
$xmlOutput->openURI('destfile.xml');
$xmlOutput->setIndent(true);
$xmlOutput->setIndentString("   ");
$xmlOutput->startDocument('1.0', 'UTF-8');

while($xmlObject->read()){
    if($xmlObject->name == 'doc'){
        $xmlOutput->startElement('doc');
        $xmlObject->readInnerXML();
        if(array_search($xmlObject->name, $interestingNodes)){
             $xmlOutput->startElement($xmlObject->name);
             $xmlOutput->text($xmlObject->value);
             $xmlOutput->endElement(); //close the current node
        }
        $xmlOutput->endElement(); //close the doc node
    }
}

$xmlObject->close();
$xmlOutput->endDocument();
$xmlOutput->flush();

?>
于 2013-08-29T19:08:56.177 に答える
1

このシナリオでは、あなたが述べたように、DOM パーサーを使用する余裕はありません。ファイル サイズが原因でメモリに収まりません。また、できたとしても、最初にファイル全体をロードしてからそれを繰り返し処理する必要があるため、この場合は SAX パーサー (イベント/ストリーム指向) を試して、関心のあるタグ ( doctitleurlabstract) のハンドラーを追加し、すべてのイベントに対して見つかったノードを追加する必要があります。新しい XML ファイルで。

詳細情報は次のとおりです。

PHP で最速の XML パーサーは何ですか?

コードがどのようなものになるかの(テストされていない)サンプルは次のとおりです。

<?php
    $file = "bigfile.xml";
    $fh = fopen("out.xml", 'a') or die("can't open file");
    $currentNodeTag = "";    
    $tags = array("doc", "title", "url", "abstract");

    function startElement($parser, $name, $attrs) {
        global $tags;

        if (isset($tags[strtolower($name)])) {
            $currentNodeTag = strtolower($name);
            fwrite($fh, sprintf("<%s>\n"));
        }
    }

    function endElement($parser, $name) {
        global $tags;

        if (isset($tags[strtolower($name)])) {
            fwrite($fh, sprintf("</%s>\n"));
            $currentNodeTag = "";
        }
    }

    function characterData($parser, $data) {
        if (!empty($currentNodeTag)) {
            fwrite($fh, $data);
        }
    }    

    $xmlParser = xml_parser_create();
    xml_set_element_handler($xmlParser, "startElement", "endElement");
    xml_set_character_data_handler ($xmlParser, "characterData");

    if (!($fp = fopen($file, "r"))) {
        die("could not open XML input");
    }

    while ($data = fread($fp, 4096)) {
        if (!xml_parse($xmlParser, $data, feof($fp))) {
            die(sprintf("XML error: %s at line %d",
                        xml_error_string(xml_get_error_code($xmlParser)),
                        xml_get_current_line_number($xmlParser)));
        }
    }

    xml_parser_free($xmlParser);
    fclose($fh);
?>
于 2013-08-29T20:28:27.957 に答える