Возникли проблемы с извлечением курсов обмена ECB в XML с XML. Полный исходный код - PullRequest
2 голосов
/ 20 августа 2011

Мне нужно взять список исторических справочных курсов валют для внутренней системы учета.

Этот вопрос касается только следующего кода, не стесняйтесь использовать этот код, если он окажется полезным (иКонечно, как только мы получим ответ, чтобы исправить окончательное «пустяк». Я включил дамп структуры БД в код, все подпрограммы БД закомментированы, пока только повторяются данные отладки.

Данные взяты изЕвропейский центральный банк XML найден по адресу http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml

ИСПРАВЛЕНО! Не стесняйтесь использовать этот код, если вам нужно вытащить список исторических значений обменного курса в БД. Обязательно удалите отладочную эхо-команду и разберитесь сБД запрашивает

<?php

/* DB structure:
 CREATE TABLE IF NOT EXISTS `currency_rates_history` (
  `id` int(4) NOT NULL auto_increment,
  `currency` char(3) character set utf8 collate utf8_unicode_ci NOT NULL default '',
  `rate` float NOT NULL default '0',
  `date` int(4) NOT NULL default '0',
  `est` tinyint(1) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8_unicode_ci AUTO_INCREMENT=1 ;

*/

error_reporting(E_ALL);

$table = "currency_rates_history";

$secs = '86400';

$prev_date = time();

$days = "0";

$XML=simplexml_load_file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml");    // European Central Bank xml only contains business days! oh well....


foreach($XML->Cube->Cube as $time)                                                          // run first loop for each date section
{

    echo "<h1>".$time["time"].'</h1>';

    list($dy,$dm,$dd) = explode("-", $time["time"]);

    $date = mktime(8,0,0,$dm,$dd,$dy);

    echo ($prev_date - $date)."<br />";

    if(($prev_date - $date) > $secs)                                                        // detect missing weekend and bank holiday values.
    {

        echo "ooh";                                                                         // for debug to search the output for missing days

        $days =(round((($prev_date - $date)/$secs),0)-1);                                   // got to remove 1 from the count....

        echo $days;                                                                         // debug, will output the number of missing days

    }
    foreach($time->Cube as $_rate)                                              // That fixed it! run the 2nd loop and ad enter the new exchange values....
    {

        $rate = floatval(str_replace(",", ".", $_rate["rate"]));


        if($days > 0)                                                                       // add the missing dates using the last known value, coul dbe more accurate but at least there is some reference data to work with
        {
            $days_cc = $days;                                                               // need to keep $days in mem for the next currency

            while($days_cc > 0)
            {
                echo $rate;
                echo date('D',$date+($days_cc*$secs))."<br />";
                /*
                mysql_query("LOCK TABLES {$table} WRITE");

                mysql_query("INSERT INTO {$table}(rate,date,currency,est) VALUES('{$rate}','".($date+($days_cc*$secs))."','{$currency}','1')");

                mysql_query("UNLOCK TABLES");
                */
                $days_cc = ($days_cc - 1);  // count down
            }
        }

        $currency = addslashes(strtolower($_rate["currency"]));
        /*
        mysql_query("LOCK TABLES {$table} WRITE");
//      mysql_query("UPDATE {$table} SET rate='{$rate}',date='{$date}' WHERE currency='{$currency}' AND date='{$date}'");   // all this double checking was crashing the script
//      if (mysql_affected_rows() == 0)
//      {
            mysql_query("INSERT INTO {$table}(rate,date,currency) VALUES('{$rate}','{$date}','{$currency}')");              // so just insert, its only going to be run once anyway!
//      }

        mysql_query("UNLOCK TABLES");
        */

        echo "1&euro;=  ".$currency."   ".$rate.", date:   ".date('D d m Y',$date)."<br/>";
    }
          $days="";                                                                         // clear days value
    $prev_date = $date;                                                                     // store the previous date
}

echo "<h1>Currencies Saved!</h1>";
?>

Итак ..... проблема во втором цикле foreach: foreach ($ XML-> Cube-> Cube-> Cube as $ _rate), если вы попытаетесь запустить скриптВы заметите, что даты правильные, он хорошо обрабатывает пропущенные выходные и праздничные дни, но значения ставок всегда ссылаются только на последние ставки в XML, то есть на сегодняшние значения.

Это должноизвлекать данные из соответствующей области в XML, то есть ставки на данную дату ... но это не так.Это проблема в simplexml_load_file или я пропустил что-то глупое в своем коде?Голова начинает болеть, так что собираюсь сделать перерыв.Приветствуются свежие глаза!

1 Ответ

3 голосов
/ 20 августа 2011

$XML->Cube->Cube->Cube во втором цикле: $XML->Cube->Cube всегда относится к первому второму уровню cube в первом первом уровне cube.Итак, вы перебираете третий уровень cubes в том же элементе.Таким образом, вы получили только сегодняшние тарифы.Имеет смысл?

Попробуйте вместо этого.Я изменил ваш код для вывода из командной строки, а не HTML.Единственное существенное изменение во втором foreach утверждении ...

$XML=simplexml_load_file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml");
foreach($XML->Cube->Cube as $time){
    echo "----".$time["time"]. "----\n";
    foreach($time->Cube as $_rate){
        $rate = floatval(str_replace(",", ".", $_rate["rate"]));
        $currency = addslashes(strtolower($_rate["currency"]));
        echo "1 euro =  ".$currency."   ".$rate . "\n";
    }
    echo "------------------\n\n";
}
echo "Done!";
...