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:
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(): boolDie 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 holidaysBeachten 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
deskSie 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 verschachtelteforeach-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 einfachesSimpleXMLElement, das mitsimplexml_load_file()odersimplexml_load_string()erstellt wurde, implementiertRecursiveIterator, aber die benutzerfreundlichehasChildren()-Semantik gehört zuSimpleXMLIterator. 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, gibtfalsezurü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.