W3docs

haschildren()

PHP SimpleXMLIterator::hasChildren() prüft, ob das aktuelle XML-Element Kindknoten hat — mit ausführbaren Beispielen und häufigen Fallstricken.

Was hasChildren() tut

hasChildren() ist eine Methode der SimpleXMLIterator-Klasse. Sie gibt true zurück, wenn das Element, auf dem der Iterator aktuell positioniert ist, mindestens ein Kindelement besitzt, und false, wenn das Element ein Blattknoten (nur Text oder leer) ist.

Sie stammt aus dem PHP-Interface RecursiveIterator, das sowohl SimpleXMLIterator als auch SimpleXMLElement implementieren. Ihre Aufgabe besteht darin, einer rekursiven Durchlauf-Engine mitzuteilen: „Soll ich in diesen Knoten hinabsteigen?" Das ist der entscheidende Gedanke und die Quelle der meisten Verwirrung:

Warnung

hasChildren() fragt nicht „hat $this Kinder?", sondern „hat das Element an der aktuellen Position des Iterators Kinder?" In der Regel wird die Methode beim Durchlaufen mit rewind() / valid() / next() aufgerufen, oder ein RecursiveIteratorIterator ruft sie für Sie auf — nicht direkt auf einem beliebigen Element.

public SimpleXMLIterator::hasChildren(): bool

Die Methode erwartet keine Parameter und gibt einen bool zurück. Um die Kinder zu lesen, sobald sie true zurückgibt, kombinieren Sie sie mit getChildren().

Einen SimpleXMLIterator einrichten

hasChildren() existiert nur auf SimpleXMLIterator. Erstellen Sie daher eine Instanz aus Ihrem XML-String mit new SimpleXMLIterator() oder laden Sie ein Dokument und konvertieren Sie es. Hier ist ein kleines Beispiel, bei dem ein Element Kinder hat und ein anderes nicht:

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

Ausgabe:

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

Beachten Sie, dass die Schleife den Iterator manuell mit rewind(), valid(), next(), key() und current() durchläuft. hasChildren() gibt Auskunft über das Element, auf dem der Cursor zu diesem Zeitpunkt steht.

Den gesamten Baum rekursiv durchlaufen

Der eigentliche Nutzen von hasChildren() zeigt sich, wenn Sie den Iterator an einen RecursiveIteratorIterator übergeben. Dieser Wrapper ruft hasChildren() und getChildren() für Sie auf und steigt automatisch ab, sodass Sie ein verschachteltes Dokument beliebiger Tiefe flach darstellen können:

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

Ausgabe:

shelf
  book
    title
  desk

Sie rufen hasChildren() hier nie manuell auf — RecursiveIteratorIterator verwendet die Methode intern, um zu entscheiden, wann rekursiv abgestiegen werden soll.

Wann Sie es verwenden sollten

  • Sie iterieren über eine unbekannte XML-Struktur und müssen wissen, ob Sie tiefer einsteigen sollen, bevor Sie Werte lesen.
  • Sie erstellen eine Baumansicht, einen Breadcrumb oder eine flache Liste aus verschachteltem XML.
  • Sie möchten, dass PHPs Iterator-Maschinerie (RecursiveIteratorIterator, Filter) XML für Sie durchläuft, anstatt verschachtelte foreach-Schleifen zu schreiben.

Wenn Sie einfach die Kinder eines bekannten Elements abrufen möchten, benötigen Sie hasChildren() in der Regel gar nicht — rufen Sie children() auf einem SimpleXMLElement auf und prüfen Sie, ob das Ergebnis mit count() leer ist.

Häufige Fallstricke

  • Aufruf auf SimpleXMLElement. Ein einfaches SimpleXMLElement, das mit simplexml_load_file() oder simplexml_load_string() erstellt wurde, implementiert RecursiveIterator, aber die benutzerfreundliche hasChildren()-Semantik gehört zu SimpleXMLIterator. Verwenden Sie diese Klasse, wenn Sie die Methode benötigen.
  • Erwartung, dass Attribute oder Text erkannt werden. hasChildren() betrachtet ausschließlich untergeordnete Elemente. Ein Element, das nur Text oder nur Attribute enthält, gibt false zurück.
  • Aufruf vor der Positionierung des Cursors. Rufen Sie immer zuerst rewind() auf (oder iterieren Sie); das Ergebnis spiegelt die aktuelle Position wider, die vor dem ersten Element undefiniert ist.

Fazit

SimpleXMLIterator::hasChildren() ist der Türhüter des rekursiven XML-Durchlaufs: Sie meldet, ob das aktuelle Element des Iterators Kindelemente hat, damit Ihr Code — oder ein RecursiveIteratorIterator — weiß, wann abgestiegen werden soll. Kombinieren Sie sie mit getChildren(), um diese Kinder zu lesen, und greifen Sie auf children() oder den umfassenderen SimpleXML-Leitfaden zurück, wenn Sie den Inhalt eines Knotens direkt benötigen.

Übung

Übung
Was gibt SimpleXMLIterator::hasChildren() zurück?
Was gibt SimpleXMLIterator::hasChildren() zurück?
Was this page helpful?