haschildren()
Apprenez comment PHP SimpleXMLIterator::hasChildren() indique si l'élément XML courant de l'itérateur possède des nœuds enfants, avec des exemples.
Ce que fait hasChildren()
hasChildren() est une méthode de la classe SimpleXMLIterator. Elle retourne true lorsque l'élément sur lequel l'itérateur est actuellement positionné possède au moins un élément enfant, et false lorsque cet élément est un nœud feuille (texte uniquement ou vide).
Elle provient de l'interface RecursiveIterator de PHP, que SimpleXMLIterator et SimpleXMLElement implémentent toutes deux. Son rôle est d'indiquer à un moteur de traversée récursive : « dois-je descendre dans ce nœud ? » C'est l'idée clé, et la source de la plupart des confusions :
hasChildren() ne demande pas « est-ce que $this a des enfants ? » Elle demande « est-ce que l'élément à la position courante de l'itérateur a des enfants ? » Vous l'appelez normalement en bouclant avec rewind() / valid() / next(), ou vous laissez un RecursiveIteratorIterator l'appeler pour vous — pas directement sur un élément arbitraire.
public SimpleXMLIterator::hasChildren(): boolLa méthode ne prend aucun paramètre et retourne un bool. Pour lire les enfants une fois qu'elle retourne true, associez-la à getChildren().
Configurer un SimpleXMLIterator
hasChildren() n'existe que sur SimpleXMLIterator, donc créez-en un à partir de votre chaîne XML avec new SimpleXMLIterator(), ou chargez un document et effectuez un transtypage. Voici un petit catalogue où un élément a des enfants et l'autre non :
<?php
$xml = new SimpleXMLIterator(<<<XML
<store>
<book>
<title>Modern PHP</title>
<author>Josh Lockhart</author>
</book>
<note>Closed on holidays</note>
</store>
XML);
for ($xml->rewind(); $xml->valid(); $xml->next()) {
if ($xml->hasChildren()) {
echo $xml->key() . " has children:\n";
foreach ($xml->getChildren() as $name => $value) {
echo " {$name}: {$value}\n";
}
} else {
echo $xml->key() . " (leaf): " . $xml->current() . "\n";
}
}Sortie :
book has children:
title: Modern PHP
author: Josh Lockhart
note (leaf): Closed on holidaysRemarquez que la boucle parcourt l'itérateur manuellement avec rewind(), valid(), next(), key() et current(). hasChildren() rend compte de l'élément sur lequel se trouve le curseur à ce moment-là.
Parcourir tout l'arbre de manière récursive
Le véritable intérêt de hasChildren() apparaît lorsque vous passez l'itérateur à un RecursiveIteratorIterator. Ce wrapper appelle hasChildren() et getChildren() pour vous, descendant automatiquement pour que vous puissiez aplatir un document imbriqué de n'importe quelle profondeur :
<?php
$xml = new SimpleXMLIterator(<<<XML
<library>
<shelf>
<book>
<title>PHP Basics</title>
</book>
</shelf>
<desk>Front entrance</desk>
</library>
XML);
$tree = new RecursiveIteratorIterator(
$xml,
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($tree as $name => $node) {
echo str_repeat(' ', $tree->getDepth()) . $name . "\n";
}Sortie :
shelf
book
title
deskVous n'appelez jamais hasChildren() manuellement ici — RecursiveIteratorIterator l'utilise en interne pour décider quand effectuer la récursion.
Quand l'utiliser
- Vous itérez sur une structure XML inconnue et devez savoir s'il faut descendre plus profondément avant de lire les valeurs.
- Vous construisez une arborescence, un fil d'Ariane ou une liste aplatie à partir de XML imbriqué.
- Vous souhaitez que la machinerie d'itérateur de PHP (
RecursiveIteratorIterator, filtres) traverse le XML pour vous plutôt que d'écrire des bouclesforeachimbriquées.
Si vous voulez simplement les enfants d'un élément connu, vous n'avez généralement pas besoin de hasChildren() du tout — appelez children() sur un SimpleXMLElement et vérifiez si le résultat est vide avec count().
Pièges courants
- L'appeler sur
SimpleXMLElement. UnSimpleXMLElementsimple créé avecsimplexml_load_file()ousimplexml_load_string()implémenteRecursiveIterator, mais la sémantique conviviale dehasChildren()appartient àSimpleXMLIterator. Utilisez cette classe lorsque vous souhaitez cette méthode. - S'attendre à ce qu'elle détecte les attributs ou le texte.
hasChildren()examine uniquement les éléments enfants. Un élément contenant uniquement du texte ou uniquement des attributs retournefalse. - L'appeler avant de positionner le curseur. Effectuez toujours un
rewind()(ou itérez) en premier ; le résultat reflète la position courante, qui est indéfinie avant le premier élément.
Conclusion
SimpleXMLIterator::hasChildren() est le gardien de la traversée XML récursive : elle indique si l'élément courant de l'itérateur a des éléments enfants, afin que votre code — ou un RecursiveIteratorIterator — sache quand descendre. Associez-la à getChildren() pour lire ces enfants, et utilisez children() ou le guide SimpleXML plus complet lorsque vous avez juste besoin du contenu d'un nœud directement.