Плох ли XML?
Сейчас объясню.
К основам
XML — это «eXtensible Markup Language», «расширяемый язык разметки». Язык разметки (markup language) — это набор символов, вставляемых в текст для выделения отдельных частей.
Вот есть у нас текст, и мы хотим выделить, где тут заголовок, а где — цитата. Мы берем этот текст и вставляем в него его <h1> и <citation> где нам надо2.
Языки разметки и языки представления данных
- SGML, XML, XHTML, markdown, textile — языки разметки.
- JSON, YAML, S-expressions — языки представления (обмена, сериализации) данных.
Разница между ними в том, что
- языки разметки плохо справляются с представлением данных,
- языки представления данных — катастрофически плохо справляются с разметкой текста.
Почему нельзя верстать сайты на S-expression’ах
Вот мы написали такой абзац1:
Оба любят писать с ресурсов api и home. У обоих аккаунты на сервере jabber.zp.ua (проверьте сами — http://juick.com/ugnich@jabber.zp.ua, http://juick.com/plaingirl@jabber.zp.ua).
Мы хотим его немного разметить, чтобы браузер его красиво показывал. Вот так у нас получится с XHTML’ом:
123
<p>Оба любят писать с ресурсов <code>api</code> и <code>home</code>.У обоих аккаунты на сервере jabber.zp.ua (проверьте сами — <a href="http://juick.com/ugnich@jabber.zp.ua">1</a>,<a href="http://juick.com/plaingirl@jabber.zp.ua">2</a>).</p>
А вот так получится, если мы будем использовать что-то вроде sexpr’ов:
12345678910
(p"Оба любят писать с ресурсов"(code "api")" и "(code "home")". У обоих аккаунты на сервере jabber.zp.ua (проверьте сами — "(a "http://juick.com/ugnich@jabber.zp.ua" 1)", "(a "http://juick.com/plaingirl@jabber.zp.ua" 2)").")
Чтобы не выглядело так страшно, можно убрать идентацию:
123
(p "Оба любят писать с ресурсов" (code "api") " и " (code "home")". У обоих аккаунты на сервере jabber.zp.ua (проверьте сами — " (a "http://juick.com/ugnich@jabber.zp.ua" 1) ", "(a "http://juick.com/plaingirl@jabber.zp.ua" 2) ").")
Выглядит ужасно. XHTML даже с длинными тегами смотрится как текст со вставками разметки, а вот sexpr’овый вариант напоминает программный код, который целиком не прочитаешь. Особенно отрываются от текста знаки препинания и пробелы — не поймешь, правильно они расставлены или нет. Все это, конечно, субъективно, но я думаю, что в этом примере вы не будете со мной спорить.
Плюс к этому следует добавить, что в случае с XHTML поломанный тег внутри другого тега (например, <p><br</p>) не натворит ничего страшного вне родительского тега, а в случае с sexpr’ами неправильно поставленная кавычка (которыми изобилует текст) рискует поломать весь документ. Это будет сущим адом.
Почему нельзя писать конфиги на XML’е
Начнем с простого. Выдуманный пример на XML:
1234
<outgoing rate="monthly"><price>30.</price><name>Internet</name></outgoing>
И он же — но для s-expressions:
1234
(outgoing(rate monthly)(price 30.)(name "Internet"))
Избыточность XML’а сразу бросается в глаза. За тегами данных не видно. Ну а что вы хотите — это не текст, который надо размечать.
При написании такого конфига выводит из себя необходимость заканчивать строки закрывающими тегами. В конфиге хочется нажать клавишу «enter» и закончить таким образом строку. В случае XHTML’а вопроса «зачем ставить закрывающий тег?» не возникало, так как текст нужно размечать со всеми его пробелами и переносами строк, которые убирать нельзя.
Ладно, идем дальше. Слева — боевой конфиг icecast’а. Справа — он же, но на языке представления данных.
|
|
Справа не придуманный мною на коленке формат. Это YAML. Вы можете подключить библиотеку для работы с yaml’ом и парсить такие конфиги так же легко, как и XML’овые.
Удивительно, но иногда конфиги на XML бывают почти так же трудночитаемыми, как и исходный код программы. Вот это из openbox’а. Чтобы забиндить там клавишу, нужно написать что-то вроде:
123
<keybind key="A-F4"><action name="Close"/></keybind>
А это из моего конфига xmonad’а, на чистом хаскелле:
12
-- close focused window, ((modMask .|. shiftMask, xK_c ), kill)
Почему на XML’е нельзя делать базы данных
Про это написал Joel Spolsky еще десять лет назад:
Как реляционная база данных выполняет команду SELECT author FROM books? В реляционной базе данных каждая строка в таблице (например, в таблице books) имеет одинаковую длину в байтах, и каждое поле находится по фиксированному смещению относительно начала строки. Так что, например, если каждая запись в таблице books имеет длину 100 байт, и поле author находится по смещению 23, то имена авторов расположены начиная с байтов 23, 123, 223, 323, и т.д. Как выглядит код перехода на следующую запись? Примерно так:
pointer += 100;Одна инструкция процессора. Ну очень быстро.
Теперь посмотрим на ту же таблицу в XML.
1234567891011
<?xml blah blah><books><book><title>UI Design for Programmers</title><author>Joel Spolsky</author></book><book><title>The Chop Suey Club</title><author>Bruce Weber</author></book></books>
Вопрос. Как выглядит код перехода на следующую запись?
Ээээ..
Итак, мораль
- Если вам нужно разметить текст — берите язык разметки. Например, XML.
- Если вам нужно сериализовать данные, прикрутить конфиг, сделать текстовый протокол взаимодействия — берите язык представления данных. Например, YAML.
- Если вам нужна база данных — берите систему управления базой данных. Например, sqlite.
Просто? Очень просто!
И не надо пихать технологию в код только потому, что она «крутая» и «модная». А скорее всего потому, что вы ничего другого не освоили. Или не хотите разобраться в предметной области. Нужен конфиг для программы? Будете делать его на XML’е? Вот зачем?
Причем не важно вообще, что это за технология. Я встречал программистов, которые пихали не к месту не только XML и PHP, но и даже LaTeX. Опыт растет, а критерии выбора инструмента остаются теми же: «то, чем все пацаны на районе пользуются».
Дисклеймер от автора
Я ненавижу XML. Сложно вспомнить другую технологию, которая бы столько раз выводила меня из себя. Но мне так же сложно указать на недостатки XML’а в пределах его ниши. Все случаи «плохого XML’а» были связаны только с неправильным его использованием.
А разгадка одна: программисты — идиоты.
Примечания
1 ↑ Этот абзац взят из статьи про Антона Угнича
2 ↑ Дается эта возможность, правда, ценой того, что текст, похожий на XML-теги, придется эскейпить. Ну, по меньшей мере заменять < на < — обычно этого бывает достаточно. Плохо, конечно, но другие способы отделения разметки от текста бывают еще хуже3, а языки разметки, в которых эскейпинг не предусмотрен, можно замучаться парсить4.
3 ↑ Об использовании разделителей хорошо написал Voker57 в своей статье «Delimeters Must Die».
4 ↑ Пример языка разметки, в котором «все настолько просто, что не нужно ни о чем думать» — textile. Вообще, язык получается таким, что некоторые вещи на нем невозможно написать. Свои мучения в его реализации я изложил отдельно.