View Sidebar
Яндекс.Метрика
 
Автоматическая загрузка отчетов брокера АЛОР на smart-lab.ru. Часть 2. Чтение отчета XML

Автоматическая загрузка отчетов брокера АЛОР на smart-lab.ru. Часть 2. Чтение отчета XML

03.04.2016 17:180 comments

Теперь наша задача получить из XML-файла отчета брокера информацию о сальдо на конец дня, сумму по операциям зачислений/списаний, сформировать комментарии. Начало цикла читайте тут.

Функция чтения отчета будет возвращать такой массив:


$result['movement'] = ''; //сумма Зачисления/списание
$result['comment'] = ''; // Комментарий
$result['account'] = ''; //Остаток

Например, если сальдо на конец дня составил 123 784.70 руб., и было две операций списания со счета:

alor-operation
то возвращаемый массив будет содержать следующие значения

$result['movement'] = '-2250'; //сумма Зачисления/списание
$result['comment'] = 'Вознаграждение брокера за ПО (-2 000.00), Вознаграждение брокера (-250.00)'; // Комментарий
$result['account'] = '123784.7'; //Остаток

В данном случае, мне представилось проще преобразовать структуру XML в массив, и работать уже с массивом.

Конвертация структуры XML в массив

Вот функция которая конвертирует XML в массив, её я нашел в интернете:


//Функция переводит XML в Массив
function xml_to_array($XML)
{
    // Clean up white space
    $XML = trim($XML);
    $returnVal = $XML; // Default if just text;
 
    // Expand empty tags
    $emptyTag = '<(.*)/>';
    $fullTag = '<\\1></\\1>';
    $XML = preg_replace ("|$emptyTag|", $fullTag, $XML);
 
    $matches = array();
    if (preg_match_all('|<(.*)>(.*)</\\1>|Ums', trim($XML), $matches))
    {
        if (count($matches[1]) > 0) $returnVal = array(); // If we have matches then return an array else just text
        foreach ($matches[1] as $index => $outerXML)
        {
            $attribute = $outerXML;
            $value = xml_to_array($matches[2][$index]);
            if (! isset($returnVal[$attribute])) $returnVal[$attribute] = array();
                $returnVal[$attribute][] = $value;
        }
    }
    // Bring un-indexed singular arrays to a non-array value.
    if (is_array($returnVal)) foreach ($returnVal as $key => $value)
    {
        if (is_array($value) && count($value) == 1 && key($value) === 0)
        {
            $returnVal[$key] = $returnVal[$key][0];
        }
    }
    return $returnVal;
}

Разбираем отчёт АЛОР

Сразу конечная функция, которая возвращает требуемый результат в массиве:

function data_forts($xml) {

if ( empty($xml) ) { //Если отчет пустой

$result['movement'] = ''; //сумма Зачисления/списание
$result['comment'] = ''; // Комментарий
$result['account'] = ''; //Остаток

return $result;

}

$xml = str_replace ( '<?xml version="1.0" encoding="windows-1251"?>', "", $xml); //Удаляем ненужный одинарный тег (иначе неправильно будет парсица)
$xml = str_replace ( "<cellValue />", "<cellValue></cellValue>", $xml); //Перед разбором XML заменяем одинарный тег двойным (иначе неправильно будет парсица)

$arr_xml = xml_to_array($xml);
unset($xml);

$result = movement_forts($arr_xml);
$result['account'] = account_forts($arr_xml); //Добавляем сальдо на конец дня

return $result;
}

Функция простая, пробежимся по коду.

Функциями замены str_replace приводит XML код в пригодный для обработки функцией xml_to_array.

Функция movement_forts возвращает в массиве движение по счету и комментарий.

Функция account_forts возвращает сальдо на конец дня.

Функция получения сальдо на конец дня

Вот код функции account_forts:

//Возвращает сумму на конец дня
function account_forts(&$arr) {

$a = $arr['report']['content']['main']['moneyMovements']['row']; //В этой структуре есть Сальдо на конец текущего дня

$last = count($a)-1; //Получаем индекс последней строки, т.к. Сальдо на конец текущего дня всегда в последней строке данной структуры

$str =  $a[$last]['cell'][3]['cellValue'];

$str = str_to_double($str);

return $str;
}

Мы просто обращаемся к нужному нам элементу массива, содержащего сальдо на конец дня.

Преобразование строки в число

Преобразование строки в число осуществляем этой функцией:


//Переводит число из строки в настоящее число
function str_to_double($str) {
    
    //$str = str_replace ( ".", ",", $str); //Заменяем точку на запятую
    $str = preg_replace("/[^x\d|*\.-]/", "", $str); //Удаляем пробелы (точнее всё кроме цифр, точки и минуса)
    $str = (real) $str;
    return $str;
}

Движение счета и комментарий

Самая сложная функция на сегодня - movement_forts:


//Возвращает движение средств с комментарием
function movement_forts(&$arr) {
    
    $result['movement'] = ''; //сумма Зачисления/списание
    $result['comment'] = ''; // Комментарий
    
    $a = $arr['report']['content']['tables']['table']; //Структура с основными таблицами, где может быть таблица 'Зачисление/списание денежных средств'

    $flag = FALSE;
    $num = count($a);    //число таблиц в структуре
    for ($i = 0; $i < $num; $i++) {

        if ( $a[$i]['headerText'] === 'Зачисление/списание денежных средств' ) { //ищем нужную таблицу по заголовку
            $a = $a[$i]['row']; //переходим к найденной таблице 
            $flag = TRUE;
            break;
        }
    }    
    
    if ( $flag === FALSE ) {
        return $result; // Если не нашли заголовок 'Зачисление/списание денежных средств', то возвращаем пустой результат
    }
    
    $num = count($a);    //число строк в таблиц (первая строка всегда шапка таблицы)
    for ($i = 1; $i < $num; $i++) {
        process_line($a[$i], $result['movement'], $result['comment'] );    //обрабатываем каждую строку
    }
        
    return $result;    
}

Вспомогательная функция process_line для добавления строки комментария:

//Обрабатываем строку таблицы. Добавляем сумму и комментарий
function process_line(&$a, &$movement, &$comment) {

$rinok = $a['cell'][0]['cellValue']; //Рынок
$oper = $a['cell'][1]['cellValue']; //Операция
$valuta = $a['cell'][2]['cellValue']; //Вид валюты
$summa = $a['cell'][3]['cellValue']; //Сумма
$prim = $a['cell'][4]['cellValue'];  //Примечание

$movement = $movement + str_to_double($summa);

if ( $comment <> '' ) {
$comment.= ', ';
}

$comment .= "$oper ($summa)";
}

Описывать эти функции не буду, в коде есть комментарии.

Рабочий пример сегодняшнего кода и кода из первой части вы найдете в этом архиве.

Переходим к части 3.

Своё мнение вы можете оставить ниже в комментариях...

Добавить комментарий


css.php