Привет! Сегодня мы познакомимся с еще одним форматом данных, который называется XML. Если коротко: XML это текстовый формат для описания данных. Данные в нем размечаются тегами в угловых скобках, теги вкладываются друг в друга и образуют дерево, а у каждого тега могут быть атрибуты. Сам по себе XML ничего не делает и никак данные не отображает: он их только описывает, а читает и обрабатывает уже программа, например на Java. Это очень важная тема. В работе над настоящими Java-приложениями ты почти наверняка столкнешься с задачами, связанными с XML. Этот формат используется в Java-разработке практически повсеместно (зачем именно, узнаем ниже), поэтому рекомендую тебе читать лекцию не «по диагонали», а разобраться во всем досконально и заодно изучить дополнительные материалы по XML :) Это время точно не будет потрачено впустую. Итак, начнем с простого: «что» и «зачем»!

Кратко

  • XML это язык разметки для хранения и передачи данных, а не язык программирования: сам он ничего не выполняет.
  • Все держится на тегах: каждому открывающему нужен закрывающий, теги вкладываются друг в друга и образуют дерево с одним корневым тегом.
  • У тега бывают атрибуты, они уточняют данные: <price currency="US dollar">.
  • Первая строка файла, пролог <?xml version="1.0" encoding="UTF-8"?>, задает версию и кодировку. Она не обязательна, но с текстом на разных языках выручает.
  • От HTML отличается тем, что теги не заданы заранее: называть их можно как угодно, а отображением данных XML не занимается вовсе.
  • Одинаковые имена тегов из разных источников разводят префиксами и пространствами имен (xmlns), а уникальность имени обычно обеспечивают через URI.

Что такое XML?

XML расшифровывается как eXtensible Markup Language, то есть «расширяемый язык разметки». Один из языков разметки тебе, возможно, уже знаком: ты слышал об HTML, с помощью которого создаются веб-страницы :)Две розовые бирки на веревочках: на левой нарисованы ноги в кроссовках с подписью <>MAN</>, на правой ноги в туфлях на каблуке с подписью <>WOMAN</>HTML и XML похожи даже внешне:
HTML 1

<h1>title</h1>
<p>paragraph</p>
<p>paragraph</p>
XML 1

<headline>title</headline>
<paragraph>paragraph</paragraph>
<paragraph>paragraph</paragraph>
HTML 2

<h1>title</h1>
<p>paragraph</p>
<p>paragraph</p>
XML 2

<chief>title</chief>
<paragraph>paragraph</paragraph>
<paragraph>paragraph</paragraph>
Иными словами, XML это язык для описания данных.

Зачем нужен XML?

XML изначально придумали для более удобного хранения и передачи данных, в том числе через Интернет. У него есть ряд преимуществ, которые позволяют успешно справляться с этой задачей. Во-первых, он легко читается и человеком, и компьютером. Думаю, ты без труда поймешь, что описывает этот xml-файл:
<?xml version="1.0" encoding="UTF-8"?>
<book>
   <title>Harry Potter and the Philosopher’s Stone</title>
   <author>J. K. Rowling</author>
   <year>1997</year>
</book>
Компьютер тоже без труда понимает такой формат. Во-вторых, поскольку данные хранятся в простом текстовом формате, при их передаче с одного компьютера на другой не возникнет никаких проблем с совместимостью. Важно понимать, что XML это не исполняемый код, а язык описания данных. После того, как ты описал данные с помощью XML, тебе нужно написать код (например, на Java), который сможет эти данные отправить/принять/обработать.

Как устроен XML?

