haschildren()
Aprende cómo PHP's SimpleXMLIterator::hasChildren() indica si el elemento XML actual del iterador tiene nodos hijo, con ejemplos ejecutables y errores comunes.
Qué hace hasChildren()
hasChildren() es un método de la clase SimpleXMLIterator. Devuelve true cuando el elemento en el que el iterador está posicionado actualmente tiene al menos un elemento hijo, y false cuando ese elemento es un nodo hoja (solo texto o vacío).
Proviene de la interfaz RecursiveIterator de PHP, que implementan tanto SimpleXMLIterator como SimpleXMLElement. Su función es indicarle a un motor de recorrido recursivo: "¿debo descender a este nodo?" Esa es la idea clave y la fuente de la mayor parte de la confusión:
hasChildren() no pregunta "¿tiene hijos $this?" Pregunta "¿tiene hijos el elemento en la posición actual del iterador?" Normalmente se llama mientras se itera con rewind() / valid() / next(), o se deja que un RecursiveIteratorIterator lo llame internamente, no directamente sobre un elemento arbitrario.
public SimpleXMLIterator::hasChildren(): boolEl método no recibe parámetros y devuelve un bool. Para leer los hijos una vez que devuelve true, combínalo con getChildren().
Configurar un SimpleXMLIterator
hasChildren() solo existe en SimpleXMLIterator, así que crea uno a partir de tu cadena XML con new SimpleXMLIterator(), o carga un documento y conviértelo. Aquí hay un pequeño catálogo donde un elemento tiene hijos y otro no:
<?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";
}
}Salida:
book has children:
title: Modern PHP
author: Josh Lockhart
note (leaf): Closed on holidaysObserva que el bucle recorre el iterador manualmente con rewind(), valid(), next(), key() y current(). hasChildren() informa sobre el elemento en el que se encuentra el cursor en ese momento.
Recorrer todo el árbol de forma recursiva
El verdadero beneficio de hasChildren() aparece cuando pasas el iterador a un RecursiveIteratorIterator. Ese contenedor llama a hasChildren() y getChildren() por ti, descendiendo automáticamente para que puedas aplanar un documento anidado de cualquier profundidad:
<?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";
}Salida:
shelf
book
title
deskAquí nunca llamas a hasChildren() manualmente — RecursiveIteratorIterator lo usa internamente para decidir cuándo recursar.
Cuándo usarlo
- Estás iterando una estructura XML desconocida y necesitas saber si debes profundizar antes de leer los valores.
- Estás construyendo una vista de árbol, migas de pan o una lista plana a partir de XML anidado.
- Quieres que la maquinaria de iteradores de PHP (
RecursiveIteratorIterator, filtros) recorra el XML por ti en lugar de escribir buclesforeachanidados.
Si simplemente quieres los hijos de un elemento conocido, generalmente no necesitas hasChildren() en absoluto — llama a children() sobre un SimpleXMLElement y comprueba si el resultado está vacío con count().
Errores comunes
- Llamarlo en
SimpleXMLElement. UnSimpleXMLElementsimple creado consimplexml_load_file()osimplexml_load_string()implementaRecursiveIterator, pero la semántica dehasChildren()pertenece aSimpleXMLIterator. Usa esa clase cuando necesites este método. - Esperar que detecte atributos o texto.
hasChildren()solo examina los elementos hijo. Un elemento que contiene solo texto o solo atributos devuelvefalse. - Llamarlo antes de posicionar el cursor. Siempre haz
rewind()(o itera) primero; el resultado refleja la posición actual, que no está definida antes del primer elemento.
Conclusión
SimpleXMLIterator::hasChildren() es el guardián del recorrido recursivo de XML: indica si el elemento actual del iterador tiene elementos hijo para que tu código —o un RecursiveIteratorIterator— sepa cuándo descender. Combínalo con getChildren() para leer esos hijos, y recurre a children() o a la guía completa de SimpleXML cuando solo necesites los contenidos de un nodo directamente.