Перетворення XML в JSON на PHP (исходники), HTML, XML, DHTML, Інтернет-технології, статті

Поява технології Asynchronous JavaScript + XML (Ajax) викликало нову хвилю ентузіазму в розробці Web-додатків, а також перегляд багатьма розробниками і проектувальниками своїх методик створення Web-додатків. JavaScript Object Notation (JSON) являє собою формат обміну даними, використовуваний для представлення даних в бізнес-логіку, що виконує в браузерах. Багато Ajax-розробники вважають за краще обробляти дані безпосередньо, використовуючи JSON в JavaScript-коді на стороні браузера. У міру розширення застосування JSON в програмах, що працюють на серверах проміжного рівня, стане необхідним надавати дані корпоративних додатків в браузери в форматі JSON, а не в XML-форматі. Це означає, що розробники повинні перетворити існуючі корпоративні дані на стороні сервера, закодовані в XML-форматі, в JSON-формат перед передачею їх в браузер. В даній статті демонструється використання заснованих на PHP серверних програм для перетворення даних програми з XML-формату в JSON-формат.


Основи XML


XML – це стандарт для розміток. Заснована на XML розмітка використовується для опису даних, що подаються за допомогою тегів, які не обов’язково повинні бути визначені заздалегідь. XML дуже добре розширюємо, оскільки можна створювати нові теги в міру необхідності. У лістингу 1 показаний приклад структури даних, представлених в XML-форматі.


Лістинг 1. Простий приклад XML-даних





<?xml version=”1.0″ encoding=”UTF-8″?>
<contacts>
<contact id=”1″>
<name>John Doe</name>
<phone>123-456-7890</phone>
<address>
<street>123 JFKStreet</street>
<city>Any Town</city>
<state>Any State</state>
<zipCode>12345</zipCode>
</address>
</contact>
</contacts>

Перший рядок – це XML-оголошення, яке вказує версію XML і використовується кодування символів. Потім слід кореневої елемент <contacts>, Який охоплює кілька дочірніх елементів. Вкладена структура дочірніх елементів визначає дані для контакту. Зверніть увагу на те, що елемент <address> містить дочірні елементи, що формують структуру піддереві нижче елемента <contact>. XML також дозволяє вказувати в відкривають тегах атрибути, що мають додаткову інформацію про елементи. Елемент <contact> має атрибут, що присвоює ідентифікатор цьому елементу. XML-документ завершується закриває тегом </contacts> для кореневого елемента.


Основи JSON


JSON не є мовою розмітки, як XML. Це текстовий формат обміну даними. Використовується синтаксис JavaScript-об’єктів і масивів. У двох словах, JSON дозволяє надавати дані просто. Наприклад, об’єкти полягають у фігурні дужки ({}), масиви в квадратні ([]). Фрагмент JavaScript-коду може без праці прийняти закодовані в JSON дані без виконання будь-якої спеціальної синтаксичного аналізу або додаткового перетворення даних. В лістингу 2 наведена структура даних, представлена ​​в JSON-форматі.


Лістинг 2. Простий приклад JSON-даних





{
“contacts” : {
“contact” : {
“@attributes” : {
“id” : “1”
},
“name” : “John Doe”,
“phone” : “123-456-7890”,
“address” : {
“street” : “123 JFK Street”,
“city” : “Any Town”,
“state” : “Any State”,
“zipCode” : “12345”
}
}
}
}

Можна помітити, що кожен фрагмент даних, показаний в XML-форматі в лістингу 1, Також присутній у JSON-прикладі в лістингу 2. Однак відмінність полягає в тому, як JSON кодує дані, використовуючи типи даних JavaScript – об’єкти та масиви. Структура даних починається з об’єкта, що містить властивість з ім’ям “contacts”, Яке само по собі є об’єктом. Цей об’єкт має одну властивість з назвою “contact”, Яке теж є об’єктом. Цей об’єкт містить кілька властивостей, що формують деталі контакту. Зверніть увагу на те, що об’єкт “contact” містить інший (вкладений) об’єкт “address”, Який описує деталі адреси. Як і в XML, дані в JSON-форматі описують самі себе, тому їх може легко прочитати як людина, так і машина.