Его главная составная часть это теги: вот такие штуки в угловых скобках:
<book>
</book>
Теги бывают открывающими и закрывающими. У закрывающего есть дополнительный символ “/”, это видно на примере выше. Каждому открывающему тегу должен соответствовать закрывающий. Они показывают, где начинается и где заканчивается описание каждого элемента в файле. Теги могут быть вложенными! В нашем примере с книгой у тега <book> есть 3 вложенных тега: <title>, <author> и <year>. Это не ограничивается одним уровнем: у вложенных тегов могут быть свои вложенные теги, и т. д. Такая конструкция называется деревом тегов. Давай рассмотрим дерево на примере XML-файла с описанием автосалона:
<?xml version="1.0" encoding="UTF-8"?>
<carstore>
   <car category="truck">
       <model lang="en">Scania R 770</model>
       <year>2005</year>
       <price currency="US dollar">200000.00</price>
   </car>
   <car category="sedan">
       <model lang="en">Ford Focus</model>
       <year>2012</year>
       <price currency="US dollar">20000.00</price>
   </car>
   <car category="sport">
       <model lang="en">Ferrari 360 Spider</model>
       <year>2018</year>
       <price currency="US dollar">150000.00</price>
   </car>
</carstore>
Здесь у нас есть тег верхнего уровня <carstore>. Его еще называют «root», то есть корневой тег. У <carstore> дочерние теги одного вида, <car>, в примере их три. У <car>, в свою очередь, тоже есть 3 своих дочерних тега: <model>, <year> и <price>. Каждый тег может иметь атрибуты, то есть дополнительную важную информацию. В нашем примере у тега <model> есть атрибут «lang», то есть язык, на котором написано название модели:
<model lang="en">Scania R 770</model>
Так мы можем указать, что название написано на английском языке. У нашего тега <price> (цена) есть атрибут «currency», то есть «валюта».
<price currency="US dollar">150000.00</price>
Так мы можем указать, что цена за машину указана в американских долларах. Таким образом, у XML есть «самоописывающий» синтаксис. Ты можешь добавить любую нужную тебе информацию для описания данных. Также в начало файла можно добавить строку с указанием версии XML и кодировки, в которой записаны данные. Она называется «prolog» и выглядит вот так:
<?xml version="1.0" encoding="UTF-8"?>
Мы применяем XML версии 1.0 и кодировку UTF-8. Это не обязательно, но может пригодиться, если ты, например, используешь в своем файле текст на разных языках. Мы упомянули о том, что XML переводится как «расширяемый язык разметки», но что значит «расширяемый»? Это означает, что он отлично приспособлен для создания новых версий твоих объектов и файлов. К примеру, мы хотим, чтобы в нашем автосалоне начали продавать еще и мотоциклы! При этом в программе нам нужно поддерживать обе версии <carstore>: и старую (без мотоциклов), и новую. Вот наша старая версия:
<?xml version="1.0" encoding="UTF-8"?>
<carstore>
   <car category="truck">
       <model lang="en">Scania R 770</model>
       <year>2005</year>
       <price currency="US dollar">200000.00</price>
   </car>
   <car category="sedan">
       <model lang="en">Ford Focus</model>
       <year>2012</year>
       <price currency="US dollar">20000.00</price>
   </car>
   <car category="sport">
       <model lang="en">Ferrari 360 Spider</model>
       <year>2018</year>
       <price currency="US dollar">150000.00</price>
   </car>
</carstore>
А вот новая, расширенная:
<?xml version="1.0" encoding="UTF-8"?>
<carstore>
   <car category="truck">
       <model lang="en">Scania R 770</model>
       <year>2005</year>
       <price currency="US dollar">200000.00</price>
   </car>
   <car category="sedan">
       <model lang="en">Ford Focus</model>
       <year>2012</year>
       <price currency="US dollar">20000.00</price>
   </car>
   <car category="sport">
       <model lang="en">Ferrari 360 Spider</model>
       <year>2018</year>
       <price currency="US dollar">150000.00</price>
   </car>
   <motorcycle>
       <model lang="en">Yamaha YZF-R6</model>
       <year>2018</year>
       <price currency="Russian Ruble">1000000.00</price>
       <owner>Vasia</owner>
   </motorcycle>
   <motorcycle>
       <model lang="en">Harley Davidson Sportster 1200</model>
       <year>2011</year>
       <price currency="Euro">15000.00</price>
       <owner>Petia</owner>
   </motorcycle>
