Что такое AJAX, думаю, все уже знают и имеют небольшое представление о том, как он работает. Но всё же много людей до сих пор представления не имеют о том, каким боком собственно XML, так как большинство ресурсов расписывают работу только со свойством responseText, не говоря уже о сторонних библиотеках (prototype, sAjax и прочее).
Почему XML?
Некоторые люди говорят, что AJAX прозвали именно AJAX’ом потому что это «прикольно». Цитата: «У американцев есть манечка, придумывать красивые аббривиатуры, они ведь не назовут технологию AJAT(response text), AJAX звучит на порядок лучше». Но это не так. Технология AJAX действительно придумана и разработана для работы с XML данными.
XML (EXtensible Markup Language) - разработан для хранения и передачи данных. Очень простой в изучении и использовании язык разметки. В настоящее время нашел широкое применение в прикладном программировании, особенно после выпуска Microsoft Visual Studio 8 и 9 (xml manifest, config, и т.д.). Есть несколько ресурсов, которые вообще отказались от HTML, CSS и полностью перешли на XML. Сразу возникает вопрос? А как же визуальная разметка? Здесь, на помощь приходит XSLT – EXtensible Stylesheet Language Transformations. Но в нашем случае вещь бесполезная, так как мы будем внедрять XML данные в уже оформленный HTML документ.
Надеюсь все уже догадываются о том, что суть AJAX в использовании нестандартного объекта – XMLHttpRequest, для общения со сторонними ресурсами. Итак, начнем с универсальной функции для создания xmlHttp объекта в различных браузерах. Выглядит она примерно так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
function getXmlHttp(){ var xmlhttp; try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { xmlhttp = false; } } if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { xmlhttp = new XMLHttpRequest(); } return xmlhttp; }
Сам объект XMLHttpRequest понимают только Firefox, Opera 8+ и Safari, так что для вредного ослика мы будем использовать его ActiveX объект, который имеет те же методы что и XMLHttpRequest. Кстати, компания Microsoft – первый, кто представил такой объект, а Firefox, Opera, Safari и другие браузеры последовали.
Краткое введение в AJAX
В рамках данной статьи мы будем использовать запрос с методом GET. Делается это в две строки, не считая инициализацию объекта xmlHttp:
var xmlHttp; xmlHttp = getXmlHttp(); xmlHttp.open('GET', 'http://www.example.ru/data.xml', true); xmlHttp.send(null)
Где http://www.example.ru/data.xml сторонний ресурс содержащий XML данные. НО, прежде чем отсылать куда-то запрос, советую сразу установить «слушатель» для данного объекта. «Слушатель» устанавливается таким образом:
xmlHttp.onreadystatechange = nameOfFunction;
Где nameOfFunction – имя функции которую следует вызвать при смены состояния объекта xmlHttp. Список всевозможных состояний:
0 – не инициализирован
1 – загрузка
2 – загрузка завершена
3 – обработка
4 – готово
Следовательно, откликаться мы будем только по состоянию 4 – готово.
Следовательно, откликаться мы будем только по состоянию 4 – готово.
function nameOfFunction() { if (xmlHttp.readyState == 4) { // что нибудь делаем }}
То же самое можно написать и в одном блоке:
xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4) { // что нибудь делаем }}
Далее следует проверить полученный код статуса HTTP сервера, но это не в рамках нашего сюжета. Сконцентрируемся на XML.
К полученным данным вы можете получить доступ двумя способами:
xmlHttp.responseText
xmlHttp.responseXML
Нас, в данном случае, интересует только второй способ. Делается это вот таким образом:
var xmlDoc = xmlHttp.responseXML.documentElement;
xmlHttp.responseXML.documentElement – это объект содержащий весь, полученный XML документ. Теперь нам следует его обработать, то есть «выдернуть» из негу нужную нам информацию, в нужном нам порядке. Для этого мы будем использовать методы DOM (Data Object Model), а именно getElementsByTagName(). В цикле по главному (не путать с корневым) элементу XML документа мы можем пройти через все интересующие нас записи. Для примера рассмотрим простой XML документ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
<?xml version="1.0" encoding="windows-1251"?><newsarchive> <entry> <id>73</id> <title>заголовок первой статьи</title> <content>содержание первой статьи</content> <date>2008-03-04 05:03:24</date> </entry> <entry> <id>74</id> <title>заголовок второй статьи</title> <content>содержание второй статьи</content> <date>2008-03-10 15:21:39</date> </entry></newsarchive>
Пускай это будет простой новостной архив из 2х записей. Таким образом, главным нашим элементом будет являться элемент entry, так как он и содержит несущую смысл информацию. На самом деле всё зависит от структуры документа, его элементной вложенности. XML позволяет писать какие угодно тэги, какой угодно вложенности, так что структура остаётся на усмотрение самого автора.
Вернемся к нашему XML документу. Мы будем просматривать каждый элемент entry в цикле, а данные элемента (id, title, content, date) будем добавлять (appendChild) в определенном порядке к какому-либо объекту, например data_div (document.getElementById). Примерно так:
1 2 3 4 5 6 7 8 9
var xmlDoc = xmlHttp.responseXML.documentElement; var dataArray = xmlDoc.getElementsByTagName("entry"); obj = document.getElementById("data_div"); for (var i = 0; i < dataArray.length; i++){ var new_el = document.createElement("div"); new_el.innerHTML = '<b>' + xmlDoc.getElementsByTagName("title")[i].childNodes[0].nodeValue + '</b><br>' + xmlDoc.getElementsByTagName("date")[i].childNodes[0].nodeValue + '<br>' + xmlDoc.getElementsByTagName("content")[i].childNodes[0].nodeValue + '<br><br>'; obj.appendChild(new_el); }
Итак, какой-нибудь HTML документ, который будет обращаться к XML файлу за данными. В нём div куда будут добавляться данные, и ссылка для посылки запроса:
<div id="data_div"> <a href="#" onclick="getSomeData(); return false;">получить данные</a><br> </div>
Javascript функция getSomeData():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
function getSomeData() { var xmlHttp; xmlHttp = getXmlHttp(); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4) { var xmlDoc = xmlHttp.responseXML.documentElement; var dataArray = xmlDoc.getElementsByTagName("entry"); obj = document.getElementById("data_div"); for (var i = 0; i < dataArray.length; i++) { var new_el = document.createElement("div"); new_el.innerHTML = '<b>' + xmlDoc.getElementsByTagName("title")[i].childNodes[0].nodeValue + '</b><br>' + xmlDoc.getElementsByTagName("date")[i].childNodes[0].nodeValue + '<br>' + xmlDoc.getElementsByTagName("content")[i].childNodes[0].nodeValue + '<br><br>'; obj.appendChild(new_el); } } } xmlHttp.open('GET', 'data.xml', true); xmlHttp.send(null); }
XML документ data.xml (повторно):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
<?xml version="1.0" encoding="windows-1251"?><newsarchive> <entry> <id>73</id> <title>заголовок первой статьи</title> <content>содержание первой статьи</content> <date>2008-03-04 05:03:24</date> </entry> <entry> <id>74</id> <title>заголовок второй статьи</title> <content>содержание второй статьи</content> <date>2008-03-10 15:21:39</date> </entry></newsarchive>
AJAX, чаще всего, работает с динамическими данными. Возможно ли динамически подавать XML документ? Конечно, любой серверный язык может выдать документ в виде XML, а в функцию xmlHttp.open() спокойно можно подставить data.php вместо data.xml. Главное помнить об одном – некоторые браузеры (в частности Internet Explorer) воспринимают XML файл только тогда, когда он действительно XML файл. То есть в вашем серверном скрипте нужно обязательно выслать заголовок браузеру, о том что вывод – XML. Конкретнее на примере PHP:
header('Content-type: application/xml');
Вы так же можете воспользоваться javascript функцией:
xmlHttp.overrideMimeType('application/xml');