Обробка даних на стороні браузера


Тепер давайте розглянемо, як дані обробляються в коді, що виконується на стороні браузера. Коли сервер передає XML-дані в браузер, ці XML-дані обробляються з використанням Document Object Model (DOM) API. Однак JavaScript-розробники повинні вивчити всі тонкощі XML-обробки і написати багато додаткового коду для синтаксичного розбору XML-даних, перш ніж з ними можна буде що-небудь зробити. З появою JSON код на стороні сервера може спакетірованние і передати дані програми в JSON-форматі у відповідь на запит браузера. Якщо код на стороні сервера передає дані в JSON-форматі в браузер, JavaScript-розробникам не потрібно писати якусь додаткову складну логіку для синтаксичного розбору XML. Крім цього, отримані в JSON-форматі дані будуть готові для обробки в коді на стороні браузера як рідна для JavaScript структура даних. Фрагмент коду, наведений в лістингу 3, Показує, що для обробки даних в JSON-форматі не потрібна додаткова робота.


Лістинг 3. Фрагмент коду для обробки даних в JSON-форматі, отриманих від сервера





var result = httpRequest.responseText;
jsonResponse = eval(“(” + result + “)”);

У фрагменті коду, що виконується на стороні браузера і наведеного в лістингу 3, result – Це рядок в JSON-форматі, отримана від сервера. Все що потрібно – один рядок коду для перетворення цих строкових даних в рідній для JavaScript тип даних шляхом використання виразу eval. Можна помітити, що працювати з JSON-даними на стороні браузера набагато простіше. Використання JSON привносить простоту і сенс в код на стороні браузера.


Вираз eval в лістингу 3 буде виконуватися незалежно від того, що поверне сервер, тому тут має місце ризик порушення системи захисту. Цей ризик обмежений, оскільки політика системи захисту браузера обмежує HTTP-запити в JavaScript тільки тим сервером, з якого код був спочатку завантажений. Але все-таки в деяких ситуаціях було б розсудливо перевірити отримані від сервера дані на відповідність очікуваним (можливо, з використанням регулярних виразів) перед передачею їх у вираз eval.


Перетворення XML-в-JSON


Все більша кількість додатків потребує перетворення XML-даних в JSON. Кілька Web-сервісів, що виконують такі перетворення, вже з’явилися. IBM T.J. Watson Research Center розробив особливий метод, що використовує PHP для виконання перетворення. Цей метод приймає XML-дані на вході і перетворює їх в JSON-формат на виході. Таке PHP-рішення забезпечує декілька переваг:



Перетворення XML-в-JSON вимагає використання двох базових функціональних можливостей PHP:



SimpleXMLElement підтримується в PHP версії 5 і вище. Це об’єкт з властивостями, що містять дані, що зберігаються в XML-документі. Services_JSON – Це пропозиція з відкритим вихідним кодом (що з’явилося в кінці 2005), що реалізовується на PHP. Воно надає функції JSON-кодування (PHP-дані в JSON) та декодування (JSON в PHP-дані). Ця бібліотека PHP-класів з відкритим вихідним кодом в даний час доступна на Web-сайті PEAR.


Використовуючи тільки ці дві базові функціональні можливості PHP, можна перетворити будь-які довільні XML-дані в JSON-формат. Перш за все, потрібно перетворити XML-вміст у відповідний PHP-тип даних, використовуючи SimpleXMLElement. Потім PHP-дані надаються в кодіровщік Services_JSON, Який, у свою чергу, формує остаточний висновок даних в JSON-форматі.


Освоєння PHP-коду


Дана реалізація xml2json складається з трьох частин:



Для простоти в даній статті не наводяться докладні коментарі у вихідному коді. Проте вихідний код в поставляються до статті файлах містить повні коментарі. Звертайтеся до цих вихідних файлів за докладною інформацією про логіку роботи програми.


В лістингу 4 визначаються деякі корисні константи. Перший рядок коду імпортує реалізацію Services_JSON.


Лістинг 4. Визначення констант в xml2json.php





require_once “json/JSON.php”; / / Внутрішній параметр Debug, специфічний для програми.
define (“DEBUG”, false); / / Максимальна глибина рекурсії, яку ми можемо дозволити.
define (“MAX_RECURSION_DEPTH_ALLOWED”, 25); / / Порожній рядок.
define (“EMPTY_STR”, “”); / / Ім’я властивості об’єкта SimpleXMLElement для атрибутів.
define (“SIMPLE_XML_ELEMENT_OBJECT_PROPERTY_FOR_ATTRIBUTES”, “@attributes”); / / Назва об’єкту SimpleXMLElement.
define (“SIMPLE_XML_ELEMENT_PHP_CLASS”, “SimpleXMLElement”);

Фрагмент коду, наведений в лістингу 5, Являє собою вхідні функцію в перетворювач xml2json. Вона приймає в якості вхідного параметра XML-дані та перетворює XML-рядок в об’єкт SimpleXMLElement, Який передається в іншу функцію (рекурсивно) в даному класі. Ця функція перетворює XML-елементи в асоціативний PHP-масив. Даний масив потім передається в якості вхідного параметра в кодіровщік Services_JSON, Який видає дані в JSON-форматі.


Лістинг 5. Використання Services_JSON в xml2json.php





public static function transformXmlStringToJson($xmlStringContents) {
$simpleXmlElementObject = simplexml_load_string($xmlStringContents);

if ($simpleXmlElementObject == null) {
return(EMPTY_STR);
}

$jsonOutput = EMPTY_STR;

/ / Перетворити XML-структуру в PHP-масив.
$array1 = xml2json::convertSimpleXmlElementObjectIntoArray($simpleXmlElementObject);

if (($array1 != null) && (sizeof($array1) > 0)) { / / Створити новий екземпляр Services_JSON
$json = new Services_JSON(); / / Перетворити його в дані в форматі JSON.
$jsonOutput = $json->encode($array1); } / / Кінець if (($ array1! = Null) && (sizeof ($ array1)> 0))

return($jsonOutput); } / / Кінець функції transformXmlStringToJson

Довгий фрагмент коду, наведений в лістингу 6, Використовує методологію рекурсії, розроблену PHP-спільнотою прихильників відкритого коду. Він приймає об’єкт SimpleXMLElement в якості вхідного параметра і рекурсивно проходить по вкладеному XML-дереву. Він зберігає всі виявлені XML-елементи в асоціативному PHP-масиві. Ви можете налаштувати граничну глибину рекурсії, змінивши константу, визначену в лістингу 4.


Лістинг 6. Логіка перетворення в xml2json.php





