2. easyAPI. Удаленная загрузка XML.
И вот, наконец, долгожданная, вторая статья из раздела easyAPI.
Сегодня мы узнаем, как загрузить XML-данные с удаленного домена. Подобная задача возникает, например, когда владелец сайта на бесплатном (а значит – без серверного кода) хостинге хочет вставить в страницу погодный XML-информер. Именно на этом примере мы и рассмотрим сегодня удаленную загрузку XML-файлов.
Итак, для фоновой загрузки данных мы привыкли использовать так называемый AJAX, то есть объект XMLHttpRequest, про эту технологию я уже не раз писал в статьях блога. Однако, эта технология в данном случае никуда не годится. Почему? А потому что объект XMLHttpRequest не позволяет делать запросы к доменам, иным, чем тот, в котором работает скрипт, создающий этот объект.
И здесь к нам на помощь приходит технология, получившая название JSONP, что значит JavaScript Object Notation with Padding. Про сам JSON можео почитать вот здесь JSON, а JSONP представляет собой объект в нотации JSON обернутый в вызов функции, что-то вроде этого:
onSuccess('JSON-object')
А теперь объясню, зачем это нужно. Хоть XMLHttpRequest и не позволяет делать запросы к удаленным доменам, однако все браузеры позволяют нам загружать JavaScript’ы с любых доменов, то есть страница, загруженная с домена localdomain.ru, позволяет выполнить в ее рамках следующую инструкцию:
<script type='text/javascript' src='http://remotedomain.ru'> </script>
А теперь смотрите, что происходит. Наша страница загружает скрипт с удаленного домена, а скрипт этот возвращает нам JSONP-конструкцию, которая после загрузки скрипта тут же и выполнится, а значит, вызовет некую предопределенную заранее функцию onSuccess, которая получит в качестве аргумента тот самый XML-файл. И теперь мы можем делать с ним все, что захотим!
Осталось только одно – завладеть таким remotedomain.ru, который вернет нам то, что нам нужно. Скажу, что домен этот – http://easyapi.ru. Да-да, именно на этом, предусмотрительно приобретенном не так давно домене, и будут жить все наши полезные, жизненно необходимые почти каждому веб-разработчику, функции. 🙂 Скромненько и со вкусом…
Итак, в рамках домена easyapi.ru я уже создал ответную часть для удаленной загрузки XML-документов. Живет она вот здесь: http://easyapi.ru/xml/get.php и принимает на входе два GET-параметра: url и callback. Первый из них – адрес, с которого будет загружаться XML-файл, а второй – имя JavaScript-функции, которая будет вызвана после загрузки, и которая должна будет обработать полученный XML-документ.
Не откладывая дело в долгий ящик, приведу ниже содержимое страницы, которая, используя наш сервис easyAPI, загружает данные об XML-погоде в городе Москва и при помощи XSLT-шаблона преобразует эти данные в красивый информер, который вы, кстати, изучив основы XSLT-преобразований, сможете оформить по своему усмотрению.
Вот исходный код страницы:
<html> <head> <script type="text/javascript"> function getXMLFromString(s) { if(window.ActiveXObject) { var xml; xml=new ActiveXObject("Microsoft.XMLDOM"); xml.async=false; xml.loadXML(s); return xml; } else if(window.DOMParser) { var parser = new DOMParser(); return parser.parseFromString(s,'text/xml'); } else { alert("Загрузка XML не поддерживается браузером"); return null; } } function getXMLDocument(url) { var xml; if(window.XMLHttpRequest) { xml=new window.XMLHttpRequest(); xml.open("GET", url, false); xml.send(""); return xml.responseXML; } else if(window.ActiveXObject) { xml=new ActiveXObject("Microsoft.XMLDOM"); xml.async=false; xml.load(url); return xml; } else { alert("XML loading not supported"); return null; } } function transformXslt(source,style) { if(window.ActiveXObject) { return source.transformNode(style); } else if(window.XSLTProcessor) { var xsltProcessor=new XSLTProcessor(); xsltProcessor.importStylesheet(style); var resultDocument = xsltProcessor.transformToDocument(source); var xmls = new XMLSerializer(); return xmls.serializeToString(resultDocument); } else { alert("Преобразование XML не поддерживается браузером"); return null; } } </script> </head> <body> <div id="res"></div> <script type="text/javascript"> function onSuccess(res) { var xslt = getXMLDocument("http://easy-4-web.ru/samples/easyxml/gis.xsl"); var xml = getXMLFromString(res.result); var res = transformXslt(xml, xslt); document.getElementById("res").innerHTML=res; } </script> <script src="http://easyapi.ru/xml/get.php?url=http://informer.gismeteo.ru/xml/27612_1.xml&callback=onSuccess" type="text/javascript"></script> </body> </html>
В первой части страницы мы видим три функции, все они – кроссбарузерные:
- getXMLFromString(s) – преобразует валидную строку s в XML-документ
- getXMLDocument(url) – загружает XML-документ с адреса url
- transformXslt(source,style) – преобразует XML-документ source при помощи XSLT-шаблона style
В нижней части исходного кода мы видим функцию onSuccess – ока как раз и выполнится после загрузки xml-документа с удаленного домена. Она отрисует загруженный и полученный в переменной res.result XML-Документ при помощи XSLT-файла, хранящегося по адресу http://easy-4-web.ru/samples/easyxml/gis.xsl
И в самой-самой нижней части исходного кода мы видим вот такую конструкцию:
<script src="http://easyapi.ru/xml/get.php?url=http://informer.gismeteo.ru/xml/27612_1.xml&callback=onSuccess" type="text/javascript"></script>
Вот эта часть и представляет собой загружалку XML-документов с удаленных доменов. Как видим в атрибуте src тега SCRIPT мы указали, кто будет заниматься загрузкой (http://easyapi.ru/xml/get.php), что он будет загружать (url=http://informer.gismeteo.ru/xml/27612_1.xml) и какая функция займется обработкой документа (callback=onSuccess)
Здесь вы можете скачать исходные коды приведенного примера. А вот здесь – посмотреть, как это работает.
В тему:
А файл get.php можете выложить?
Werot, March 18, 2010 2:13 amНет, файл get.php, как и прочие исходные серверные файлы сервиса easyAPI я не выкладываю. Но если вкратце, то это просто загрузка файла, проверка mime-типа загружаемого файла, и в случае, если тип – XML, отдача файла пользователю.
admin, March 18, 2010 9:36 amВ чем причина, http://easyapi.ru/xml/get.php не обрабатывает такой адрес http://www.morow.com/playlist.xml, вот пример:
function onSuccess()
{
alert(“Функция вызвана”)
}
Исправил.
Обработчик ожидал, что ему придет Content-Type = text/xml, а от данного сайта приходил application/xml.
admin, October 18, 2010 8:59 amСпасибо, все получилось, правда, возникла проблема с кэшированием скрипта браузером, но это детали. Еще раз спасибо за эту статью и сервис 🙂
Anton, October 18, 2010 9:43 pmВот тоже хотел сделать себе на сайт. Модуль прогноза погоды.
Сайт стоит на CMS DLE 9.5
Шаблон написал сам, Javascript неделю назад начал читать и практиковать, раньше только на Java, C++, VB программировал.
Вроде как ваш код мне понятен, но я не могу понять почему у меня он не работает. Не из-за того что xslt обработчик находиться у вас на сервере? Хотя, если писать в функцию onSucces alert(“готово”), оно не выполняется. Может быть это из-за моего корявого JavaScript-а который был написан ранее, и я подключал библиотеку jQuery может это из-за него и как это можно вылечить?
“Не из-за того что xslt обработчик находиться у вас на сервере?” – это я к тому что не должен ли он у меня на сервере лежать. Также я пробовал кучу способов с php. PHP в шаблоне игнорируется, подумал может в движке написать в файле index.php, написал, создал для него клише({moduleWeather}) сделал так чтобы он заменял клише на обработанную переменную типа string, обновил сайт, и тут ничего не происходило. Кажется я в отчаянии) а отказываться от этого я не собираюсь, хочу попробовать и опыт получить
Акуна, January 16, 2012 4:14 pmРазместите и скрипт и XSLT на своем сервере.
Вячеслав Гринин, January 16, 2012 10:35 pmВалюта Центробанка не парсится из-за русских букв http://easyapi.ru/xml/get.php?url=http://www.cbr.ru/scripts/XML_daily.asp&callback=onSuccess
Евгений, February 26, 2014 8:54 pm