W3docs

haschildren()

Scopri come hasChildren() di PHP verifica se l'elemento XML corrente ha nodi figli, con esempi eseguibili e insidie comuni.

Cosa fa hasChildren()

hasChildren() è un metodo della classe SimpleXMLIterator. Restituisce true quando l'elemento su cui l'iteratore è attualmente posizionato ha almeno un elemento figlio, e false quando quell'elemento è un nodo foglia (solo testo o vuoto).

Proviene dall'interfaccia RecursiveIterator di PHP, implementata sia da SimpleXMLIterator che da SimpleXMLElement. Il suo compito è comunicare al motore di attraversamento ricorsivo: "devo scendere in questo nodo?" Questa è l'idea chiave, e la fonte della maggior parte della confusione:

Attenzione

hasChildren() non chiede "ha figli $this?" Chiede "l'elemento alla posizione corrente dell'iteratore ha figli?" Di solito lo si chiama mentre si itera con rewind() / valid() / next(), oppure si lascia che un RecursiveIteratorIterator lo chiami per te — non direttamente su un elemento arbitrario.

public SimpleXMLIterator::hasChildren(): bool

Il metodo non accetta parametri e restituisce un bool. Per leggere i figli quando restituisce true, abbinalo a getChildren().

Configurare un SimpleXMLIterator

hasChildren() esiste solo su SimpleXMLIterator, quindi creane uno dalla tua stringa XML con new SimpleXMLIterator(), oppure carica un documento e convertilo. Ecco un piccolo catalogo in cui un elemento ha figli e uno 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";
    }
}

Output:

book has children:
  title: Modern PHP
  author: Josh Lockhart
note (leaf): Closed on holidays

Nota che il ciclo scorre l'iteratore manualmente con rewind(), valid(), next(), key() e current(). hasChildren() riporta il risultato per qualsiasi elemento su cui il cursore si trova in quel momento.

Percorrere l'intero albero in modo ricorsivo

Il vero vantaggio di hasChildren() emerge quando si passa l'iteratore a un RecursiveIteratorIterator. Quel wrapper chiama hasChildren() e getChildren() per te, discendendo automaticamente così puoi appiattire un documento annidato di qualsiasi profondità:

<?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";
}

Output:

shelf
  book
    title
  desk

Non è necessario chiamare hasChildren() manualmente qui — RecursiveIteratorIterator lo usa internamente per decidere quando ricorrere.

Quando usarlo

  • Stai iterando una struttura XML sconosciuta e hai bisogno di sapere se scendere più in profondità prima di leggere i valori.
  • Stai costruendo una vista ad albero, una breadcrumb o un elenco appiattito da XML annidato.
  • Vuoi che la macchina degli iteratori di PHP (RecursiveIteratorIterator, filtri) attraversi l'XML per te invece di scrivere cicli foreach annidati.

Se vuoi semplicemente i figli di un elemento noto, di solito non hai bisogno di hasChildren() — chiama children() su un SimpleXMLElement e verifica se il risultato è vuoto con count().

Insidie comuni

  • Chiamarlo su SimpleXMLElement. Un semplice SimpleXMLElement creato con simplexml_load_file() o simplexml_load_string() implementa RecursiveIterator, ma la semantica utile di hasChildren() appartiene a SimpleXMLIterator. Usa quella classe quando vuoi questo metodo.
  • Aspettarsi che rilevi attributi o testo. hasChildren() guarda solo gli elementi figli. Un elemento che contiene solo testo o solo attributi restituisce false.
  • Chiamarlo prima di posizionare il cursore. Esegui sempre rewind() (o itera) prima; il risultato riflette la posizione corrente, che è indefinita prima del primo elemento.

Conclusione

SimpleXMLIterator::hasChildren() è il guardiano dell'attraversamento ricorsivo XML: indica se l'elemento corrente dell'iteratore ha elementi figli, così il tuo codice — o un RecursiveIteratorIterator — sa quando scendere. Abbinalo a getChildren() per leggere quei figli, e ricorri a children() o alla guida più ampia su SimpleXML quando hai bisogno direttamente del contenuto di un nodo.

Esercitazione

Pratica
Cosa restituisce SimpleXMLIterator::hasChildren()?
Cosa restituisce SimpleXMLIterator::hasChildren()?
Was this page helpful?