</carstore>
Вот так легко и просто мы добавили описание мотоциклов в наш файл :) При этом нам совершенно не нужно задавать для мотоциклов те же дочерние теги, что и для машин. Обрати внимание, что у мотоциклов, в отличие от машин, есть элемент <owner>, то есть владелец. Это никак не помешает компьютеру (да и человеку тоже) прочитать данные.

Отличия XML от HTML

Мы уже сказали, что XML и HTML внешне очень похожи. Поэтому, очень важно знать, чем они отличаются. Во-первых, они используются для разных целей. HTML нужен для разметки веб-страниц. Например, если тебе нужно создать веб-сайт, с помощью HTML ты сможешь указать: «Меню должно быть в верхнем правом углу. В нем должны быть такие-то кнопки». Иными словами, задача HTML это отображение данных. XML нужен для хранения и передачи информации в удобном для человека и компьютера виде. Этот формат не содержит никаких указаний на то, как эти данные нужно отображать: это зависит от кода самой программы. Во-вторых, у них есть основное техническое отличие. Теги HTML являются заранее заданными («predefined»). Иными словами, для создания заголовка (например, большой надписи в начале страницы) в HTML используются только теги <h1></h1> (для заголовков поменьше <h2></h2>,<h3></h3>). Не получится создать заголовки в HTML, используя теги с другими названиями. XML не использует заранее заданные теги. Ты можешь давать тегам любые названия, какие захочешь: <header>, <title>, <idontknow2121>. Коротко все различия выглядят так:
HTML XML
Задача Отобразить данные: как страница выглядит в браузере Описать данные, чтобы их можно было сохранить и передать
Теги Заданы заранее, свои придумать нельзя Любые, какие нужны: <carstore>, <idontknow2121>
Внешний вид данных Задается самой разметкой Не задается никак, это забота программы, которая читает файл
Незакрытый тег Браузер, скорее всего, отрисует страницу и так Нарушение разметки это фатальная ошибка, документ не обработается

Разрешение конфликтов

Свобода, которую предоставляет XML, может привести и к некоторым проблемам. К примеру, одна и та же сущность (например, машина) может использоваться программой в разных целях. К примеру, у нас есть XML-файл, в котором описаны машины. Однако, наши программисты не договорились заранее между собой. И теперь, помимо данных реальных автомобилей, в наши xml попадают еще и данные игрушечных моделей! Более того, у них одинаковые атрибуты. В нашу программу приходит вот такой XML-файл. Как же нам отличить настоящую машину от игрушечной модельки?
<?xml version="1.0" encoding="UTF-8"?>
<carstore>
   <car category="truck">
       <model lang="en">Scania R 770</model>
       <year>2005</year>
       <price currency="US dollar">200000.00</price>
   </car>
   <car category="sedan">
       <model lang="en">Ford Focus</model>
       <year>2012</year>
       <price currency="US dollar">100.00</price>
   </car>
</carstore>
Здесь нам помогут префиксы и пространства имен. Чтобы отделять в нашей программе игрушечные машины от настоящих (да и вообще любые игрушечные вещи от их реальных прототипов), мы вводим два префикса: «real» и «toy».
<real:car category="truck">
   <model lang="en">Scania R 770</model>
   <year>2005</year>
   <price currency="US dollar">200000.00</price>
</real:car>
<toy:car category="sedan">
   <model lang="en">Ford Focus</model>
   <year>2012</year>
   <price currency="US dollar">100.00</price>
</toy:car>
Теперь наша программа сможет различить сущности! Все, что имеет префикс toy, будет отнесено к игрушкам :) Однако, мы пока не закончили. Чтобы использовать префиксы, нам надо зарегистрировать каждый из них в качестве пространства имен (namespace). Ну, на самом деле, «зарегистрировать» это громко сказано :) Достаточно просто придумать уникальное имя для каждого из них. Это как с классами: у класса есть короткое имя (Cat) и полное имя с указанием всех пакетов (zoo.animals.Cat) Для создания уникальных имен namespace обычно используют URI. Иногда сюда подставляют адрес в Сети, где подробно описаны функции и предназначение этого пространства имен. Но это не обязательно должен быть действующий интернет-адрес. Очень часто на проектах используют просто URI-подобные строки, которые помогают отследить иерархию пространств имен. Вот пример:
<?xml version="1.0" encoding="UTF-8"?>
<carstore xmlns:real="http://testproject.developersgroup1.companyname/department2/namespaces/real"
         xmlns:toy="http://testproject.developersgroup1.companyname/department2/namespaces/toy">
