Формат XML представляет популярный формат хранения и передачи данных. Рассмотрим, как загружать xml-документ на веб-странице с помощью ajax-запроса.
В качестве сервера, как и в прошлой статье, будем использовать Node.js как наиболее простой вариант, но естественно при желании можно использовать любую другую технологию серверного уровня или какой-нибудь веб-сервер.
Итак, определим для проекта на жестком диске папку, в которой создадим три файла:
index.html: главная страница приложения
users.xml: xml-файл с данными
app.js: файл приложения сервера, который будет использовать Node.js
Файл users.xml будет представлять загружаемые данные и пусть будет иметь следующее содержимое:
<?xml version="1.0" encoding="UTF-8" ?> <users> <user name="Tom" age="39"> <contacts> <email>tom@smail.com</email> <phone>+1234567890</phone> </contacts> </user> <user name="Bob" age="43"> <contacts> <email>bob@tmail.com</email> <phone>+1334567181</phone> </contacts> </user> <user name="Sam" age="28"> <contacts> <email>sam@xmail.com</email> <phone>+1434567782</phone> </contacts> </user> </users>
Здесь элемент users представляет набор пользователей, каждый из которых представлен элементом user. Для каждого такого элемента определены два атрибута: name (имя пользователя) и age (возраст пользователя). И также элемент user имеет вложенный элемент contacts, который представляет контактные данные пользователя в виде вложенных элементов phone и email.
Файл app.js будет представлять код сервера Node.js. Определим в нем следующий код:
const http = require("http"); const fs = require("fs"); http.createServer((request, response)=>{ // если запрошены данные xml if(request.url == "/data"){ fs.readFile("users.xml", (_, data) => response.end(data)); } else{ fs.readFile("index.html", (_, data) => response.end(data)); } }).listen(3000, ()=>console.log("Сервер запущен по адресу http://localhost:3000"));
Вкратце пробежимся по коду. Сначала подключаются пакеты с функциональностью, которую мы собираемся использовать:
const http = require("http"); // для обработки входящих запросов const fs = require("fs"); // для чтения файлов с жесткого диска
Для создания сервера применяется функция http.createServer(). В эту функцию передается функция-обработчик, которая вызывается каждый раз, когда к серверу приходит запрос.
Эта функция имеет два параметра: request
(содержит данные запроса) и response
(управляет отправкой ответа).
В функции-обработчике с помощью свойства request.url
мы можем получить путь к ресурсу, к которому пришел запрос.
Так, в данном случае, если пришел запрос по пути "/data", то оправляем users.xml:
if(request.url == "/data"){ fs.readFile("users.xml", (_, data) => response.end(data)); }
Для считывания файла применяется функция fs.readFile. Первый параметр функции - адрес файла (в данном случае предполагается, что файл находится в одной папке с файлом сервера server.js). Второй параметр - функция, которая вызывается после считывания файла и получет его содержимое через свой второй параметр data.
Для всех остальных запросов отправляем в ответ файл index.html:
else{ fs.readFile("index.html", (_, data) => response.end(data)); }
В конце с помощью функции listen() запускаем веб-сервер на 3000 порту. То есть сервер будет запускаться по адресу http://localhost:3000/
Для получения файла "users.xml" с сервера определим в файле index.html следующий код:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>METANIT.COM</title> </head> <body> <script> const xhr = new XMLHttpRequest(); xhr.onload = () => { if (xhr.status == 200) { const xml = xhr.responseXML; console.log(xml); } }; xhr.open("GET", "/data"); // GET-запрос к /data xhr.responseType = "document"; // устанавливаем тип ответа xhr.setRequestHeader("Accept", "text/xml"); // принимаем только xml xhr.send(); // выполняем запрос </script> </body> </html>
Для получения данных отправляем запрос по адресу "/data". Чтобы полученные данные автоматически были распарсены в документ XML,
свойству responseType
присваиваем значение "document".
xhr.responseType = "document";
Кроме того, следует установить для заголовка Accept значение "text/xml" или "application/xml", чтобы принимать данные только в формате XML:
xhr.setRequestHeader("Accept", "text/xml");
В обработчике события onload документ XML доступен через свойство responseXML
в виде объекта типа Document, который в
данном случае просто выводится на консоль:
xhr.onload = () => { if (xhr.status == 200) { const xml = xhr.responseXML; console.log(xml); } };
После определения всех файлов в консоли перейдем к папке сервера с помощью команды cd и запустим сервер с помощью команды node server.js
C:\app>node server.js Сервер запущен по адресу http://localhost:3000
После запуска сервера мы можем перейти в браузере по адресу http://localhost:3000, нам отобразится страница, в javascript-коде произойдет обращение по адресу "/data". Сервер в ответ отправит содержимое файла users.xml, и консоль барузера отобразит это содержимое:
Теперь усложим задачу - допустим, нам надо вывести данные о пользователях из xml в таблицу на веб-страницу. Для этого изменим код index.html следующим образом:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>METANIT.COM</title> </head> <body> <div id="content"></div> <script> const contentDiv = document.getElementById("content"); const xhr = new XMLHttpRequest(); xhr.onload = () => { if (xhr.status == 200) { const xmlDoc = xhr.responseXML; const table = createTable(); // выбираем все элементы user const users = xmlDoc.getElementsByTagName("user"); for (let i = 0; i < users.length; i++) { const user = users[i]; const userName = user.getAttribute("name"); const userAge = user.getAttribute("age"); const contact = user.querySelector("contacts email").textContent; const row = createRow(userName, userAge, contact); table.appendChild(row); } contentDiv.appendChild(table); } }; xhr.open("GET", "/data"); xhr.responseType = "document"; xhr.setRequestHeader("Accept", "text/xml"); xhr.send(); // создаем таблицу function createTable() { const table = document.createElement("table"); const headerRow = document.createElement("tr"); const nameColumnHeader = document.createElement("th"); const ageColumnHeader = document.createElement("th"); const contactColumnHeader = document.createElement("th"); nameColumnHeader.appendChild(document.createTextNode("Name")); ageColumnHeader.appendChild(document.createTextNode("Age")); contactColumnHeader.appendChild(document.createTextNode("Contacts")); headerRow.appendChild(nameColumnHeader); headerRow.appendChild(ageColumnHeader); headerRow.appendChild(contactColumnHeader); table.appendChild(headerRow); return table; } // создаем одну строку для таблицы function createRow(userName, userAge, userContact) { const row = document.createElement("tr"); const nameColumn = document.createElement("td"); const ageColumn = document.createElement("td"); const contactColumn = document.createElement("td"); nameColumn.appendChild(document.createTextNode(userName)); ageColumn.appendChild(document.createTextNode(userAge)); contactColumn.appendChild(document.createTextNode(userContact)); row.appendChild(nameColumn); row.appendChild(ageColumn); row.appendChild(contactColumn); return row; } </script> </body> </html>
В данном случае загружаем таблицу на страницу в элемент с идентификатором "content", который получаем в коде JavaScript в элемент contentDiv
const contentDiv = document.getElementById("content");
Для создания таблицы определены две вспомогательные функции. Функция createTable создает элемент table с одной строкой - заголовками столбцов. Функция createRow принимает через параметры имя, возраст и контакты пользователя и для них создает строку.
В основной части кода выполняем запрос на сервер. Поскольку ответ сервера будет представлять документ xml в виде типа Document
, то с помощью стандартных
методов типа getElementsByTagName
или querySelector
мы можем найти нужные в документе элементы. И в начале выбираем все элементы user:
const xmlDoc = xhr.responseXML; const table = createTable(); // выбираем все элементы user const users = xmlDoc.getElementsByTagName("user");
Далее перебираем все элементы user и выбираем у каждого атрибуты name и age, а также вложенный элемент email:
for (let i = 0; i < users.length; i++) { const user = users[i]; const userName = user.getAttribute("name"); const userAge = user.getAttribute("age"); const contact = user.querySelector("contacts email").textContent; const row = createRow(userName, userAge, contact); table.appendChild(row); }
Для каждого элемента user создается строка, которая затем добавляется в таблицу.
Таким образом, при обращении к странице index.html будет загружен xml-документ, по которому будет создана таблица: