Вот код, который будет делать то, что вы хотите.Он сохраняет значение для каждого элемента, когда встречается с узлом TEXT
или CDATA
, а затем сохраняет его, когда достигает значения END_ELEMENT
.В то время сохраненное значение устанавливается на ''
, поэтому, если для элемента не найдено значение, оно получает пустую строку (это можно изменить на null
, если вы предпочитаете).Он также имеет дело с самозакрывающимися тегами, например <brandName />
с проверкой isEmptyElement
, когда обнаружен узел ELEMENT
.Это использует переменные переменные PHP, чтобы избежать длинной последовательности if ($nodename == ...)
, которую вы имеете в своем коде, но также использует массив для хранения значений для каждого продукта, что, на мой взгляд, в долгосрочной перспективе является лучшим решением для вашей проблемы.
$reader = new XMLReader();
$reader->xml($xml);
$count = 0;
$this_value = '';
$products = array();
while($reader->read()) {
switch ($reader->nodeType) {
case XMLReader::ELEMENT:
// deal with self-closing tags e.g. <productEan />
if ($reader->isEmptyElement) {
${$reader->name} = '';
$products[$count][$reader->name] = '';
}
break;
case XMLReader::TEXT:
case XMLReader::CDATA:
// save the value for storage when we get to the end of the element
$this_value = $reader->value;
break;
case XMLReader::END_ELEMENT:
if ($reader->name == 'product') {
$count++;
print_r(array($categoryName, $brandName, $productCode, $productId, $productFullName, $productEan, $productEuroPriceNetto, $productFrontendPriceNetto, $productFastestSupplierQuantity, $deliveryEstimatedDays));
}
elseif ($reader->name != 'products') {
${$reader->name} = $this_value;
$products[$count][$reader->name] = $this_value;
// set this_value to a blank string to allow for empty tags
$this_value = '';
}
break;
case XMLReader::WHITESPACE:
case XMLReader::SIGNIFICANT_WHITESPACE:
default:
// nothing to do
break;
}
}
$reader->close();
print_r($products);
Я опустил вывод, так как он довольно длинный, но вы можете увидеть работающий код в этой демонстрации на 3v4l.org .