<real:car category="truck">
   <model lang="en">Scania R 770</model>
   <year>2005</year>
   <price currency="US dollar">200000.00</price>
</real:car>
<toy:car category="sedan">
   <model lang="en">Ford Focus</model>
   <year>2012</year>
   <price currency="US dollar">100.00</price>
</toy:car>
</carstore>
Конечно, в Сети нет никакого сайта по адресу http://testproject.developersgroup1.companyname/department2/namespaces/real Но тут есть полезная информация: за создание пространства имен «real» отвечает группа разработчиков «developersgroup1» из отдела «department2». Если нужно будет внести новые имена, или обсудить с ними возможные конфликты, мы знаем куда обратиться. Иногда в качестве уникального имени для namespace используют реальный адрес в Сети с описанием этого пространства имен. Например, если это большая компания, и ее проект будет использоваться миллионами людей по всему миру. Но это делается далеко не всегда: на Stackoverflow есть обсуждение этого вопроса. В принципе, требование использовать URI в качестве имен для namespace не является строгим: можно и просто рандомные строки. Такой вариант тоже будет работать:
xmlns:real="nvjneasiognipni4435t9i4gpojrmeg"
Но у использования URI есть ряд преимуществ. Подробнее об этом ты можешь почитать вот тут.

Основные стандарты XML

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

AJAX

Строго говоря, это не стандарт XML, а прием веб-разработки, который попал в этот список за компанию. AJAX это когда страница подгружает данные с сервера и обновляет себя, не перезагружаясь целиком! Звучит круто? :) Аббревиатура расшифровывается как Asynchronous JavaScript and XML, но XML остался в ней по историческим причинам: сегодня по такой схеме почти всегда возят JSON. Определение и примеры есть в глоссарии MDN.

XSLT

Позволяет преобразовывать XML-текст в другие форматы. Например, используя XSLT, ты можешь преобразовать XML в HTML! Задача XML, как мы уже говорили, это описание данных, а не отображение. Но с использованием XSLT мы можем обойти это ограничение! Вот здесь лежит документация MDN по XSLT: описание элементов преобразования и примеры того, как это работает :)

XML DOM

Позволяет получать, изменять, добавлять или удалять отдельные элементы из XML-файла. Вот небольшой пример как это работает. У нас есть файл books.xml:
<bookstore>
   <book category="cooking">
       <title lang="en">Everyday Italian</title>
       <author>Giada De Laurentiis</author>
       <year>2005</year>
       <price>30.00</price>
   </book>
   <book category="children">
       <title lang="en">Harry Potter</title>
       <author>J K. Rowling</author>
       <year>2005</year>
       <price>29.99</price>
   </book>
</bookstore>
В нем две книги. У книг есть такой элемент как заголовок, <title>. А вот тут мы при помощи JavaScript можем получить из нашего XML-файла все заголовки книг и вывести первый из них в консоль:
<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
  myFunction(this);
  }
};
xhttp.open("GET", "books.xml", true);
xhttp.send();

function myFunction(xml) {
    var xmlDoc = xml.responseXML;
  document.getElementById("demo").innerHTML =
  xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue;
}
</script>

</body>
</html>
Пример рабочий, но написан по старой моде: XMLHttpRequest и var сегодня заменяют на fetch(), о чем прямо говорит MDN. Логика при этом остается той же: получить файл, разобрать его как XML, достать нужный тег. Про разбор XML в браузере есть отдельная статья MDN :)

DTD (document type definition)

