Обмен данными в формате XML

С одной стороны, обмен данными в текстовом формате является простым, но с другой стороны, это влечет за собой жесткую зависимость между клиентским и серверным кодами. Если разработкой проекта занимаются разные люди, а обычно так и бывает, то такой способ обмена данными не является эффективным. При обмене данными в формате XML разработчики могут заранее договориться о формате XML-документа, и в дальнейшем каждый будет выполнять свою часть работы, опираясь на согласованный формат.

Прежде чем рассматривать обработку данных в формате XML с помощью JavaScript, напомним некоторые правила создания простейших XML-документов. XML-документ состоит из двух разделов — пролога и тела документа. В прологе указывается объявление XML.

<?xml version="1.0" encoding="utf-8" ?>

В параметре encoding указывается кодировка XML-документа. Если она не указана, то по умолчанию используется кодировка UTF-8.

Тело XML-документа должно находиться внутри корневого тега. Обычно имя тега совпадает с именем документа.

<?xml version="1.0" encoding="utf-8" ?>
<ajax>
<!-- Тело XML-документа -->
</ajax>

При указании имени тега необходимо помнить, что регистр символов имеет значение. Имена должны начинаться с буквы и содержать буквы, цифры или символ подчеркивания. В отличие от HTML-тегов, в XML пространство имен выбирает сам разработчик.

Следует учитывать, что каждому открывающему тегу должен соответствовать закрывающий тег.

<item></item>

Кроме того, должна соблюдаться вложенность тегов. Если элемент является пустым, то он может быть записан следующим образом.

<item/>

XML-теги могут иметь параметры. Параметр указывается в формате:

<Имя параметра>="<Значение>"

Значение параметра обязательно должно быть указано в кавычках, а сам параметр указывается в открывающем теге.

<item id="5">Данные</item>

Все специальные символы внутри тегов и в значениях параметров должны быть заменены на мнемонические имена.

Внутри тегов можно использовать комментарии, которые имеют синтаксис, похожий на синтаксис HTML-комментариев.

<!-- Это комментарий -->

Следование этим несложным правилам избавит от множества проблем при работе с XML-документами.

Теперь рассмотрим обмен данными в формате XML на примере. Создадим документ с формой (листинг 10.7), который будет обмениваться данными с файлом ajax.php (листинг 10.8), расположенным на сервере.

Листинг 10.7. Обмен данными в формате XML

<!doctype html>
<html>
<head>
<title>Обмен данными в формате XML</title>
<meta charset="utf-8">
<script>
function f_GET() {
   // Отправка запроса методом GET
   var link;
   var url;
   var txt1 = document.getElementById("text1").value;
   var txt2 = document.getElementById("text2").value;
   if (txt1 == "" || txt2 == "") {
      window.alert("Не заполнено поле");
      return false;
   }
   if (window.XMLHttpRequest) {
      link = new XMLHttpRequest();
   }
   else {
      if (window.ActiveXObject) {
         var XMLHTTP = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0",
                       "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
         for (var i=0; i<4; i++) {
            try { // Обработка исключений
               link = new ActiveXObject(XMLHTTP[i]);
               break; // Если объект создан, то выход из цикла
            }
            catch (e) {}
         }
      }
   }
   if (!link) {
      window.alert("Ваш веб-браузер не поддерживает технологию Ajax");
      return false;
   }
   url = "/ajax.php?text1=" + encodeURIComponent(txt1);
   url += "&text2=" + encodeURIComponent(txt2);
   // Подготовка асинхронного запроса методом GET
   link.open('GET', url, true);
   link.onreadystatechange = function() {
      f_razborRequest(link);
   };
   link.send(null); // Отправляем запрос
   document.getElementById("otvet").innerHTML = "Загрузка...";
}

function f_razborRequest(link) {
   // Обрабатываем асинхронный запрос
   if (link.readyState == 4) {
      if (link.status == 200) { // Запрос успешно обработан
         var xml = link.responseXML;
         var otvet = xml.getElementsByTagName("otvet");
         var text1 = otvet.item(0)
                          .getElementsByTagName("text1").item(0);
         var text2 = otvet.item(0)
                          .getElementsByTagName("text2").item(0);
         var msg = text1.firstChild.data + "<br>" +
                   text2.firstChild.data;
         document.getElementById("text1").value = "";
         document.getElementById("text2").value = "";
         document.getElementById("otvet").innerHTML = msg;
      }
      else {
         document.getElementById("otvet").innerHTML = "Ошибка";
      }
   }
}
</script>
</head>
<body>
<input type="text" id="text1"><br>
<input type="text" id="text2"><br>
<input type="button" value="Отправить методом GET" onclick="f_GET();">
<br>
<div id="otvet"></div>
</body>
</html>

