Небольшое отступление: идея использовать Cls формат вместо XML появилась в 2001-м году после знакомства с языком CURL. В то время XML уже занял серьезные позиции, но еще не везде. Тем более, что в C/C++ никогда не было стандартной поддержки XML и для работы с XML требовалось искать и использовать сторонние библиотеки. Поэтому на тот момент формат Cls для работы с конфигурационными и лог файлами выглядел более предпочтительно, чем XML. С тех пор прошло достаточно много времени, поддержка XML существенно усилилась (как и проникновение его в массы), появились новые форматы YAML и JSON. Но даже на этом фоне Cls формат в своих нишах выглядит достаточно конкурентноспособно.
В Cls используются знакомые разработчикам по C/C++ escape-последовательности для представления символов в виде их кодов и для экранирования специальных символов.
Происходит это за счет:
отсутствия необходимости указывать имя в закрывающем теге;
отсутствия понятия атрибутов, что позволяет для простых тегов-значений задавать значения непосредственно в самом теге.
Можно сравнить несколько фрагментов на XML и Cls. В Cls варианте удалось освободится от части атрибутов:
XML
<service name="DayTime"> <ip value="localhost:3028"/> <ip value="my.site.org:5000"/> <message name="GetCurrentTime"/> <message name="GetUTCTime"> <priority value="0"/> <field name="localTime" type="String"/> <field name="timeZone" type="String"/> </message> </service>
Cls
{service {name "DayTime"} {ips localhost:3028 my.site.org:5000 } {message GetCurrentTime} {message GetUTCTime {priority 0} {field {name "localTime"} {type String}} {field {name "timeZone"} {type String}} } }
В нормальном XML, все теги должны принадлежать одному родителю и этот родитель должен быть единственным тегом верхнего уровня во входном потоке. Cls не требует этого.
В Cls нет атрибутов, все описания делаются на основе тегов. Это значит, что любой тег в дальнейшем можно расширить новыми подчиненными тегами. Например, в приведенном выше примере тег {param {value}} можно пополнить новыми тегами. А вот в случае XML атрибут value тега <param> уже останется таким, как есть.
XML является де-факто и де-юре стандартом во многих областях. Он поддерживается огромным количеством инструментов и лежит в основе многих технологий. Он общепризнан и раскручен. Соответственно, выбор XML гораздо более безопасен потому, что всегда найдется нужный инструмент и нужный разработчик, который этим инструментом может воспользоваться.
Вообще. Текущая версия Cls работает только с 8-битовыми текстом (ASCII).
Соответственно, cls-файлы не получится использовать из других языков программирования. Если только не реализовать поддержку Cls формата для них.
Главное отличие Cls от YAML заключается в том, что Cls не использует переводы строк и пробелы в качестве специальных символов. Что позволяет применять Cls, например, для формирования log-файлов (в которых каждая запись должна располагаться точно в одной строке).
Cls не чувствителен к ошибкам форматирования. Например, при модификации конфигурационных файлов “на скорую руку”. Или, что более важно, когда фрагменты Cls файла генерируются и при генерации нет возможности учитывать форматирование предыдущих фрагментов. Так, корректный Cls файл вполне может иметь вид:
{some-config {first-part {internal-tag "autogenerated"} {internal-tag "another autogenerated"} } }
однако, такое форматирование недопустимо в YAML.
Так же не все можно легко и логично представить в YAML. Например, требуется описать фильтр содержимого текстовых файлов, состоящий из произвольного количества регулярных выражений. Причем регулярное выражение может может либо разрешать включение в результирующее множество, либо напротив – запрещать. В Cls это записывается в виде простой последовательности тегов:
{filter {include "regex1" } {exclude "regex2" } {include "regex3" } }
В YAML же придется делать вектор из Hash-шей, причем в каждом Hash-е будет всего одна пара ключ/значение:
filter: - include: regex1 - exclude: regex2 - include: regex3
Остальные преимущества на данный момент на стороне YAML: лаконичность и поддержка в разных языках программирования.
Cls очень хорошо зарекомендавал себя при работе с конфигурационными файлами. Которые могут содержать довольно сложные описания, но сохранять при этом приемлимую читабельность. Которые правятся вручную в обычных текстовых редакторах.
Одним из простых способов ведения log-файлов и файлов протоколов является сохранение одной записи строго в одной строке файла. При этом обеспечивается защита от сбоев (например, все строки, которые из-за последствий сбоя не удалось корректно разобрать, просто игнорируются). А так же упрощается извлечение информации. Например, при помощи утилиты grep по шаблону извлекается вся запись целиком (если одна запись занимает несколько строк, то шаблон может быть найден только в одной из них и потребуется приложить дополнительные усилия, чтобы извлечь всю запись).
По этим показателям YAML вообще сложно расматривать в качестве формата для log-файлов. XML можно использовать, но придется применять дополнительные усилия для форматирования XML-потока в одну строку. В Cls это делается автоматически посредством ClsRuby::OneLineFormatter.
Парсинг Cls формата с помощью ClsRuby (как и cls_2 в C++) построен на идее о том, что каждый тег – это объект какого-то класса тега. Далее, для каждого значения в теге сразу же определяется, какому типу оно принадлежит и в каком формате должно быть указано. Поэтому конкретному Cls формату соответствует некоторая модель из объектов-парсеров (что выражается в программе наборов классов и атрибутов в них). А сам парсинг выполняется по аналогии с SAX парсингом XML. Что в результате парсинга приводит к тому, что в объектах-парсерах находятся извлеченные из входного потока значения. Остается их только взять. При этом проверку значений на корректность осуществляют сами объекты-парсеры во время парсинга входного потока.
В случае же с DOM-парсингом XML или ручным разбором YAML требуется сначала разобрать входной поток, а затем из полученного DOM-представления извлекать значения. Проверяя попутно их наличие, формат и допустимость.
Примечание. Работа с XML значительно упрощается, если используется инструмент с автоматизированным отображением XML на структуры данных.
# vim:ts=2:sts=2:sw=2:expandtab:ft=txt:tw=78
Generated with the Darkfish Rdoc Generator 2.