haschildren()
Aprenda como o SimpleXMLIterator::hasChildren() do PHP indica se o elemento XML atual do iterador possui nós filhos, com exemplos executáveis e armadilhas comuns.
O que hasChildren() faz
hasChildren() é um método da classe SimpleXMLIterator. Ele retorna true quando o elemento em que o iterador está posicionado atualmente possui pelo menos um elemento filho, e false quando esse elemento é um nó folha (somente texto ou vazio).
Ele vem da interface RecursiveIterator do PHP, que tanto SimpleXMLIterator quanto SimpleXMLElement implementam. Sua função é informar ao mecanismo de travessia recursiva: "devo descer neste nó?" Essa é a ideia central e a fonte da maior parte da confusão:
hasChildren() não pergunta "o $this tem filhos?" Ele pergunta "o elemento na posição atual do iterador tem filhos?" Normalmente você o chama durante um loop com rewind() / valid() / next(), ou deixa um RecursiveIteratorIterator chamá-lo por você — não diretamente em um elemento arbitrário.
public SimpleXMLIterator::hasChildren(): boolO método não recebe parâmetros e retorna um bool. Para ler os filhos quando ele retornar true, combine-o com getChildren().
Configurando um SimpleXMLIterator
hasChildren() existe apenas em SimpleXMLIterator, portanto crie um a partir de sua string XML com new SimpleXMLIterator(), ou carregue um documento e faça o cast. Aqui está um pequeno catálogo onde um elemento tem filhos e outro não:
<?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";
}
}Saída:
book has children:
title: Modern PHP
author: Josh Lockhart
note (leaf): Closed on holidaysObserve que o loop percorre o iterador manualmente com rewind(), valid(), next(), key() e current(). hasChildren() informa sobre o elemento em que o cursor está posicionado naquele momento.
Percorrendo a árvore inteira recursivamente
O verdadeiro benefício de hasChildren() aparece quando você passa o iterador para um RecursiveIteratorIterator. Esse wrapper chama hasChildren() e getChildren() por você, descendo automaticamente para que você possa achatar um documento aninhado de qualquer profundidade:
<?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";
}Saída:
shelf
book
title
deskVocê nunca chama hasChildren() manualmente aqui — o RecursiveIteratorIterator o usa internamente para decidir quando fazer a recursão.
Quando utilizá-lo
- Você está iterando uma estrutura XML desconhecida e precisa saber se deve aprofundar antes de ler os valores.
- Você está construindo uma visualização em árvore, breadcrumb ou lista achatada a partir de XML aninhado.
- Você quer que o mecanismo de iteradores do PHP (
RecursiveIteratorIterator, filtros) percorra o XML por você em vez de escrever loopsforeachaninhados.
Se você simplesmente quer os filhos de um elemento conhecido, geralmente não precisa de hasChildren() — chame children() em um SimpleXMLElement e verifique se o resultado está vazio com count().
Armadilhas comuns
- Chamá-lo em
SimpleXMLElement. UmSimpleXMLElementsimples criado comsimplexml_load_file()ousimplexml_load_string()implementaRecursiveIterator, mas a semântica amigável dehasChildren()pertence aoSimpleXMLIterator. Use essa classe quando quiser este método. - Esperar que detecte atributos ou texto.
hasChildren()olha apenas para elementos filhos. Um elemento que contém apenas texto ou apenas atributos retornafalse. - Chamá-lo antes de posicionar o cursor. Sempre faça
rewind()(ou itere) primeiro; o resultado reflete a posição atual, que é indefinida antes do primeiro elemento.
Conclusão
SimpleXMLIterator::hasChildren() é o guardião da travessia recursiva de XML: ele informa se o elemento atual do iterador possui elementos filhos para que seu código — ou um RecursiveIteratorIterator — saiba quando descer. Combine-o com getChildren() para ler esses filhos, e recorra a children() ou ao guia completo de SimpleXML quando precisar apenas do conteúdo de um nó diretamente.