J'ai le fichier XML suivant, le fichier est plutôt volumineux et je n'ai pas réussi à obtenir simplexml pour l'ouvrir et le lire; j'essaie donc XMLReader sans succès en 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>
Malheureusement, je n'ai pas trouvé de bon tutoriel sur ceci pour PHP et j'aimerais voir comment je peux obtenir le contenu de chaque élément dans une base de données.
Tout dépend de la taille de l'unité de travail, mais j'imagine que vous essayez de traiter chaque nœud <product/>
Successivement.
Pour cela, le moyen le plus simple serait d'utiliser XMLReader pour accéder à chaque nœud, puis d'utiliser SimpleXML pour y accéder. Ainsi, vous réduisez l'utilisation de la mémoire, car vous ne traitez qu'un seul nœud à la fois et vous exploitez toujours la simplicité d'utilisation de SimpleXML. Par exemple:
$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');
}
Aperçu rapide des avantages et des inconvénients des différentes approches:
XMLReader uniquement
Avantages: rapide, utilise peu de mémoire
Inconvénients: excessivement difficile à écrire et à déboguer, nécessite beaucoup de code utilisateur pour accomplir quoi que ce soit d’utile. Le code Userland est lent et sujet aux erreurs. De plus, cela vous laisse plus de lignes de code à maintenir
XMLReader + SimpleXML
Avantages: n'utilise pas beaucoup de mémoire (seulement la mémoire nécessaire pour traiter un nœud) et SimpleXML est, comme son nom l'indique, très facile à utiliser.
Inconvénients: la création d'un objet SimpleXMLElement pour chaque nœud n'est pas très rapide. Vous devez vraiment le comparer pour comprendre si c'est un problème pour vous. Même une machine modeste serait capable de traiter un millier de nœuds par seconde.
XMLReader + DOM
Avantages: utilise environ autant de mémoire que SimpleXML et XMLReader :: expand () est plus rapide que la création d'un nouveau SimpleXMLElement. Je souhaite qu'il soit possible d'utiliser simplexml_import_dom()
mais cela ne semble pas fonctionner dans ce cas
Inconvénients: DOM est agaçant de travailler avec. C'est à mi-chemin entre XMLReader et SimpleXML. Pas aussi compliqué et maladroit que XMLReader, mais à des années-lumière du travail avec SimpleXML.
Mon conseil: écrivez un prototype avec SimpleXML, voyez si cela fonctionne pour vous. Si les performances sont primordiales, essayez DOM. Restez aussi loin que possible de XMLReader. N'oubliez pas que plus vous écrivez de code, plus vous risquez d'introduire des bogues ou des régressions de performances.
Pour XML formaté avec des attributs ...
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>
code php:
$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();
La majeure partie de ma vie en analyse XML est consacrée à l'extraction de nuggets d'informations utiles à partir de chargements de XML (Amazon MWS). En tant que tel, ma réponse suppose que vous ne voulez que des informations spécifiques et que vous savez où elles se trouvent.
Je trouve que le moyen le plus simple d'utiliser XMLReader est de savoir quelles balises je souhaite utiliser et de les utiliser. Si vous connaissez la structure du fichier XML et que celui-ci comporte de nombreuses balises uniques, j’aperçois que l’utilisation du premier cas est simple. Les cas 2 et 3 sont simplement destinés à vous montrer comment faire pour des tags plus complexes. C'est extrêmement rapide. J'ai une discussion de la vitesse sur Quel est l'analyseur XML le plus rapide en PHP?
La chose la plus importante à retenir lors de l'analyse syntaxique basée sur les balises est d'utiliser if ($myXML->nodeType == XMLReader::ELEMENT) {...
- qui vérifie que nous ne traitons que des nœuds en ouverture et non des espaces ou des nœuds en fermeture.
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();
}
La réponse acceptée m'a donné un bon départ, mais elle a amené plus de cours et plus de traitement que je l'aurais souhaité. c'est donc mon interprétation:
$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();
XMLReader est bien documenté sur site PHP . Il s'agit d'un analyseur XML Pull, ce qui signifie qu'il est utilisé pour parcourir les nœuds (ou nœuds DOM) d'un document XML donné. Par exemple, vous pouvez parcourir tout le document que vous avez donné comme ceci:
<?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();
?>
Il vous appartient ensuite de décider comment traiter le noeud renvoyé par XMLReader :: expand () .
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));
}
}