Skip to content

Instantly share code, notes, and snippets.

@ikenfin
Created September 22, 2016 17:21
Show Gist options
  • Save ikenfin/27ff6a7f9710b587dc32d5b21d8a3a4e to your computer and use it in GitHub Desktop.
Save ikenfin/27ff6a7f9710b587dc32d5b21d8a3a4e to your computer and use it in GitHub Desktop.
Файлы к статье о XMLReader (http://ikfi.ru/article/parsim-xml-s-pomoschju-xmlreader)
<?php
/*
Родительский класс для XML импортеров.
*/
class AbstractAdvertisementXMLReader {
protected $reader;
protected $result = array();
// события
protected $_eventStack = array();
/*
Конструктор класса.
Создает сущность XMLReader и загружает xml, либо бросает исключение
*/
public function __construct($xml_path) {
$this->reader = new XMLReader();
if(is_file($xml_path))
$this->reader->open($xml_path);
else throw new Exception('XML file {'.$xml_path.'} not exists!');
}
/*
Потоково парсит xml и вызывает методы для определенных элементов
напр.
при обнаружении элемента <Rubric> попытается вызвать метод parseRubric
все методы парсинга должны быть public или protected.
*/
public function parse() {
$this->reader->read();
while($this->reader->read()) {
if($this->reader->nodeType == XMLREADER::ELEMENT) {
$fnName = 'parse' . $this->reader->localName;
if(method_exists($this, $fnName)) {
$lcn = $this->reader->name;
// стреляем по началу парсинга блока
$this->fireEvent('beforeParseContainer', array('name' => $lcn));
// пробежка по детям
if($this->reader->name == $lcn && $this->reader->nodeType != XMLREADER::END_ELEMENT) {
// стреляем событие до парсинга элемента
$this->fireEvent('beforeParseElement', array('name' => $lcn));
// вызываем функцию парсинга
$this->{$fnName}();
// стреляем событием по названию элемента
$this->fireEvent($fnName);
// стреляем событием по окончанию парсинга элемента
$this->fireEvent('afterParseElement', array('name' => $lcn));
}
elseif($this->reader->nodeType == XMLREADER::END_ELEMENT) {
// стреляем по окончанию парсинга блока
$this->fireEvent('afterParseContainer', array('name' => $lcn));
}
}
}
}
}
/*
Вызывается при каждом распознавании
*/
public function onEvent($event, $callback) {
if(!isset($this->_eventStack[$event])) //!is_array($this->_eventStack[$event]))
$this->_eventStack[$event] = array();
$this->_eventStack[$event][] = $callback;
return $this;
}
/*
Выстреливает событие
*/
public function fireEvent($event, $params = null, $once = false) {
if($params == null) $params = array();
$params['context'] = $this;
if(!isset($this->_eventStack[$event]))
return false;
$count = count($this->_eventStack[$event]);
if(isset($this->_eventStack[$event]) && $count > 0) {
for($i = 0; $i < $count; $i++) {
call_user_func_array($this->_eventStack[$event][$i], $params);
if($once == true) {
array_splice($this->_eventStack[$event], $i, 1);
}
}
}
}
/*
Получить результаты парсинга
*/
public function getResult() {
return $this->result;
}
/*
Очистить результаты парсинга
*/
public function clearResult() {
$this->result = array();
}
}
<?php
class ConfigXMLReader extends AbstractAdvertisementXMLReader{
/*
Парсит наценки
*/
protected function parseRatio() {
if($this->reader->nodeType == XMLREADER::ELEMENT && $this->reader->localName == 'Ratio') {
$ratio = array(
'group_id' => $this->reader->getAttribute('group_id'),
'id' => $this->reader->getAttribute('id'),
'value' => $this->reader->getAttribute('value')
);
$this->reader->read();
if($this->reader->nodeType == XMLREADER::TEXT)
$ratio['name'] = $this->reader->value;
$this->result['ratios'][] = $ratio;
}
}
/*
Парсит настройки несовместимых наценок
*/
protected function parseRatioException() {
if($this->reader->nodeType == XMLREADER::ELEMENT && $this->reader->localName == 'RatioException') {
$ratioException = array(
'id_1' => $this->reader->getAttribute('id_1'),
'id_2' => $this->reader->getAttribute('id_2')
);
$this->result['ratioExceptions'][] = $ratioException;
}
}
}
@ikenfin
Copy link
Author

ikenfin commented Dec 4, 2019

Я что-то не уловил, или условие AbstractAdvertisementXMLReader.php:64 никогда не выполнится, т.к. противоречит AbstractAdvertisementXMLReader.php:41 ?

Да, видимо 5 лет назад, когда писал этот код знатно косякнул с after/before container событиями (если честно, то я даже не помню зачем вообще их делал, поскольку так и не использовал ни разу).
Думаю самым простым решением будет просто выпилить :50 и с :64 .. :67.

А вообще, надо будет собраться и переписать и статью и примеры.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment