Плох ли 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/[email protected], http://juick.com/[email protected]).
Мы хотим его немного разметить, чтобы браузер его красиво показывал. Вот так у нас получится с XHTML’ом:
<p>Оба любят писать с ресурсов <code>api</code> и <code>home</code>.
У обоих аккаунты на сервере jabber.zp.ua (проверьте сами — <a href="http://juick.com/[email protected]">1</a>,
<a href="http://juick.com/[email protected]">2</a>).</p>
А вот так получится, если мы будем использовать что-то вроде sexpr’ов:
(p
"Оба любят писать с ресурсов"
(code "api")
" и "
(code "home")
". У обоих аккаунты на сервере jabber.zp.ua (проверьте сами — "
(a "http://juick.com/[email protected]" 1)
", "
(a "http://juick.com/[email protected]" 2)
").")
Чтобы не выглядело так страшно, можно убрать идентацию:
(p "Оба любят писать с ресурсов" (code "api") " и " (code "home")
". У обоих аккаунты на сервере jabber.zp.ua (проверьте сами — " (a "http://juick.com/[email protected]" 1) ", "
(a "http://juick.com/[email protected]" 2) ").")
Выглядит ужасно. XHTML даже с длинными тегами смотрится как текст со вставками разметки, а вот sexpr’овый вариант напоминает программный код, который целиком не прочитаешь. Особенно отрываются от текста знаки препинания и пробелы — не поймешь, правильно они расставлены или нет. Все это, конечно, субъективно, но я думаю, что в этом примере вы не будете со мной спорить.
Плюс к этому следует добавить, что в случае с XHTML поломанный тег внутри другого тега (например, <p><br</p>
) не натворит ничего страшного вне родительского тега, а в случае с sexpr’ами неправильно поставленная кавычка (которыми изобилует текст) рискует поломать весь документ. Это будет сущим адом.
Почему нельзя писать конфиги на XML’е
Начнем с простого. Выдуманный пример на XML:
<outgoing rate="monthly">
<price>30.</price>
<name>Internet</name>
</outgoing>
И он же — но для s-expressions:
(outgoing
(rate monthly)
(price 30.)
(name "Internet"))
Избыточность XML’а сразу бросается в глаза. За тегами данных не видно. Ну а что вы хотите — это не текст, который надо размечать.
При написании такого конфига выводит из себя необходимость заканчивать строки закрывающими тегами. В конфиге хочется нажать клавишу «enter» и закончить таким образом строку. В случае XHTML’а вопроса «зачем ставить закрывающий тег?» не возникало, так как текст нужно размечать со всеми его пробелами и переносами строк, которые убирать нельзя.
Ладно, идем дальше. Слева — боевой конфиг icecast’а. Справа — он же, но на языке представления данных.
|
|
Справа не придуманный мною на коленке формат. Это YAML. Вы можете подключить библиотеку для работы с yaml’ом и парсить такие конфиги так же легко, как и XML’овые.
Удивительно, но иногда конфиги на XML бывают почти так же трудночитаемыми, как и исходный код программы. Вот это из openbox’а. Чтобы забиндить там клавишу, нужно написать что-то вроде:
<keybind key="A-F4">
<action name="Close"/>
</keybind>
А это из моего конфига xmonad’а, на чистом хаскелле:
-- 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.
<?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. Вообще, язык получается таким, что некоторые вещи на нем невозможно написать. Свои мучения в его реализации я изложил отдельно.