@KoNnY
web-master

Как в SimpleXMLReader получить атрибут родительского элемента N уровня, зная его дочерний элемент?

Добрый день!

Имеется xml-файл с товарами (более 300 тыс строк, размером в 40Мб). Нужно этот файл спарсить и залить данные в БД OpenCart.
Делал парсинг с помощью кода
$properties = $products->getElementsByTagName("Property"); // Получаем список всеx атрибутов
	
	$attributes = array(); // создаем пустой массив атрибутов
	$i = 0;
	foreach ($properties as $node) {
		$attributes[$i]['id'] = $node->getAttribute('ID');
		$attributes[$i]['name'] = $node->getAttribute('Name');
		$attributes[$i]['sort_order'] = $node->getAttribute('Sort');
$attributes[$i]['articul'] =  $node->parentNode->parentNode->parentNode->getAttribute('Articul');
		$i++;
	}


Все хорошо обрабатывается, есть возможность заполучить значение Артикул у родительского элемента
$attributes[$i]['articul'] =  $node->parentNode->parentNode->parentNode->getAttribute('Articul');


Но вот с большим объемом данных этот скрипт зависает на полчаса... что очень плохо

Нашел в Интернете пример работы SimpleXMLReader. Сделал вывод им, так он шустро обработал данные в течении нескольких секунд. Ниже частично приведен его код
class ExampleXmlReader1 extends SimpleXMLReader
{
    public function __construct()  {
        // by node name
        $this->registerCallback("Property", array($this, "callbackAttributes"));
    }

    protected function callbackAttributes($reader)  {
        $xml = $reader->expandSimpleXml();
        $attributes = $xml->attributes();
        $ref = (string) $attributes->{"ID"};
        if ($ref) {
            $name = (string) $attributes->{"Name"};
            $sort = (int) $attributes->{"Sort"};
            echo "$ref: $name - $sort;\n";
        }
        return true;
    }
}


Но вот незадача, никак не могу найти пример обращения к родительским узлам и их атрибутам... Мне нужно заполучить Артикул товара, но как это сделать - ума не приложу. Помогите, пожалуйста.
  • Вопрос задан
  • 966 просмотров
Решения вопроса 1
@SilverSlice
Расширение XMLReader, которое используется в SimpleXMLReader, читает документ в потоке, т.е. последовательно, без построения дерева DOM. Поэтому вы не сможете обратиться к родительским элементам. Вам нужно при чтении запомнить в переменной атрибут (артикул) нужного элемента и потом подставить его в результирующий массив.

Должно получиться примерно так:
$reader = new XMLReader();
$reader->open('file.xml');

$attributes = array();
$i = 0;
while ($reader->read()) {
    if ($reader->nodeType == XMLReader::ELEMENT && $reader->localName == 'Product') {
        $articul = $reader->getAttribute('Articul');

        while ($reader->read()) {
            if ($reader->nodeType == XMLReader::ELEMENT && $reader->localName == 'Property') {
                $attributes[$i]['id'] = $reader->getAttribute('ID');
                $attributes[$i]['name'] = $reader->getAttribute('Name');
                $attributes[$i]['sort_order'] = $reader->getAttribute('Sort');
                $attributes[$i]['articul'] =  $articul;
                $i++;
            }
            if ($reader->nodeType == XMLReader::END_ELEMENT && $reader->localName == 'Product') {
                break;
            }
        }
    }
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы