Ich habe die folgende XML-Datei, die Datei ist ziemlich groß und ich konnte Simplexml nicht dazu bringen, die Datei zu öffnen und zu lesen, also versuche ich XMLReader ohne Erfolg in PHP
<?xml version="1.0" encoding="ISO-8859-1"?>
<products>
<last_updated>2009-11-30 13:52:40</last_updated>
<product>
<element_1>foo</element_1>
<element_2>foo</element_2>
<element_3>foo</element_3>
<element_4>foo</element_4>
</product>
<product>
<element_1>bar</element_1>
<element_2>bar</element_2>
<element_3>bar</element_3>
<element_4>bar</element_4>
</product>
</products>
Ich habe leider kein gutes Tutorial für PHP gefunden und würde gerne sehen, wie ich jeden Elementinhalt in einer Datenbank speichern kann.
Antworten:
Es hängt alles davon ab, wie groß die Arbeitseinheit ist, aber ich denke, Sie versuchen, jeden
<product/>
Knoten nacheinander zu behandeln .Der einfachste Weg wäre, XMLReader zu verwenden, um zu jedem Knoten zu gelangen, und dann SimpleXML zu verwenden, um auf sie zuzugreifen. Auf diese Weise halten Sie die Speichernutzung gering, da Sie jeweils nur einen Knoten behandeln und dennoch die Benutzerfreundlichkeit von SimpleXML nutzen. Zum Beispiel:
$z = new XMLReader; $z->open('data.xml'); $doc = new DOMDocument; // move to the first <product /> node while ($z->read() && $z->name !== 'product'); // now that we're at the right depth, hop to the next <product/> until the end of the tree while ($z->name === 'product') { // either one should work //$node = new SimpleXMLElement($z->readOuterXML()); $node = simplexml_import_dom($doc->importNode($z->expand(), true)); // now you can use $node without going insane about parsing var_dump($node->element_1); // go to next <product /> $z->next('product'); }
Schneller Überblick über Vor- und Nachteile verschiedener Ansätze:
Nur XMLReader
Vorteile: schnell, verbraucht wenig Speicher
Nachteile: Sehr schwer zu schreiben und zu debuggen, erfordert viel Userland-Code, um irgendetwas Nützliches zu tun. Userland-Code ist langsam und fehleranfällig. Außerdem stehen Ihnen mehr Codezeilen zur Verfügung
XMLReader + SimpleXML
Vorteile: verwendet nicht viel Speicher (nur den Speicher, der für die Verarbeitung eines Knotens benötigt wird) und SimpleXML ist, wie der Name schon sagt, sehr einfach zu verwenden.
Nachteile: Das Erstellen eines SimpleXMLElement-Objekts für jeden Knoten ist nicht sehr schnell. Sie müssen es wirklich vergleichen, um zu verstehen, ob es ein Problem für Sie ist. Selbst eine bescheidene Maschine könnte jedoch tausend Knoten pro Sekunde verarbeiten.
XMLReader + DOM
Vorteile: Verwendet ungefähr so viel Speicher wie SimpleXML, und XMLReader :: expand () ist schneller als das Erstellen eines neuen SimpleXMLElement. Ich wünschte, es wäre möglich zu verwenden,
simplexml_import_dom()
aber es scheint in diesem Fall nicht zu funktionierenNachteile: Es ist ärgerlich, mit DOM zu arbeiten. Es ist auf halbem Weg zwischen XMLReader und SimpleXML. Nicht so kompliziert und umständlich wie XMLReader, aber Lichtjahre von der Arbeit mit SimpleXML entfernt.
Mein Rat: Schreiben Sie einen Prototyp mit SimpleXML und prüfen Sie, ob er für Sie funktioniert. Wenn die Leistung von größter Bedeutung ist, versuchen Sie es mit DOM. Halten Sie sich so weit wie möglich von XMLReader entfernt. Denken Sie daran, je mehr Code Sie schreiben, desto höher ist die Wahrscheinlichkeit, dass Sie Fehler oder Leistungsregressionen einführen.
quelle
Für mit Attributen formatierte XML ...
data.xml:
<building_data> <building address="some address" lat="28.902914" lng="-71.007235" /> <building address="some address" lat="48.892342" lng="-75.0423423" /> <building address="some address" lat="58.929753" lng="-79.1236987" /> </building_data>
PHP-Code:
$reader = new XMLReader(); if (!$reader->open("data.xml")) { die("Failed to open 'data.xml'"); } while($reader->read()) { if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'building') { $address = $reader->getAttribute('address'); $latitude = $reader->getAttribute('lat'); $longitude = $reader->getAttribute('lng'); } $reader->close();
quelle
Die akzeptierte Antwort gab mir einen guten Start, brachte aber mehr Klassen und mehr Verarbeitung, als ich gerne hätte; Das ist also meine Interpretation:
$xml_reader = new XMLReader; $xml_reader->open($feed_url); // move the pointer to the first product while ($xml_reader->read() && $xml_reader->name != 'product'); // loop through the products while ($xml_reader->name == 'product') { // load the current xml element into simplexml and we’re off and running! $xml = simplexml_load_string($xml_reader->readOuterXML()); // now you can use your simpleXML object ($xml). echo $xml->element_1; // move the pointer to the next product $xml_reader->next('product'); } // don’t forget to close the file $xml_reader->close();
quelle
Den größten Teil meines XML-Parsing-Lebens verbringe ich damit, Nuggets nützlicher Informationen aus LKW-Ladungen XML (Amazon MWS) zu extrahieren. In meiner Antwort wird davon ausgegangen, dass Sie nur bestimmte Informationen wünschen und wissen, wo sich diese befinden.
Ich finde, der einfachste Weg, XMLReader zu verwenden, besteht darin, zu wissen, aus welchen Tags die Informationen stammen sollen, und sie zu verwenden. Wenn Sie die Struktur des XML kennen und es viele eindeutige Tags hat, finde ich, dass die Verwendung des ersten Falls einfach ist. Die Fälle 2 und 3 sollen Ihnen nur zeigen, wie dies bei komplexeren Tags möglich ist. Das geht extrem schnell; Ich habe eine Diskussion über die Geschwindigkeit von Was ist der schnellste XML-Parser in PHP?
Das Wichtigste, an das Sie sich erinnern sollten, wenn Sie ein Tag-basiertes Parsing wie dieses durchführen, ist die Verwendung. Dabei wird
if ($myXML->nodeType == XMLReader::ELEMENT) {...
überprüft, ob es sich nur um das Öffnen von Knoten und nicht um Leerzeichen oder das Schließen von Knoten oder was auch immer handelt.function parseMyXML ($xml) { //pass in an XML string $myXML = new XMLReader(); $myXML->xml($xml); while ($myXML->read()) { //start reading. if ($myXML->nodeType == XMLReader::ELEMENT) { //only opening tags. $tag = $myXML->name; //make $tag contain the name of the tag switch ($tag) { case 'Tag1': //this tag contains no child elements, only the content we need. And it's unique. $variable = $myXML->readInnerXML(); //now variable contains the contents of tag1 break; case 'Tag2': //this tag contains child elements, of which we only want one. while($myXML->read()) { //so we tell it to keep reading if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Amount') { // and when it finds the amount tag... $variable2 = $myXML->readInnerXML(); //...put it in $variable2. break; } } break; case 'Tag3': //tag3 also has children, which are not unique, but we need two of the children this time. while($myXML->read()) { if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Amount') { $variable3 = $myXML->readInnerXML(); break; } else if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Currency') { $variable4 = $myXML->readInnerXML(); break; } } break; } } } $myXML->close(); }
quelle
Simple example: public function productsAction() { $saveFileName = 'ceneo.xml'; $filename = $this->path . $saveFileName; if(file_exists($filename)) { $reader = new XMLReader(); $reader->open($filename); $countElements = 0; while($reader->read()) { if($reader->nodeType == XMLReader::ELEMENT) { $nodeName = $reader->name; } if($reader->nodeType == XMLReader::TEXT && !empty($nodeName)) { switch ($nodeName) { case 'id': var_dump($reader->value); break; } } if($reader->nodeType == XMLReader::END_ELEMENT && $reader->name == 'offer') { $countElements++; } } $reader->close(); exit(print('<pre>') . var_dump($countElements)); } }
quelle
XMLReader ist auf derPHP-Sitegut dokumentiert. Dies ist ein XML-Pull-Parser. Dies bedeutet, dass er zum Durchlaufen von Knoten (oder DOM-Knoten) eines bestimmten XML-Dokuments verwendet wird. Sie können beispielsweise das gesamte von Ihnen angegebene Dokument folgendermaßen durchgehen:<?php $reader = new XMLReader(); if (!$reader->open("data.xml")) { die("Failed to open 'data.xml'"); } while($reader->read()) { $node = $reader->expand(); // process $node... } $reader->close(); ?>
Es liegt dann an Ihnen, zu entscheiden, wie mit dem von XMLReader :: expand () zurückgegebenen Knoten umgegangen werden soll .
quelle
Das funktioniert besser und schneller für mich
<html> <head> <script> function showRSS(str) { if (str.length==0) { document.getElementById("rssOutput").innerHTML=""; return; } if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else { // code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (this.readyState==4 && this.status==200) { document.getElementById("rssOutput").innerHTML=this.responseText; } } xmlhttp.open("GET","getrss.php?q="+str,true); xmlhttp.send(); } </script> </head> <body> <form> <select onchange="showRSS(this.value)"> <option value="">Select an RSS-feed:</option> <option value="Google">Google News</option> <option value="ZDN">ZDNet News</option> <option value="job">Job</option> </select> </form> <br> <div id="rssOutput">RSS-feed will be listed here...</div> </body> </html>
** Die Backend-Datei **
<?php //get the q parameter from URL $q=$_GET["q"]; //find out which feed was selected if($q=="Google") { $xml=("http://news.google.com/news?ned=us&topic=h&output=rss"); } elseif($q=="ZDN") { $xml=("https://www.zdnet.com/news/rss.xml"); }elseif($q == "job"){ $xml=("https://ngcareers.com/feed"); } $xmlDoc = new DOMDocument(); $xmlDoc->load($xml); //get elements from "<channel>" $channel=$xmlDoc->getElementsByTagName('channel')->item(0); $channel_title = $channel->getElementsByTagName('title') ->item(0)->childNodes->item(0)->nodeValue; $channel_link = $channel->getElementsByTagName('link') ->item(0)->childNodes->item(0)->nodeValue; $channel_desc = $channel->getElementsByTagName('description') ->item(0)->childNodes->item(0)->nodeValue; //output elements from "<channel>" echo("<p><a href='" . $channel_link . "'>" . $channel_title . "</a>"); echo("<br>"); echo($channel_desc . "</p>"); //get and output "<item>" elements $x=$xmlDoc->getElementsByTagName('item'); $count = $x->length; // print_r( $x->item(0)->getElementsByTagName('title')->item(0)->nodeValue); // print_r( $x->item(0)->getElementsByTagName('link')->item(0)->nodeValue); // print_r( $x->item(0)->getElementsByTagName('description')->item(0)->nodeValue); // return; for ($i=0; $i <= $count; $i++) { //Title $item_title = $x->item(0)->getElementsByTagName('title')->item(0)->nodeValue; //Link $item_link = $x->item(0)->getElementsByTagName('link')->item(0)->nodeValue; //Description $item_desc = $x->item(0)->getElementsByTagName('description')->item(0)->nodeValue; //Category $item_cat = $x->item(0)->getElementsByTagName('category')->item(0)->nodeValue; echo ("<p>Title: <a href='" . $item_link . "'>" . $item_title . "</a>"); echo ("<br>"); echo ("Desc: ".$item_desc); echo ("<br>"); echo ("Category: ".$item_cat . "</p>"); } ?>
quelle