2017-07-19 5 views
0

J'ai vu beaucoup de tutoriels ici en débordement, mais je ne pouvais pas comprendre ce que je me manque .. Je besoin d'aide ..XML obtenir les attributs

J'ai un XML qui est en ligne et je suis en train de analyser comme ceci:

<products> 
    <product> 
    <id>13389</id> 
    <name><![CDATA[ product name ]]></name> 
    <category id="14"><![CDATA[ Shoes > test1 ]]></category> 
    <price>41.30</price> 
</products> 

en ce qui concerne, je lis le XML et l'analyse comme ceci:

$reader = new XMLReader(); 
$reader->open($product_xml_link); 
while($reader->read()) { 
if($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'product') { 
    $product = new SimpleXMLElement($reader->readOuterXml()); 
    $pid = $product->id; 
    $name = $product->name; 
    $name = strtolower($name); 
    $link = $product->link; 
    $price = $product->Price; 
    ... 
    ... 
} 
} //end while loop 

comme vous pouvez le voir, il y a un id dans la balise catégorie .. C'est le celui que je voudrais saisir et passer à mon code ..

je fait quelque chose comme ceci:

echo "prodcut= " . (string)$product->category->getAttribute('id'); 

L'erreur que je reçois est: Appel à la méthode non définie SimpleXMLElement :: getAttribute()

J'ai besoin cet identifiant afin de le tester avant insertion dans DB .. Donc,

if($id = 600) { 
//insert DB 
} 

Répondre

1

Voici plusieurs choses. D'abord $product = new SimpleXMLElement($reader->readOuterXml()); signifie que vous lisez tout cela en tant que document XML séparé et que vous pars à nouveau. Voici expand(), qui retournera directement un noeud DOM et les noeuds DOM peuvent être importés dans SimpleXML.

Pour les attributs utiliser la syntaxe de tableau ..

$reader = new XMLReader(); 
$reader->open($product_xml_link); 

// an document to expand to 
$document = new DOMDocument(); 

// find the first product node 
while ($reader->read() && $reader->localName !== 'product') { 
    continue; 
} 

while ($reader->localName === 'product') { 
    $product = simplexml_import_dom($reader->expand($document)); 
    $data = [ 
    'id' => (string)$product->id, 
    'name' => (string)$product->name, 
    'category_id' => (string)$product->category['id'], 
    // ... 
    ]; 
    var_dump($data); 
    // move to the next product sibling 
    $reader->next('product'); 
} 
$reader->close(); 

Sortie:

array(3) { 
    ["id"]=> 
    string(5) "13389" 
    ["name"]=> 
    string(14) " product name " 
    ["category_id"]=> 
    string(2) "14" 
} 

Bien sûr, vous pouvez utiliser le DOM directement et récupérer les données de détail en utilisant des expressions XPath:

$reader = new XMLReader(); 
$reader->open($product_xml_link); 

// prepare a document to expand to 
$document = new DOMDocument(); 
// and an xpath instance to use 
$xpath = new DOMXpath($document); 

// find the first product node 
while ($reader->read() && $reader->localName !== 'product') { 
    continue; 
} 

while ($reader->localName === 'product') { 
    $product = $reader->expand($document); 
    $data = [ 
    'id' => $xpath->evaluate('string(id)', $product), 
    'name' => $xpath->evaluate('string(name)', $product), 
    'category_id' => $xpath->evaluate('string(category/@id)', $product), 
    // ... 
    ]; 
    var_dump($data); 
    // move to the next product sibling 
    $reader->next('product'); 
} 
$reader->close(); 
+0

Bonjour, merci pour votre réponse .. Puis-je demander s'il y a un moyen plus facile, sans tableaux ? Mon code tel quel, est-ce possible de récupérer l'identifiant? sans $ document = new DOMDocument(); // et une instance xpath à utiliser $ xpath = new DOMXpath ($ document); Ou n'importe quoi? –

+0

Le tableau est uniquement un moyen de collecter les données lues.Utilisez des variables, appelez des fonctions, ... et bien, vous pouvez utiliser ma bibliothèque FluentDOM. Il étend XMLReader/DOM et en extrait une partie: https://github.com/FluentDOM/FluentDOM/blob/master/examples/XMLReader/sitemap.php :-) – ThW

+0

Je garde ma solution telle quelle, avec quelques changements parlé de: $ document = ... $ xpath =. . . J'ai effacé la ligne de code $ product = new SimpleXMLElement et j'ai transformé toutes mes données en tableau comme vous le mentionnez .. Maintenant, je vois que l'analyse XML est un peu plus lente ... Le XML a 5.500 produits (qui ne sont pas beaucoup). Avant tout changement, le XML est un peu plus rapide je crois .. Des suggestions? –

0

vous voulez boucler tous les produits, et extraire les éléments enfants id, name, link, et price le contenu du texte? qui peut être fait comme:

foreach((@DOMDocument::loadHTML($xml))->getElementsByTagName("product") as $product){ 
    $vars=array('id','name','link','price'); 
    foreach($vars as $v){ 
     ${$v}=$product->getElementsByTagName($v)->item(0)->textContent; 
    } 
    unset($v,$vars); 
    //now you have $id , $name , $link , $price as raw text, and $product is the DOMNode for the <product> tag. 
} 

et si vous voulez seulement traiter id 600, ajoutez if($id!=600){continue;} après la unset(); - et si vous voulez économiser du CPU, vous devez également insérer une pause; à la fin de la boucle foreach dans ce cas. (Alors il arrêtera en boucle une fois trouvé id 600)

Edit: fixe un code de rupture faute de frappe, le code ne fonctionnera pas sans la faute de frappe fixer

modifier: si vous souhaitez utiliser XPath pour trouver le bon élément, ce serait $product=(new DOMXpath((@DOMDOcument::loadHTML($xml))))->query('//product/id[text()=\'600\']')->item(0)->parentNode;

modifier: fixe une autre faute de frappe révolutionnaire code (items(0) ->item(0))