Lorsque vous utilisez PHP pour traiter les données XML, simplexml_load_string est une fonction très pratique qui convertit les chaînes XML en structures d'objets pour un accès et une manipulation faciles. Cependant, de nombreux développeurs rencontrent un problème commun lors de la gestion de XML avec des espaces de noms: simplexml_load_string ne semble pas reconnaître correctement ou accéder aux éléments dans l'espace de noms.
Cet article explorera les causes de ce problème en profondeur et fournira des solutions claires pour vous aider à les comprendre et à les résoudre dans un seul article.
Regardons d'abord un exemple, qui est une chaîne XML contenant l'espace de noms:
<span><span><span class="hljs-meta"><?xml version=<span class="hljs-string">"1.0"</span></span></span><span>?>
</span><span><span class="hljs-tag"><<span class="hljs-name">root</span></span></span><span> </span><span><span class="hljs-attr">xmlns:h</span></span><span>=</span><span><span class="hljs-string">"http://www.w3.org/TR/html4/"</span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">h:table</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">h:tr</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">h:td</span></span></span><span>>Apples</span><span><span class="hljs-tag"></<span class="hljs-name">h:td</span></span></span><span>>
</span><span><span class="hljs-tag"><<span class="hljs-name">h:td</span></span></span><span>>Bananas</span><span><span class="hljs-tag"></<span class="hljs-name">h:td</span></span></span><span>>
</span><span><span class="hljs-tag"></<span class="hljs-name">h:tr</span></span></span><span>>
</span><span><span class="hljs-tag"></<span class="hljs-name">h:table</span></span></span><span>>
</span><span><span class="hljs-tag"></<span class="hljs-name">root</span></span></span><span>>
</span></span>
Si nous essayons d'analyser en utilisant le code suivant:
<span><span><span class="hljs-variable">$xmlString</span></span><span> = <span class="hljs-string"><<<XML
<?xml version="1.0"?>
<root xmlns:h="http://www.w3.org/TR/html4/">
<h:table>
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
</root>
XML</span>;
</span><span><span class="hljs-variable">$xml</span></span><span> = </span><span><span class="hljs-title function_ invoke__">simplexml_load_string</span></span><span>(</span><span><span class="hljs-variable">$xmlString</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>->table);
</span></span>
Vous constaterez que $ xml-> Le tableau ne renvoie aucun résultat. En effet, simplexml_load_string ne gère pas les balises d'espace de noms préfixées (telles que H: Table ).
Dans XML, les espaces de noms sont utilisés pour éviter les conflits de nom d'élément. Par exemple, H in H: Table est en fait un préfixe de référence pointant vers Xmlns: H = "http://www.w3.org/tr/html4/" . Cela rend le XML plus extensible et organisé, mais apporte également des difficultés d'analyse supplémentaires.
Nous pouvons utiliser les méthodes enfants () et getNamespaces () fournies par la classe simplexmlelement pour accéder aux éléments avec des espaces de noms.
<span><span><span class="hljs-variable">$namespaces</span></span><span> = </span><span><span class="hljs-variable">$xml</span></span><span>-></span><span><span class="hljs-title function_ invoke__">getNamespaces</span></span><span>(</span><span><span class="hljs-literal">true</span></span><span>);
</span><span><span class="hljs-comment">// Résultat de sortie:['h' => 'http://www.w3.org/TR/html4/']</span></span><span>
</span></span>
<span><span><span class="hljs-variable">$h</span></span><span> = </span><span><span class="hljs-variable">$xml</span></span><span>-></span><span><span class="hljs-title function_ invoke__">children</span></span><span>(</span><span><span class="hljs-variable">$namespaces</span></span><span>[</span><span><span class="hljs-string">'h'</span></span><span>]);
</span><span><span class="hljs-variable">$tr</span></span><span> = </span><span><span class="hljs-variable">$h</span></span><span>->table->tr;
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$tr</span></span><span>->td </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$td</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$td</span></span><span> . PHP_EOL;
}
</span></span>
Résultat de sortie:
<span><span><span class="hljs-attribute">Apples</span></span><span>
Bananas
</span></span>
Si vous préférez utiliser la méthode de requête XPath pour obtenir des données, vous pouvez enregistrer l'espace de noms via la méthode RegisterXPathNamespace :
<span><span><span class="hljs-variable">$xml</span></span><span> = </span><span><span class="hljs-title function_ invoke__">simplexml_load_string</span></span><span>(</span><span><span class="hljs-variable">$xmlString</span></span><span>);
</span><span><span class="hljs-variable">$xml</span></span><span>-></span><span><span class="hljs-title function_ invoke__">registerXPathNamespace</span></span><span>(</span><span><span class="hljs-string">'h'</span></span><span>, </span><span><span class="hljs-string">'http://www.w3.org/TR/html4/'</span></span><span>);
</span><span><span class="hljs-variable">$tds</span></span><span> = </span><span><span class="hljs-variable">$xml</span></span><span>-></span><span><span class="hljs-title function_ invoke__">xpath</span></span><span>(</span><span><span class="hljs-string">'//h:td'</span></span><span>);
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$tds</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$td</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$td</span></span><span> . PHP_EOL;
}
</span></span>
Cette approche est non seulement sémantiquement claire, mais aussi plus flexible lorsqu'il s'agit de structures XML complexes.
Lorsque vous utilisez simplexml_load_string pour analyser XML avec l'espace de noms, si vous constatez que les éléments enfants ne sont pas accessibles, ne vous précipitez pas pour soupçonner que le XML est incorrect. Comprenez et faites bon usage des méthodes enfants () , getNamespaces () et registerxpathNamespace () , et vous ferez facilement les troubles causés par les espaces de noms.
Bien que la gestion des espaces de noms soit un peu lourde, une fois maîtrisé, il peut se connecter de manière transparente à diverses sources de données XML standardisées et améliorer les capacités d'intégration des applications PHP. J'espère que cet article peut vous aider à bien comprendre ce problème!