Загрузка данных из 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
Автор: Иван Шамаев






