 | Уровень сложности: простой Дит Элза (Dethe Elza), старший технический архитектор, JustSystems Дэвид Мертц (David Mertz), технический писатель, Gnosis Software, Inc.
26.04.2007 В прошлом выпуске колонки Вопросы XML Дэвид Мертц объяснял, что reStructured Text - это облегченный язык разметки для форматирования преимущественно текстовых документов, а до этого был рассмотрен YAML, облегченный язык разметки для документов, которые содержат преимущественно данные. Являются ли эти технологии полезными и сейчас, с появлением AJAX и микроформатов, иными словами – достаточно ли "легки" микроформаты? Посмотрите, как можно использовать JSON (который проще, чем YAML) при помощи MochiKit для AJAX без X, и примените reStructured Text для генерирования микроформатов.
XML всегда использовался для разметки как документов, так и структурированных данных, что в зависимости от точки зрения конкретного автора интерпретировалось то как самое большое достоинство этого языка, то как самый большой недостаток. В тех случаях, когда нет резких границ между документом и данными, XML может быть лучшим вариантом, но в качестве общего решения XML может быть и более сложным, чем любое имеющееся частное решение проблемы. Ранее Дэвид рассказывал о YAML (см. раздел Ресурсы). YAML ("Ain't Markup Language" (тоже язык разметки) или, по-другому, "Yet Another Markup Language" (еще один язык разметки) - это диалект, предназначенный для того, чтобы упростить транспорт данных (чисел, строк, списков, простых структур) по сравнению с XML. В данной статье мы будем говорить о стандарте JSON (JavaScript Object Notation), который является подмножеством YAML, но при этом проще в разработке и синтаксическом разборе. В JavaScript и Python, если JSON поступил от надежного источника, он может быть просто обработан механизмом выполнения сценариев, но синтаксические анализаторы, которые существуют для JSON, происходят от менее надежных источников.
Поскольку мы будем использовать JSON, чтобы подойти к спектру "документ-данные" со стороны данных, вы можете использовать структурированные текстовые форматы, не обращая внимания на свойства микроформата как документа. Существует три основных подхода к структурированию текста (если не учитывать многие разновидности разметки Wiki): reStructured Text, Markdown и Textile. Мы рассмотрим каждый из этих подходов, чтобы посмотреть, как они смогут справиться с нашим примером микроформата, хотя бы теоретически.
Что входит в микроформат?
Какие типы данных может содержать микроформат? Суть микроформата заключается в том, чтобы разместить небольшой (как правило) объем данных в форме, которая легко может быть обработана человеком или компьютером, поэтому можно получить некоторые преимущества, если проигнорировать это условие и закодировать данные только для человека или только для компьютера, а не для обоих случаев, а затем обработать данные, чтобы получить микроформатированную версию. В общем случае пример календаря hCalendar включает следующие фрагменты информации:
- Содержание/Название;
- Размещение;
- URL;
- Дата (и, по желанию, время) начала действия;
- Дата (и, по желанию, время) окончания действия;
- Временная зона;
- Описание.
На самом деле придется написать не очень большой код. В листинге 1 показан пример события hCalendar:
Листинг 1. Событие hCalendar
<div class="vevent">
<a class="url"
href="http://www.vanpyz.org/conference/keynotes.html">
<abbr class="dtstart" title="20060804T1900-0700">
4 Август 2006 г. - 19:00
</abbr> -
<abbr class="dtend" title="20060804T2100-0700">
21:00
</abbr> -
<span class="summary">
Vancouver Python Workshop Keynotes
</span> - at
<span class="location">
Fletcher Challenge Canada Theatre,
SFU Harbour Center,
Downtown Vancouver
</span>
</a>
<div class="description">
<p>The Vancouver Python Workshop keynote address is an
opportunity to hear from leading members of the Python
community. This years speakers are Guido van Rossum of
Google and Jim Hugunin from Microsoft.</p>
</div>
</div> |
Если вы просмотрите этот листинг от начала до конца, чтобы понять суть данных, вы сможете написать подобный код при помощи JSON. Обратите внимание на то, что для даты, времени и временной зоны используется кодировка ISO8601, стандартный способ форматирования даты и времени, которые сами по себе являются микроформатом (см. раздел Ресурсы). Следующий пример (листинг 2) - это корректный код в языках JavaScript или Python:
Листинг 2. Код с использованием JSON
event = {
'title': 'Vancouver Python Workshop Keynotes',
'location': 'Fletcher Challenge Canada Theatre, \
SFU Harbour Center, Downtown Vancouver',
'url': 'http://www.vanpyz.org/conference/keynotes.html',
'start': '2006-08-04T19:00-0700',
'end': '2006-08-04T21:00-0700',
'description': 'The Vancouver Python Workshop keynote address\
is an opportunity to hear from leading members of the Python\
community. This years speakers are Guido van Rossum of Google\
and Jim Hugunin from Microsoft.'}; |
Этот формат, как вы увидите далее, также легко может передаваться через интернет. Сюжет развивается....
Вы внесли данные в мои документы!
Использование JSON для контента микроформата представляет подход с точки зрения данных. Что касается документа, в микроформатах мы можем идти от структурированного текста. Как выглядел бы календарь hCalendar, написанный при помощи reStructured Text? Известно, что reST позволяет создавать подключаемые модули расширения при помощи директив, поэтому директива о проведении синтаксического разбора данных hCalendar будет выглядеть примерно так:
.. event::
LOCATION: Fletcher Challenge Canada Theatre,
SFU Harbour Center, Downtown Vancouver
DTSTART: TZID=America/Vancouver:20060804T190000
DTEND: TZID=America/Vancouver:20060804T210000
SUMMARY: Vancouver Python Workshop Keynotes
DESCRIPTION: The Vancouver Python Workshop keynote address
is an opportunity to hear from leading members of the Python
community. This years speakers are Guido van Rossum of Google
and Jim Hugunin from Microsoft. |
Интересно, что данный вид hCalendar представляет собой
отображение более раннего стандарта iCalendar на подмножество HTML. Но на что же похож
этот загадочный iCalendar? В листинге 3 показано то же событие в iCalendar:
Листинг 3. Событие в iCalendar
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Apple Computer\, Inc//iCal 2.0//EN
BEGIN:VEVENT
DURATION:PT3H
LOCATION: Fletcher Challenge Canada Theatre,
SFU Harbour Center, Downtown Vancouver
DTSTAMP:20060615T034522Z
UID:FE31377A-AB78-4D99-BC25-3F09C99E5928
DTSTART;TZID=America/Vancouver:20060704T100000
SUMMARY:Vancouver Python Workshop Keynotes
DESCRIPTION:The Vancouver Python Workshop keynote address
is an opportunity to hear from leading members of the Python
community. This years speakers are Guido van Rossum of Google
and Jim Hugunin from Microsoft.
END:VEVENT
END:VCALENDAR |
Да, iCalendar - это текстовый формат, который относительно прост для синтаксического разбора,
можно найти соответствующие библиотеки, а с результатом работать в том языке программирования,
который вы предпочитаете. Поэтому, хотя и допустимо создать для reStructured Text директиву, которая будет извлекать
все элементы данных hCalendar, лучше изменить директиву .. include:: так,
чтобы сделать возможным включение контента iCalendar напрямую, в формате hCalendar. Поскольку многие из
существующих инструментов, такие, как iCal от Apple, предусматривают возможность импортирования и экспортирования форматирования iCalendar, многократное использование
форматирования напрямую может быть довольно полезным. Мы не будем подробно рассматривать добавление
или изменение директив в reStructured Text, как в интересах краткости, так и потому, что Дит
уже написал практическое руководство по этой теме вместе с ведущим разработчиком reStructured Text Дэвидом Гуджером (David Goodger)
(см. раздел Ресурсы).
 |
Это легче воздуха, но дышится труднее
Хотя JSON предоставляет более простой способ форматирования данных, чем YAML или XML, reStructured Text может
быть довольно сложным инструментом. Документ в reStructured Text может читаться проще, чем XML, и
может быть проще в использовании, если вы не станете пытаться использовать все его функции. Но когда вы начнете добавлять большое количество
директив, таблиц и других функций, Измеритель сложности, предложенный Дитом, будет зашкаливать. Поскольку JSON добивается
простоты за счет специализации (известный компромисс, который восходит к Domain Specific Languages, или DSL),
можно и дальше упрощать структурированный текст, если вы не боитесь пожертвовать некоторыми
функциями и гибкостью reStructured Text. И оказывается, что такое еще более легкое
и ориентированное на документ форматирование существует.
Мы рассмотрим Textile и MarkDown, два облегченных варианта структурированного текста, которые упрощают микроформатирование данных. К сожалению, те же свойства, которые делают эти инструменты столь подходящими для создания контента на основе документа, приводят к их непригодности для решения задач с подходом на основе данных, таких, как hCalendar. Textile не имеет разметки для
<div> или <abbr> или других способов добавить классы в <a>. Хотя этот стандарт достаточно
гибкий и упрощает добавление атрибутов class, id и style, в нем нет
механизма, позволяющего добавить атрибуты title. В Markdown вообще не предусмотрен механизм добавления
атрибутов (хотя PyMarkdown имеет расширение для их поддержки), и не имеет структур для <div> и <abbr>. Любая из двух систем может быть использована в виде преформатированного HTML, но тогда вы сразу теряете преимущество использования облегченного форматирования.
Отсутствие поддержки микроформатов в этих облегченных языках разметки
понятно. Микроформаты - это, по своей сути, данные, а языки Textile
и MarkDown создавались как инструменты, предназначенные для того, чтобы писать в интернете. Они
пытаются упростить получение слов, которые вам нужны, за счет минимального форматирования,
но игнорируют проблемы вставки данных, предназначенных для чтения машиной. Одна из самых
старых проблем XML - это то, что язык используется как для данных (информации, которая предназначена для чтения машиной)
так и для контента (текста, который предназначен для чтения человеком). Форматы структурированного текста теряют преимущества там, где начинается содержимое
, тогда как YAML и JSON плавно теряют преимущества, когда речь заходит о данных. Каждый из них
может делать свою работу так же хорошо или даже лучше, чем XML, но в тех случаях, когда граница
между данными и содержимым стерта, как в микроформатах, эти
языки могут столкнуться с затруднениями на переходе.
 |
REST - JSON
Многие примеры, в которых используется язык JSON, показывают, как браузер может получать сообщения JSON от
сервера, использующего метод GET. Но парадигма REST состоит из четырех глаголов: GET, POST, PUT
и DELETE, и для этого есть причина. GET следует использовать для того, чтобы выполнять стандартные запросы к
Web-ресурсу (то есть, метод GET должен быть идемпотентом), POST, чтобы
создавать новые ресурсы, PUT, чтобы обновлять существующие ресурсы, и
DELETE для удаления ресурса. Поскольку мы хотим быть верными приверженцами REST,
давайте создадим простую инфраструктуру для перемещения данных JSON, воспользовавшись всеми четырьмя
глаголами.
Ниже приводится код программы CGI на языке Python, которая инкапсулирует простейший
каркас для перемещения по битам воображаемого кода JSON. Программа использует библиотеку
Боба Ипполито (Bob Ippolito) simplejson для более безопасного разбора кода JSON,
вместо того, чтобы просто использовать процедуру eval для строки, полученной через интернет. Безусловно, нужно намного
больше, чтобы создать интерфейс REST (создание URI для каждого
ресурса - непростая задача). В разделе Ресурсы можно найти ссылки на дополнительную
информацию. В листинге 4 демонстрируется простейший сервер REST/JSON:
Листинг 4. Сервер REST/JSON
#!/usr/local/bin/python
'''
Minimal JSON REST server
'''
import os
import cgi
import cgitb
cgitb.enable()
import simplejson
sample_data = {'name': 'King Arthur',
'quest': 'To seek the holy grail',
'airspeed_of_unladen_European_swallow': '24 MPH'}
def post(args):
'''
Used to create a new resource
'''
new_uri = 'http://example.org/' # URI of newly created resource
sample_data['result_uri'] = new_uri
print simplejson.dumps(sample_data)
def put(args):
'''
Used to update an existing resourc
'''
sample_data.update(args)
print simplejson.dumps(sample_data)
def get(args):
'''
sed for any side-effect free request
'''
print simplejson.dumps(sample_data)
def delete(args):
'''
Used to remove an existing note
'''
print simplejson.dumps({'content':'None'})
def main():
method = os.environ.get('REQUEST_METHOD', 'GET')
if method == 'GET':
args = None
else:
json_value = cgi.FieldStorage().getfirst('json_value')
args = simplejson.loads(json_value)
if method == 'POST':
method = args['method'] # fix for browsers that don't
# send PUT or DELETE properly
# Start an HTTP response
print "Content-type: text/plain"
print ""
# Python dispatch idiom using a dictionary vs. case-statement
dict(POST=post,
PUT=put,
GET=get,
HEAD=get,
DELETE=delete)[method](args)
if __name__ == '__main__':
main() |
Программа листинга 4 предназначена для обработки основного кода REST и JSON на стороне сервера. Для стороны клиента Дит написал небольшой фрагмент на JavaScript, который можно встроить в Web-страницу.
В этом примере тоже используется код Боба Ипполито (Bob Ippolito) - библиотека MochiKit
JavaScript, которой мы остались очень довольны. В листинге 5 приводится код простейшего клиента JSON/REST:
Листинг 5. Простейший клиент JSON/REST
//
// rest.js
//
// Simplistic framework for bi-directional JSON transport via REST
//
SERVER = 'http://localhost/rest_cgi.py'
function handle_success(result){
alert('Success: ' + result.responseText);
}
function handle_error(result){
logError(result.responseText);
}
var sample_content = {'name': 'Sir Lancelot',
'quest': 'To seek the holy grail',
'favorite_color': 'blue'};
function _sendVerb(verb, content, handler){
var req = getXMLHttpRequest();
// Certain browsers don't actually support verbs besides GET
// and POST, spoiling the party for the rest of us
content['method'] = verb;
if (verb != 'GET'){
verb = 'POST'
}
req.open(verb, SERVER);
# queryString is the easiest way to send data to the server
json_content = queryString(['json_value'],
[serializeJSON(content)]);
var req = sendXMLHttpRequest(req, json_content)
req.addCallbacks(handler, handle_error);
}
function get(){
_sendVerb('GET', '', handle_success);
}
function post(){
_sendVerb('POST', sample_content, handle_success);
}
function put(){
_sendVerb('PUT', sample_content, handle_success);
}
function test_delete(){
_sendVerb('DELETE', sample_content, handle_success);
} |
 |
JSON и микронавты
При помощи программ из листингов 4 и 5 вы можете перемещаться по битам кода JSON достаточно свободно, но вам все еще нужно что-то делать для этого. Учитывая все, что было сказано раньше, естественным желанием будет конвертировать данные обратно в формат hCalendar или iCalendar, в зависимости от того, обрабатываются ли данные на стороне клиента или на стороне сервера, а также от конкретных задач. Например, можно использовать MochiKit (особенно функции быстрого вызова DOM) на стороне клиента, чтобы создать пример шаблона для данных JSON в листинге 2 и переформатировать их в формат hCalendar прямо в браузере, заменив функцию handleSuccess(), как показано в листинге 6:
Листинг 6. Замена функции handleSuccess()
function handleSuccess(result){
var data = evalJSON(result.responseText);
// Преобразуем данные json в узлы DOM
var hCalendarData = objectToCalendar(data);
// In a real application we would add/replace this in our
// Web page somewhere, but for this demo we'll just display it.
alert(toHTML(hCalendarData));
}
var ABBR = createDOMFunc('abbr');
function pad2(number){
if (number < 10){
return '0' + number;
}else{
return '' + number;
}
}
function time(date){
return pad2(date.getHours()) +
':' +
pad2(date.getMinutes());
}
function objectToCalendar(obj){
var startDate = isoTimestamp(obj.start);
var endDate = isoTimestamp(obj.end);
var cal = DIV({'class':'vevent'},
A({'class':'url', 'href': obj.url},
ABBR({'class':'dtstart', 'title': obj.start},
startDate.toLocaleDateString(),
' - ',
time(startDate)
),
' - ',
ABBR({'class': 'dtend', 'title': obj.end},
time(endDate)
),
' - ',
SPAN({'class': 'summary'}, obj.summary),
' - at ',
SPAN({'class': 'location'}, obj.location)
),
DIV({'class':'description'},
P(obj.description)
)
);
return cal;
} |
Из примера не вполне понятно, какие функции выполняет код в листинге 6; MochiKit определяет множество функций быстрого вызова HTML DOM, которые позволяют достаточно легко создать структуру DOM фрагмента hCalendar. Если нет встроенных ярлыков для элементов <abbr>, код также создает один такой ярлык. MochiKit выполняет конвертирование объектов JavaScript Date в формат ISO8601 и обратно, но встроенная строковая интерпретация
объекта Date - это не совсем то, что нам нужно, поэтому нужно написать программу, которая сама выполняла бы интерпретацию. Ничего
особенно сложного, но все еще не очень ясно, поэтому рекомендуем обратиться к превосходной документации по Mochikit (см. раздел Ресурсы).
Теперь вы можете переслать данные JSON браузеру при помощи AJAX и форматировать их в формат hCalendar при помощи
шаблонов браузера. Помимо того, что этот подход полностью соответствует тому, что о нем говорят. Он предлагает то, что может оказаться действительно полезным.
Прополка в саду ветвящихся тропинок
Какую выгоду от всего этого можете получить именно вы? Действительно ли удобнее включить iCalendar в код reStructured Text или лучше переслать биты кода JSON не в hCalendar, а в браузер? Почему просто не написать двоичный код, или XML, и покончить с этим?
В действительности, окажется ли методика, описанная здесь, полезной для вас или нет, описывается старой поговоркой специалистов по информационным технологиям: поживем увидим. Если вы создаете Web-сервисы на основе REST, то передача данных через JSON, а не через XML, может быть более быстрой и более удобной. Если вы используете язык reStructured Text для упрощенного (и более читабельного) создания HTML-контента, то возможность непосредственного включения микроформатов, либо в виде HTML (hCalendar), либо в виде простого текста (iCalendar) может упростить задачу. При создании новой системы стоит подумать об обеих технологиях.
Конечная задача микроформатов - сделать данные проще для человеческого восприятия, в то же время сохраняя их дружественными к машинному синтаксическому разбору. Философия микроформатов состоит в многократном использовании уже имеющихся семантических форматов, в частности, HTML, везде, где это возможно. AJAX, JSON и REST упрощают и обогащают создание систем для микроформатов и другого контента, в то время как облегченная разметка делает создание и редактирование контента для таких систем более простым, быстрым и дружественным для человеческого восприятия. Поэтому все упомянутые технологии имеют право на существование, и вы можете заметить синергетический эффект, если будете применять их в сочетаниях друг с другом.
Загрузка | Описание | Имя | Размер | Метод загрузки |
|---|
| Example code | x-matters46-example.zip | 3KB | HTTP |
|---|
Ресурсы Научиться
- Оригинал статьи XML Matters: Lighter than microformats: Picoformats;
- "XML Matters: reStructured Text" (Вопросы XML: reStructured Text) (Дэвид Мертц (David Mertz), сайт developerWorks, февраль 2003 г.): Откройте для себя, что облегченная разметка может быть лучше, чем XML;
- "XML Matters: YAML improves on XML" (Вопросы XML: YAML превосходит XML) (Дэвид Мертц (David Mertz), сайт developerWorks, октябрь 2002 г.): Научитесь использовать YAML в тех случаях, где вы использовали бы для передачи данных XML;
- "Вопросы XML: микроформаты; технология канал-поток (pipestreaming)" : Узнайте, когда следует использовать микроформаты вместо произвольных диалектов XML;
- "XML Matters: Up and Atom" (Вопросы XML: технология Аtom) (Дит Элза (Dethe Elza), сайт developerWorks, май 2006 г.): Исследуйте протокол Atom Publishing Protocol как идеальный интерфейс REST;
- "Introducing JSON" (Введение в JSON): Посетите сайт Дугласа Крокфорда (Douglas Crockford), который представляет JSON всему миру. Здесь вы найдете ссылки на статьи, примеры и библиотеки для использования JSON с многими языками программирования;
-
Restructured Text: Узнайте больше о проекте Python docutils -- по большей части это формат reStructured Text, который может генерировать не только HTML, но и XML, PDF, слайды, DocBook, и другие форматы. Авторы использовали reStructured Text, например, при создании этой статьи;
-
Markdown: Ознакомьтесь с вкладом, который внес Джон Грубер (John Gruber) в лотерею облегченной разметки. Автор обнаружил, что текст, который генерируется кодом Markdown, является самым ясным и читаемым, поэтому он использует его в своих блогах, но за ясность приходится платить: этот стандарт не является легко расширяемым;
-
Textile: Ознакомьтесь с форматом Дина Аллена (Dean Allen) для облегченной разметки -- язык почти так же читабелен, как Markdown (это полностью субъективное мнение авторов), но позволяет встраивать идентификаторы, атрибуты классов и стили CSS непосредственно в документ (и результирующий HTML), что несколько снижает читабельность, но зато дает больше гибкости;
-
ISO8601: Ознакомьтесь с анализом шаблонов ISO8601 для форматирования даты, времени и временного промежутка в тексте, который написал Маркус Кун (Markus Kuhn);
-
Протокол Atom Publishing Protocol: Ознакомьтесь с действующим в настоящее время проектом IETF (9 редакция) развивающейся спецификации;
- "How to create a RESTful Protocol" (Как создать протокол на базе REST): Подробно изучите вопросы, которые необходимо иметь в виду при создании интерфейса REST, в статье Джо Грегэрио (Joe Gregario);
- "Calculating the average airspeed of an un-laden sparrow" (Как рассчитать скорость полета воробья без груза): В статье вы найдете ответ на вопрос, который ставил в тупик поколение ученых времен короля Артура;
- "Creating reStructured Text Directives" (Создание директив reStructured Text) Прочитайте это руководство по созданию новых директив для обработчика reStructured Text, написанное Дитом Элза (Dethe Elza), Дэвидом Гуджером (David Goodger) и Феликсом Виманом (Felix Wiemann);
-
IBM XML 1.1 certification: Узнайте, как стать сертифицированным разработчиком IBM в области XML 1.1 и смежных технологий;
-
XML: См. зоны developerWorks по XML и просмотрите различные технические статьи и советы, учебные руководства, стандарты и Красную книгу IBM (Redbooks);
-
Технические события и новые материалы на Web-сайте developerWorks: Следите за технологиями в данных сеансах;
Получить продукты и технологии
-
Simple JSON: Попробуйте использовать эту библиотеку Python для безошибочного синтаксического разбора и сериализации данных JSON;
-
MochiKit: Загрузите MochiKit для нормализации JavaScript и DOM в разных браузерах, и поместите ее в множество утилит, большей частью на языке Python;
-
PyTextile: Станьте обладателем адаптации Python для облегченной системы разметки Дина Аллена (Dean Allen) Textile. Ссылка дана через механизм Wayback Machine сайта archive.org, поскольку сайт разработчика, кажется, больше не существует;
-
iCalendar для Python: Попробуйте пакет iCalendar, синтаксический анализатор / генератор файлов iCalendar для использования с языком Python. Программа соответствует спецификации RFC 2445 (iCalendar);
-
vobject: Проект Chandler предлагает пакет Python для синтаксического разбора и генерирования файлов vCalendar и vCard;
-
Пробное программное обеспечение IBM: Создайте следующий проект разработки с помощью пробного ПО IBM, которое можно загрузить непосредственно с сайта developerWorks.
Обсудить
Об авторах  | |  | Название любимой должности Дита Элзы (Dethe Elza) - Chief Mad Scientist (проект Mad Science, руководитель). C ним можно связаться по электронной почте delza@livingcode.org. Он ведет блог, в основном, на тему языка Python и Mac OS X, на сайте http://livingcode.blogspot.com/ и пишет программы для своих детей. Советы и рекомендации по материалам этой рубрики приветствуются. |
 | |  | Дэвид Мертц безгранично верит в открытые стандарты, его чуть отпугивает лишь многословие. С Дэвидом можно связаться по электронной почте mertz@gnosis.cx; его жизнь предлагается для пристального анализа на сайте http://gnosis.cx/dW/. Советы и рекомендации по материалам этого, прошлых и будущих выпусков рубрики приветствуются. Ознакомьтесь с книгой Дэвида
Обработка текста в языке Python
. |
Выскажите мнение об этой странице
|  |