Загрузка данных из Yandex Direct API в QlikView (преобразование JSON в XML)
В Yandex Direct API имеется инструмент подключения к данным сервиса, чтобы генерировать аналитическую отчетность по маркетинговым кампаниям. Чтобы получить данные, необходимо отправлять на сервер API запросы и сервер возвращает результат в формате JSON. Пока что QlikView не умеет напрямую работать с этим форматом, поэтому одним из выходов является написание конвертора формата JSON в формат XML. Yandex Metrika умеет возвращать формат XML, Yandex Direct пока что отдает данные в JSON.
Ниже приведен пример php-скрипта, который преобразует JSON в XML. Плюс вызывается функция для преобразования результата Yandex Direct API в XML:
<?php /** * Эта вспомогательная функция проверяет, является ли массив * ассоциативным - то есть есть ли в нем строковые ключи * * @param array $array * @return bool */ function isAssocArray($array) { if(!is_array($array)) { return false; } if(count($array) < 1) { return true; } foreach($array as $key => $value) { if(is_numeric($key)) { return false; } } return true; } /** * Эта вспомогательная функция генерирует XML-элемент * * @param mixed $content Содержимое элемента * @param string $parent_tag Имя родительского тега на случай, если * * @return bool */ function generateXmlTagContents($content, $parent_tag = 'WHATTAG') { if(is_array($content)) { // Содержимое - массив if(isAssocArray($content)) { // Содержимое - массив вида array('id' => ..., 'name' => ...) return arrayToXml($content); } else { // Содержимое - массив вида array(0 => ..., 1 => ...) $result = ''; foreach($content as $content_value) { $result .= "<{$parent_tag}>" . generateXmlTagContents($content_value, $parent_tag) . "</{$parent_tag}>"; } return $result; } } else { // Содержимое - не массив. $content = (string)$content; if(preg_match('#[<>&]#', $content)) { // Если в содержимом есть специальные символы, то его нужно обернуть в <![CDATA[...]]> return "<![CDATA[{$content}]]>"; } return $content; } } /** * Эта функция генерирует XML на основе массива * * @param array $array Исходный массив * @return string Итоговый XML */ function arrayToXml(array $array) { $result = ''; foreach($array as $tag => $content) { // Сделать $tag (будущее имя тега) маленькими буквами $tag = strtolower($tag); // Эта строка вырезает из имени тега все буквы, кроме // латинского алфавита, дефиса, подчеркивания, двоеточия // и цифр (эти символы разрешены в именах тегов XML) // (ну, не только они, на самом деле, но в основном используются они) $tag = preg_replace('#[^-_:a-z0-9]#', '', $tag); if(is_array($content) && isAssocArray($content) === false) { // Если содержимое - это массив с числовыми ключами, то выводить сам тэг // сейчас не нужно - у каждого элемента он будет свой, сгенерированный // функцией generateXmlTagContents() $result .= generateXmlTagContents($content, $tag); } else { // В противном случае это обычный элемент, и мы выводим сам тэг, а // generateXmlTagContents() займется его содержимым. $result .= "<{$tag}>" . generateXmlTagContents($content, $tag) . "</{$tag}>"; } } return $result; } // ---- Ниже пример использования функции arrayToXml() -------------------- $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,'https://api-sandbox.direct.yandex.com/json/v5/keywords'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS,'{"method":"get","params":{"SelectionCriteria":{"CampaignIds":[181497,181498,181499]},"FieldNames":["Id","Keyword","State","Status","AdGroupId","CampaignId","Bid","ContextBid","StrategyPriority"] }}'); //Post Fields curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $headers = [ 'POST /json/v5/keywords/ HTTP/1.1', 'Host: api-sandbox.direct.yandex.com', 'Authorization: Bearer AQAAAAAJ8KAaAAP5x0wl5UonY0Cfu3KFIyi1aUY', 'Accept-Language: ru', 'Client-Login: iv-shamaev', 'Content-Type: application/json; charset=utf-8', ]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $server_output = curl_exec ($ch); curl_close ($ch); $data = json_decode($server_output, true); $result = arrayToXml($data); // Указать, что весь последующий вывод - это XML // Но надо иметь в виду, что до этой команды ничего нельзя выводить. header('Content-Type: text/xml; charset=utf-8'); // Эта строка нужна в начале каждого XML-файла echo '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>'; // После нее можно вывести само содержимое echo $result; ?>
Преобразование JSON в XML требуется для интеграции Yandex Direct API с QlikView. Код вставляется в script_name.php на домене и данные загружаются через URL:
http://my_domain_name.ru/script_name.php
Еще один пример с обычным массивом JSON, который преобразуется в XML:
<?php /** * Эта вспомогательная функция проверяет, является ли массив * ассоциативным - то есть есть ли в нем строковые ключи * * @param array $array * @return bool */ function isAssocArray($array) { if(!is_array($array)) { return false; } if(count($array) < 1) { return true; } foreach($array as $key => $value) { if(is_numeric($key)) { return false; } } return true; } /** * Эта вспомогательная функция генерирует XML-элемент * * @param mixed $content Содержимое элемента * @param string $parent_tag Имя родительского тега на случай, если * * @return bool */ function generateXmlTagContents($content, $parent_tag = 'WHATTAG') { if(is_array($content)) { // Содержимое - массив if(isAssocArray($content)) { // Содержимое - массив вида array('id' => ..., 'name' => ...) return arrayToXml($content); } else { // Содержимое - массив вида array(0 => ..., 1 => ...) $result = ''; foreach($content as $content_value) { $result .= "<{$parent_tag}>" . generateXmlTagContents($content_value, $parent_tag) . "</{$parent_tag}>"; } return $result; } } else { // Содержимое - не массив. $content = (string)$content; if(preg_match('#[<>&]#', $content)) { // Если в содержимом есть специальные символы, то его нужно обернуть в <![CDATA[...]]> return "<![CDATA[{$content}]]>"; } return $content; } } /** * Эта функция генерирует XML на основе массива * * @param array $array Исходный массив * @return string Итоговый XML */ function arrayToXml(array $array) { $result = ''; foreach($array as $tag => $content) { // Сделать $tag (будущее имя тега) маленькими буквами $tag = strtolower($tag); // Эта строка вырезает из имени тега все буквы, кроме // латинского алфавита, дефиса, подчеркивания, двоеточия // и цифр (эти символы разрешены в именах тегов XML) // (ну, не только они, на самом деле, но в основном используются они) $tag = preg_replace('#[^-_:a-z0-9]#', '', $tag); if(is_array($content) && isAssocArray($content) === false) { // Если содержимое - это массив с числовыми ключами, то выводить сам тэг // сейчас не нужно - у каждого элемента он будет свой, сгенерированный // функцией generateXmlTagContents() $result .= generateXmlTagContents($content, $tag); } else { // В противном случае это обычный элемент, и мы выводим сам тэг, а // generateXmlTagContents() займется его содержимым. $result .= "<{$tag}>" . generateXmlTagContents($content, $tag) . "</{$tag}>"; } } return $result; } // ---- Ниже пример использования функции arrayToXml() -------------------- $input = ' { "Result":{ "Product":[ {"Id":181497,"Name":"Product 1"}, {"Id":181498,"Name":"Product 2"}, {"Id":181499,"Name":"Product 3"}, {"Id":181499,"Name":"Pr<od&uct 3"} ] } }'; $data = json_decode($input, true); $result = arrayToXml($data); // Указать, что весь последующий вывод - это XML // Но надо иметь в виду, что до этой команды ничего нельзя выводить. header('Content-Type: text/xml; charset=utf-8'); // Эта строка нужна в начале каждого XML-файла echo '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>'; // После нее можно вывести само содержимое echo $result; ?>
Загружаем данные в QlikView:
Получили код для загрузки данных в QlikView из JSON через преобразование в XML:
// Start of [arraytoxml.php] LOAD statements product: LOAD id, name FROM [http://my_domain_name.ru/arraytoxml.php] (XmlSimple, Table is [result/product]); // End of [arraytoxml.php] LOAD statements
Автор: Иван Шамаев