PHP XML дочерний вопрос разбора

Это сводит меня с ума. В моем файле XML у меня есть вложенные дочерние элементы с тем же именем <entry> и я пытаюсь получить только верхний уровень. Если я позвоню getElementsByTagName() он захватывает их всех, так что я разбираюсь с прямыми детьми, и, похоже, ничего не работает правильно.

<locations>
<devices>
<entry>
<a/>
<b/>
<c>
<entry>
..
</entry>
</c>
</entry>
<entry>
<a/>
<b/>
<c>
<entry>
..
</entry>
</c>
</entry>
</devices>
</locations>

<?
$path = "Export.txt" ;
$xml = file_get_contents( $path );
$dom = new DOMDocument( '1.0', 'utf-8' );
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;

// use it as a source
$dom->loadXML($xml) ;

// grab all "devices" should ONLY be 1 device
$devices = $dom->getElementsByTagName('devices');

$entries = array() ;
// parse through each FIRST child...which should be the first level <entry>
// however, the below is empty.
for ($i = 0; $i < $devices->childNodes->length; ++$i) {
echo $count++ ;
$entries[] = $devices->childNodes->item($i);
}

// but I get the following error on this foreach:
// Warning: Invalid argument supplied for foreach() in process.php
foreach ($devices->childNodes as $node) {
echo "This: " . $count++ ;
}

// this prints "1": which is correct.
echo sizeof($devices) ;

// дополнительный вопрос относительно извлечения getElementsByTag из childNode

foreach ($devices as $device) {
foreach($device->childNodes as $child) { // this should be each parent <entry>
$thisC = $child->getElementsByTagName('c') ;  // this should be only <c> tags BUT THIS NEVER SEEMS TO WORK
foreach ($thisC->childNodes as $subEntry) {
echo $subEntry->nodeValue ;
}
}
}

0

Решение

Вы можете использовать запрос XPath, чтобы получить соответствующие элементы:

<?php
$dom = new DomDocument("1.0", "utf-8");
$dom->loadXML(file_get_contents("export.txt"));
$xpath = new DomXPath($dom);
$entries = $xpath->query("/locations/devices/entry");
$count = 0;
// $entries is a DomNodeList
var_dump($entries);
foreach ($entries as $entry) {
//do stuff with $entry
}

Или использовать ваш оригинальный подход:

<?php
$dom = new DomDocument("1.0", "utf-8");
$dom->loadXML(file_get_contents("export.txt"));
$devices = $dom->getElementsByTagName('devices');
$entries = [];
foreach ($devices as $device) {
foreach ($device->childNodes as $child) {
if ($child instanceof DomElement && $child->tagName === "entry") {
$entries[] = $child;
}
}
}
// $entries is an array of DomElement
var_dump($entries);
foreach ($entries as $entry) {
//do stuff with $entry
}
1

Другие решения

Других решений пока нет …