2013-08-29 9 views
5

Ich versuche und brauche etwas Hilfe bei der Durchführung der folgenden:Stream Parse 4 GB XML-Datei in PHP

Ich möchte streamen eine große XML-Datei (4 GB) mit PHP parsen. Ich kann kein einfaches XML oder DOM verwenden, weil sie die gesamte Datei in den Speicher laden, also brauche ich etwas, das die Datei streamen kann.

Wie kann ich das in PHP tun?

Was ich versuche zu tun ist, durch eine Reihe von <doc> Elemente zu navigieren. Und schreiben Sie einige ihrer Kinder in eine neue XML-Datei.

Die XML-Datei Ich versuche, sieht wie folgt zu analysieren:

<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> 

Ich versuche, alle Kinder jedes <doc> Element in eine neue XML-Datei zu erhalten/kopieren mit Ausnahme des <links> Element und seine Kinder .

Deshalb möchte ich die neue XML-Datei wie folgt aussehen:

<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> 

ich stark jegliche Hilfe in Streaming/Stream-Parsing/Strom Lesen der ursprünglichen XML-Datei schätzen würde und dann einen Teil seiner Inhalte zu schreiben zu einer neuen XML-Datei in PHP.

+3

Schauen Sie sich die XMLReader Klasse: http: //www.php.net/manual/en/intro.xmlreader.php Es ist ein Streaming-Parser. Ich lese gerade Ihre Frage tiefer, um zu sehen, ob ich mit spezifischeren Antworten helfen kann. – DeeDee

+0

@DeeDee Ich hatte von XMLReader gehört, wusste aber nicht, wie man es benutzt. Danke für die Hilfe! –

+0

Sicher! Es wird nicht zu stark verwendet, wie der Mangel an Kommentaren in der offiziellen Dokumentation zeigt. Ich selbst habe es schon sehr lange nicht mehr benutzt. Können Sie mich wissen lassen, wie mein Code funktioniert? Wenn es nicht sofort funktioniert, können wir zusammenarbeiten und herausfinden, was los ist. – DeeDee

Antwort

4

Hier ist ein College-Versuch. Dies setzt voraus, eine Datei verwendet wird, und dass Sie in eine Datei schreiben:

<?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(); 

?> 
+0

Was war in Ihrer neuesten Bearbeitung? Ich kann den Unterschied zwischen dieser aktuellen Version und der Version, die ich vorher gelesen habe, nicht unterscheiden. –

+0

Das sieht genau nach was ich gesucht habe, danke.Ich werde es heute Abend ausprobieren und Sie wissen lassen, was passiert. –

+0

Ich habe das ' DeeDee

0

Für dieses Szenario Sie nicht einen DOM-Parser verwenden leisten können, wie Sie sagten, es wird nicht durch in den Speicher passen auf die Dateigröße, und selbst wenn Sie könnten, wird es langsam, wie es zuerst die gesamte Datei laden und danach müssen Sie durchlaufen, so für diesen Fall sollten Sie versuchen, einen SAX-Parser (Event/Stream orientiert) Fügen Sie einen Handler für die Tags hinzu, in denen Sie interessiert sind (doc, title, url, abstract) und fügen Sie für jedes Ereignis den Knoten hinzu, der in der neuen XML-Datei enthalten ist.

Hier erfahren Sie mehr Informationen haben:

What is the fastest XML parser in PHP?

Hier ist ein (nicht getestet) Probe von dem, was der Code wäre:

<?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); 
?> 
+0

Ich erhalte einen Fehler mit dem Code, den ich nicht reparieren kann. Es macht auch keinen Sinn. Der Fehler, den ich bekomme, ist: 'PHP-Parse-Fehler: Syntaxfehler, unerwartet ';' in /Users/irfanm/Desktop/mamp/xml2.php in Zeile 12 '. –