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

Что такое XML?

XML расшифровывается как eXtensible Markup Language — «расширяемый язык разметки». Один из языков разметки тебе, возможно, уже знаком: ты слышал об HTML, с помощью которого создаются веб-страницы :) 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">
       <title lang="en">Ford Focus</title>
       <year>2012</year>
       <price currency="US dollar">20000.00</price>
   </car>
   <car category="sport">
       <title lang="en">Ferrari 360 Spider</title>
       <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">
       <title lang="en">Ford Focus</title>
       <year>2012</year>
       <price currency="US dollar">20000.00</price>
   </car>
   <car category="sport">
       <title lang="en">Ferrari 360 Spider</title>
       <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">
       <title lang="en">Ford Focus</title>
       <year>2012</year>
       <price currency="US dollar">20000.00</price>
   </car>
   <car category="sport">
       <title lang="en">Ferrari 360 Spider</title>
       <year>2018</year>
       <price currency="US dollar">150000.00</price>
   </car>
   <motorcycle>
       <title lang="en">Yamaha YZF-R6</title>
       <year>2018</year>
       <price currency="Russian Ruble">1000000.00</price>
       <owner>Vasia</owner>
   </motorcycle>
   <motorcycle>
       <title lang="en">Harley Davidson Sportster 1200</title>
       <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>.

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

Свобода, которую предоставляет 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">
       <title lang="en">Ford Focus</title>
       <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">
   <title lang="en">Ford Focus</title>
   <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">
   <title lang="en">Ford Focus</title>
   <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. Он позволяет изменять содержимое веб-страницы без ее перезагрузки! Звучит круто? :) Можешь испробовать эту технологию лично вот тут. XSLT — позволяет преобразовывать XML-текст в другие форматы. Например, используя XSLT, ты можешь преобразовать XML в HTML! Задача XML, как мы уже говорили, — описание данных, а не отображение. Но с использованием 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>
Опять же, рекомендую посмотреть, как работает этот пример, используя песочницу:) 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-стандартов. Ознакомиться с каждым из них и попробовать «поковыряться» в коде ты можешь на сайте WC3 (раздел «Important XML Standarts»). Да и вообще, если тебе нужна информация по XML, там можно найти практически все :) Ну а наша лекция на этом подошла к концу. Настало время вернуться к задачам! :) До встречи!