public static function convertSimpleXmlElementObjectIntoArray($simpleXmlElementObject,
&$recursionDepth=0) { / / Стежити за глибиною рекурсії.

if ($recursionDepth > MAX_RECURSION_DEPTH_ALLOWED) { / / Фатальна помилка. Вийти зараз.
return(null);
}

if ($recursionDepth == 0) {
if (get_class($simpleXmlElementObject) != SIMPLE_XML_ELEMENT_PHP_CLASS) { / / Якщо викликає функція не викликала цю функцію спочатку / / З об’єктом SimpleXMLElement, повернути управління.
return(null);
} else { / / Зберегти оригінальний SimpleXmlElementObject, переданий викликає функцією. / / Він нам знадобиться в самому кінці, коли будемо повертатися звідси назавжди.
$callerProvidedSimpleXmlElementObject = $simpleXmlElementObject;
} } / / Кінець if ($ recursionDepth == 0) {

if (get_class($simpleXmlElementObject) == SIMPLE_XML_ELEMENT_PHP_CLASS) { / / Отримати копію simpleXmlElementObject
$copyOfsimpleXmlElementObject = $simpleXmlElementObject; / / Отримати об’єктні змінні в об’єкт SimpleXmlElement для ітерації.
$simpleXmlElementObject = get_object_vars($simpleXmlElementObject);
}

/ / Має бути масивом об’єктних змінних.
if (is_array($simpleXmlElementObject)) { / / Ініціалізувати отримується масив.
$resultArray = array(); / / Дорівнює чи розмір вхідного масиву 0? Ми досягли нечастого тексту CDATA, якщо є.
if (count($simpleXmlElementObject) <= 0) { / / Повернути одиночний текст CDATA. Це міг би бути навіть / / Порожній елемент, або просто заповнений пробілами.
return (trim(strval($copyOfsimpleXmlElementObject)));
}

/ / Пройдемо по дочірнім елементам.
foreach($simpleXmlElementObject as $key=>$value) { / / Якщо цей блок коду закоментований, XML-атрибути будуть / / Додані в масив result. / / Видаліть коментарі з наступного блоку коду, якщо XML-атрибути НЕ / / Потрібно повертати як частина масиву result.
/*
if((is_string($key)) && ($key == SIMPLE_XML_ELEMENT_OBJECT_PROPERTY_FOR_ATTRIBUTES)) {
continue;
}
*/

/ / Обробити рекурсивно щойно виявлений поточний елемент. / / Збільшити глибину рекурсії на одиницю.
$recursionDepth++;
$resultArray[$key] =
xml2json::convertSimpleXmlElementObjectIntoArray($value, $recursionDepth);

/ / Зменшити глибину рекурсії на одиницю.
$recursionDepth–; } / / Кінець foreach ($ simpleXmlElementObject as $ key => $ value) {

if ($recursionDepth == 0) { / / Це все. Починаємо виходити. / / Встановити ім’я кореневого XML-елементу як кореневої [top-level] ключ / / Асоціативного масиву, який ми збираємося повернути функції, / / Викликала рекурсивну функцію.
$tempArray = $resultArray;
$resultArray = array();
$resultArray[$callerProvidedSimpleXmlElementObject->getName()] = $tempArray;
}

return ($resultArray);
} else { / / Тепер шукаємо або текст XML-атрибута, або / / Текст між XML-тегами.
return (trim(strval($simpleXmlElementObject))); } / / Кінець else } / / Кінець функції convertSimpleXmlElementObjectIntoArray.

В кінці успішного проходження по XML-дереву ця функція перетворює і збереже всі XML-елементи (кореневої елемент і всі дочірні елементи) в асоціативному PHP-масиві. Для складних XML-документів одержуваний PHP-масив буде таким же складним. Після завершення формування цього PHP-масиву кодіровщік Services_JSON може легко перетворити його в дані JSON-формату. Щоб зрозуміти логіку рекурсії, перегляньте документований вихідний файл.


Реалізація тестового драйвера для xml2json


Фрагмент коду, наведений в лістингу 7, Являє собою тестовий драйвер, що застосовує логіку перетворення xml2json.


Лістинг 7. xml2json_test.php





<?php
require_once(“xml2json.php”);

/ / Ім’я файла, з якого читається XML-вміст.
$testXmlFile = “”;

/ / Читати ім’я файлу з командного рядка.
if ($argc <= 1) {
print(“Please provide the XML filename as a command-line argument:
“);
print(” php -f xml2json_test.php test1.xml
“);
return;
} else {
$testXmlFile = $argv[1];
}

/ / Читати XML-вміст з вхідного файлу.
file_exists($testXmlFile) or die(“Could not find file ” . $testXmlFile);
$xmlStringContents = file_get_contents($testXmlFile);

$jsonContents = “”; / / Перетворити на формат JSON. / / Xml2json просто приймає об’єкт String, що містить XML-вміст, / / В якості вхідного параметра.
$jsonContents = xml2json::transformXmlStringToJson($xmlStringContents);

echo(“JSON formatted output generated by xml2json:

“);
echo($jsonContents);
?>


Ви можете виконати програму з командного рядка з ім’ям XML-файла, зазначеним як аргумент командного рядка:






php -f xml2json_test.php test2.xml

При виконанні з командного рядка програма читає XML-вміст з файлу в строкову змінну. Потім вона викликає статичну функцію в класі xml2json для отримання результату в JSON-форматі. Крім виконання програми з командного рядка ви можете змінити логіку в цьому вихідному файлі для надання перетворювача xml2json у вигляді викликається Web-сервісу, що використовує протоколи доступу Simple Object Access Protocol (SOAP) або Representational State Transfer (REST). При необхідності можна легко зробити це в PHP з мінімальними витратами.


В лістингу 8 наведений один з чотирьох тестових XML-файлів, що поставляються до статті для тестування реалізації xml2json. Ступінь складності цих файлів різна. Ви можете передати один з цих файлів у вигляді аргументу командного рядка в тестовий драйвер xml2json_test.php.


Лістинг 8. Тестування реалізації xml2json з test2.xml





<?xml version=”1.0″ encoding=”UTF-8″?>
<books>
<book id=”1″>
<title>Code Generation in Action</title>
<author><first>Jack</first><last>Herrington</last></author>
<publisher>Manning</publisher>
</book>

<book id=”2″>
<title>PHP Hacks</title>
<author><first>Jack</first><last>Herrington</last></author>
<publisher>O”Reilly</publisher>
</book>

<book id=”3″>
<title>Podcasting Hacks</title>
<author><first>Jack</first><last>Herrington</last></author>
<publisher>O”Reilly</publisher>
</book>
</books>

Фрагмент коду, наведений в лістингу 9, Являє собою результат у форматі JSON при використанні файлу test2.xml як аргумент командного рядка для тестового драйвера xml2json_test.php.


Лістинг 9. Результат в JSON-форматі для test2.xml





{
“books” : {
“book” : [ {
“@attributes” : {
“id” : “1”
},
“title” : “Code Generation in Action”,
“author” : {
“first” : “Jack”, “last” : “Herrington”
},
“publisher” : “Manning”
}, {
“@attributes” : {
“id” : “2”
},
“title” : “PHP Hacks”, “author” : {
“first” : “Jack”, “last” : “Herrington”
},
“publisher” : “O”Reilly”
}, {
“@attributes” : {
“id” : “3”
},
“title” : “Podcasting Hacks”, “author” : {
“first” : “Jack”, “last” : “Herrington”
},
“publisher” : “O”Reilly”
}
]}
}

Зверніть увагу на те, що XML-атрибут id для елемента <book> зберігається в JSON-даних як властивість об’єкта “@attributes”, А елемент <book> зберігається як масив об’єктів. Отримані дані в JSON-форматі готові для прийому в JavaScript-коді з використанням вираження eval.


Висновок


JSON тільки починає набувати вагу серед Web-розробників. Його переваги, видимі головним чином JavaScript-розробниками, складаються в елегантності і простоті. У певних ситуаціях JSON може бути гідною альтернативою XML. В даній статті аргументується необхідність перетворення XML-в-JSON на сервері проміжного рівня. Потім увага приділяється логічному обгрунтуванню використання корпоративних даних в XML-форматі у вигляді даних в форматі JSON, для того щоб програми на стороні браузера могли легко використовувати їх. Надається PHP-код, який може виконувати перетворення XML-в-JSON.


Ви можете використовувати вихідний код, що поставляється з даною статтею, в різних цілях – як автономну програму, як бібліотеку класів для існуючої програми, що виконується на стороні сервера, або як функцію Web-сервісу SOAP / REST для участі у корпоративній сервіс-орієнтованої архітектури (Service-Oriented Architecture – SOA).

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*