Листинг 10.8. Исходный код файла ajax.php

<?php
header('Content-Type: text/xml; charset=utf-8');
echo '<?xml version="1.0" encoding="utf-8" ?>', "\n";
echo "<ajax>\n";
echo "   <otvet>\n";
if (isset($_GET['text1']) && isset($_GET['text2'])) {
   echo "      <text1>";
   echo 'Поле 1 – ';
   echo htmlspecialchars($_GET['text1'], ENT_COMPAT, 'UTF-8');
   echo "</text1>\n";
   echo "      <text2>";
   echo 'Поле 2 – ';
   echo htmlspecialchars($_GET['text2'], ENT_COMPAT, 'UTF-8');
   echo "</text2>\n";
}
else {
   echo 'Данные не получены';
}
echo "   </otvet>\n";
echo "</ajax>\n";
?>

После заполнения двух полей и щелчка на кнопке Отправить методом GET внутри функции f_GET() получаем значение текстовых полей и сохраняем их в переменных txt1 и txt2. Далее проверяем, заполнены ли поля ввода, и, если они не заполнены, выводим сообщение и завершаем выполнение функции. На следующем этапе пытаемся создать объект XMLHttpRequest. Если объект создать не удалось, выводим сообщение и завершаем выполнение функции.

Затем формируем строку запроса, которую будем передавать методом GET. Все данные, введенные пользователем в поля ввода, перекодируем с помощью метода encodeURIComponent(). Сформированную строку сохраняем в переменной url.

url = "/ajax.php?text1=" + encodeURIComponent(txt1);
url += "&text2=" + encodeURIComponent(txt2);

Далее с помощью метода open() подготавливаем объект к отправке асинхронного запроса методом GET.

link.open('GET', url, true);

В свойстве onreadystatechange указываем функцию-обработчик и с помощью метода send() отправляем запрос на сервер.

link.send(null);

Теперь рассмотрим, что происходит при получении запроса сервером. Получив запрос, сервер создаст две переменные окружения: $_GET['text1'] и $_GET['text2']. Для корректного отображения отправленной информации указываем MIME-тип и кодировку с помощью функции header().

header('Content-Type: text/xml; charset=utf-8');

Далее формируем XML-документ, который отправим в ответ на запрос. В результате веб-браузер получит XML-документ, приведенный в листинге 10.9.

Листинг 10.9. XML-документ, формируемый в качестве ответа сервера

<?xml version="1.0" encoding="utf-8" ?>
<ajax>
   <otvet>
      <text1>Поле 1 – Строка 1</text1>
      <text2>Поле 2 – Строка 2</text2>
   </otvet>
</ajax>

После получения ответа XML-документ будет доступен через свойство responseXML внутри функции f_razborRequest().

var xml = link.responseXML;

С помощью метода getElementsByTagName() получаем список всех элементов otvet и сохраняем его в переменной otvet.

var otvet = xml.getElementsByTagName("otvet");

Получить доступ к отдельному элементу списка позволяет метод item(). Нумерация элементов начинается с нуля. Общее количество элементов можно получить с помощью свойства length.

var count = otvet.length;

Доступ к элементам text1 и text2 внутри элемента otvet также происходит с помощью метода getElementsByTagName().

var text1 = otvet.item(0).getElementsByTagName("text1").item(0);
var text2 = otvet.item(0).getElementsByTagName("text2").item(0);

Получить доступ к элементу можно по индексу, указанному в квадратных скобках.

var text1 = otvet[0].getElementsByTagName("text1")[0];
var text2 = otvet[0].getElementsByTagName("text2")[0];

Чтобы получить данные внутри элементов text1 и text2, следует воспользоваться свойством firstChild. Свойство firstChild содержит информацию о длине строки (свойство length) и текстовых данных элемента (свойство data). Именно свойство data позволяет нам получить переданные данные и сформировать строку для вывода результата.

var msg = text1.firstChild.data + "<br>" + text2.firstChild.data;
document.getElementById("otvet").innerHTML = msg;
Предыдущая статья Все статьи Следующая статья