Позволяет определить список разрешенных элементов для какой-то сущности в XML-файле. К примеру, мы работаем над сайтом книжного магазина, и все команды разработчиков договорились, что для элемента book в XML-файлах должны быть указаны только атрибуты title, author и year. Но как нам защитить себя от невнимательности? Очень легко!
<?xml version="1.0"?>
<!DOCTYPE book [
       <!ELEMENT book (title,author,year)>
       <!ELEMENT title (#PCDATA)>
       <!ELEMENT author (#PCDATA)>
       <!ELEMENT year (#PCDATA)>
       ]>

<book>
   <title>The Lord of The Rings</title>
   <author>John R.R. Tolkien</author>
   <year>1954</year>
</book>
Здесь мы определили список допустимых атрибутов для <book>. Попробуй добавить туда новый элемент, и сразу получишь ошибку!
<book>
   <title>The Lord of The Rings</title>
   <author>John R.R. Tolkien</author>
   <year>1954</year>
   <mainhero>Frodo Baggins</mainhero>
</book>
Ошибка! “Element mainhero is not allowed here” Есть и много других XML-стандартов. Ознакомиться с каждым из них можно на сайте W3C: там собраны спецификации всего семейства XML, от XML Schema до XPath и XQuery. Да и вообще, если тебе нужна информация по XML, там можно найти практически все :) Ну а наша лекция на этом подошла к концу. Настало время вернуться к задачам! :) До встречи!

Вопросы и ответы

Что такое XML простыми словами?

Это текстовый формат для описания данных. Название расшифровывается как eXtensible Markup Language, то есть расширяемый язык разметки. Данные размечаются парными тегами в угловых скобках, теги вкладываются друг в друга и образуют дерево. XML не программа и не язык программирования: он ничего не выполняет и ничего не рисует, он только хранит данные в виде, понятном и человеку, и машине.

Чем XML отличается от HTML?

Целью и свободой в именах тегов. HTML нужен, чтобы браузер отобразил страницу, и его теги заданы заранее: заголовок это <h1>, абзац это <p>, придумать свои нельзя. XML нужен, чтобы описать данные, и теги в нем называют как удобно: <carstore>, <price>, что угодно. Про внешний вид XML не знает ничего, это забота программы, которая файл читает.

Что такое пролог в XML и обязателен ли он?

Пролог это первая строка файла вида <?xml version="1.0" encoding="UTF-8"?>. Она сообщает версию XML и кодировку, в которой записаны данные. Строка не обязательна, файл будет работать и без нее, но с ней надежнее: если в данных встречается текст на разных языках, явно указанная кодировка избавляет от проблем с нечитаемыми символами.

Зачем нужны пространства имен (namespace) в XML?

Чтобы одинаковые имена тегов из разных источников не путались между собой. Если в один файл попадают данные о настоящих машинах и об игрушечных моделях, теги <car> будут выглядеть одинаково. Решение это префикс: <real:car> и <toy:car>. Каждый префикс объявляют через атрибут xmlns, а в качестве уникального имени обычно берут URI, причем сайта по этому адресу может и не существовать: важна только уникальность строки.

Что такое DTD и зачем проверять структуру XML?

DTD (document type definition) это описание того, какие элементы разрешены внутри тега и в каком порядке. Если команда договорилась, что у <book> бывают только <title>, <author> и <year>, то DTD превращает эту договоренность в правило: лишний элемент вызовет ошибку сразу, а не через месяц в чужом коде. Кроме DTD для той же задачи используют схемы XSD, они умеют описывать еще и типы данных.

Чем XML отличается от JSON и что выбрать?

XML описывает данные тегами и умеет то, чего у JSON нет: атрибуты, пространства имен, комментарии, проверку структуры через DTD или XSD, преобразование через XSLT. JSON проще и компактнее, у него нет закрывающих тегов и он ложится один в один на объекты и массивы. Поэтому веб-API сегодня почти всегда отдают JSON, а XML остается там, где важна строгая схема и сложная структура: конфигурации, обмен документами, корпоративные интеграции. В Java с XML встречаешься постоянно хотя бы потому, что на нем написаны файлы сборки Maven.

Читайте также