Вопросы XML: Микроформаты: технология канал-поток (pipestreaming)

Дит Элза (Dethe Elza), Дэвид Мертц (David Mertz)

Одна из самых изящных абстракций компьютерных технологий - особые структуры - каналы в UNIX. Эти каналы позволяют повторно использовать небольшие программы (которые умеют делать что-то одно, но делают это хорошо), присоединяя их друг к другу так, чтобы вывод одной программы перетекал на ввод другой. К сожалению, поскольку каналы UNIX большей частью построчно-ориентированы, их нельзя просто применить для обработки XML. Мы познакомимся с некоторыми существующими инструментами, которые появились в результате множества попыток решить эту проблему.

Потоки - это понятие, связанное с каналами: они представляют собой среду, с которой работают каналы. Идея потока заключается в том, что программе не нужно иметь все данные в наличии, чтобы начать работать; это позволяет ей обрабатывать данные по мере их создания, данные, поступающие по сети или файлы, которые слишком велики, чтобы поместиться в память.

Почему следует использовать технологию канал-поток (pipestreaming)?

Аналогия с каналами и потоками оказалась очень удачной для UNIX и может с разной степенью успеха применяться ко многим другим системам. Она присутствует, в той или другой форме, в большинстве языков программирования и операционных систем. Применительно к XML самой распространенной формой обработки каналов и потоков являются фильтры SAX. Большинство читателей данной рубрики знают, что SAX - это простой пользовательский интерфейс (Simple API) для XML. Этот API ориентирован на обработку потоков, он анализирует XML и вызывает обработчики событий, как только произойдет значимое событие (например, закрытие или открытие элемента) в процессе анализа. Поскольку при SAX-обработке не нужно поддерживать состояние или строить крупные структуры данных (например, DOM), то она обычно используется для задач XML, имеющих дело с большими наборами данных (которые с трудом умещаются в памяти), если требуется высокая скорость обработки или в случае разреженных данных (используются только избранные фрагменты данных XML, а остальное игнорируется).

Проблема с использованием каналов и фильтров на уровне языка программирования, скажем, с классом Java™ InputStreamReader или фильтром SAX, заключается в том, что приходится работать на очень низком уровне с очень нудным, подверженным ошибкам и содержащим множество повторов кодом. Именно желание найти способ перехода на более высокий уровень абстрации кода, сохранив при этом гибкость для широкого диапазона задач обработки XML, вынуждает использовать рассматриваемые библиотеки и инструменты. Кроме того, во многих случаях объединение отдельных инструментов XML для многоэтапной обработки (канал) приводит к многократному повторению синтаксического разбора XML. Было бы удобно сохранить обрабатываемый код XML в памяти, пока он передается с этапа на этап.

Но для начала давайте подумаем, какие проблемы мы можем решить, используя библиотеки технологии канал-поток (pipestreaming)? Конечно, хорошо мечтать об этом абстрактном способе работы с XML, но для чего мы можем его использовать?

Некоторые распространенные применения каналов XML включают:

  • Чтение/Разбор XML (с диска, из сети, с системы управления контентом CMS или откуда-нибудь еще);
  • Преобразование не-XML в XML (например, преобразование формата reStructured Text в XHTML);
  • Проверка корректности ( DTD, XSchema, RelaxNG или Schematron);
  • Агрегация фрагментов XML (например, через XInclude или DITA Maps);
  • Преобразование (чаще при помощи XSLT);
  • Заполнение шаблонов (замена значений заместителей на реальный контент);
  • Форматирование для отображения на мониторе или печати (через CSS или XSL-FO);
  • Сериализация/Запись обратно в XML (на диск, в сеть, в CMS, или куда-либо еще);
  • Связывание их вместе в синтаксис описателя (обычно тоже XML).

Обратите внимание, что канал может включать любые из этих применений, некоторые из них могут повторяться и изменяться, а также включать другие настраиваемые элементы. Но перечисленные применения , наверное, можно назвать основными ингредиентами обработки XML. И, как уже было отмечено ранее, канал должен сохранять разобранный XML на протяжении всего процесса, а не проводить повторный анализ на каждом этапе.

Например, можно взять немного гипертекста, который характеризует людей и события, и скомпоновать из него Web-календарь. Или можно проиграть все в обратном порядке: просмотреть Web-календари нескольких людей, чтобы проанализировать их планы, и выбрать время встречи. Для этого примера я взял календарь и людей, но идея подходит для всего, что можно выразить в форме XML (а сейчас из этих вещей можно составить огромный список).

Отступление по поводу микроформатов

Одна из причин, по которой в качестве примера был взят календарь, заключается в том, что здесь начинается движение под названием "микроформаты", в котором не пытаются изобрести колесо или что-либо еще, а берут существующие спецификации и переводят на существующие диалекты XML. Самый распространенный диалект, на котором они концентрируются, это XHTML, используются атрибуты class и link , чтобы добавить семантики; цель - добиться одновременно удобочитаемости для человека (на Web-странице) и для компьютера (путем включения данных для компьютера в атрибуты). Существуют микроформаты для людей и организаций (hCard, основанный на vCard спецификации), календарей и событий (hCalendar, основанный на iCalendar спецификации), структур и ссылок (XOXO), тэгов и ключевых слов (rel-tag), обзоров (hReview), социальных сетей (XFN), лицензирования контента (rel-license) и многого другого. В этой статье мы остановимся на микроформате hCalendar.

В листинге 1 приведен пример микроформата hCalendar:

Листинг 1. Микроформат hCalendar

<div class="vevent">
    <abbr class="dtstart" title="20060322T0830-0800">
      22 Март 2006 г. - 08:30
    </abbr> -
    <abbr class="dtend" title="20060322T0900-0800">
      09:00
    </abbr> -
    <span class="summary">
        Dentist Appointment
    </span> - at
    <span class="location">
       Office on Pacific Ave.
     </span>
     <div class="description">
        Get permanent crown installed.
    </div>
</div>

Этот частный пример был сгенерирован формирователем микроформата hCalendar. Для синтаксического разбора микроформатов hCalendar и hCard у Фила Доуэса (Phil Dawes) на сайте имеется библиотека языка python, а на страницe hCalendar вы можете найти много других инструментов и реализаций. Пользователи браузера Firefox® с модулем расширения Greasemonkey могут обнаружить даже сценарии Greasemonkey для извлечения различных микроформатов с посещаемых ими страниц. Сайты Upcoming.org и Eventful.com помещают у себя события и календари в формате hCalendar. Безусловно, существует много данных, с которыми можно работать в виде микроформатов.

Возвращаемся к каналам и потокам

Как создать канал для обработки XML-данных после того, как вы нашли или создали их? У вас есть несколько вариантов различной изощренности и сложности. Фильтры SAX - это своеобразная низкоуровневая инфраструктура, которая лежит в основе или создает идеи для других наборов инструментов. XMLGAWK - это построчно-ориентированный язык программирования GNU AWK, который, благодаря расширениям, позволяющим обрабатывать XML, превратился в элементно-ориентированный. XmlRpcFilteringPipe это технология канал-поток (pipestreaming) по Лайону Кимбро (Lion Kimbro), которая для построения канала использует XML-RPC. NetKernel™ - полный комплект инструментов, который берет идею технологии канал-поток (pipestreaming) и извлекает из нее все, что можно. Apache Cocoon построен на основе понятия "каналы компонентов", которое принципиально аналогичен понятию технологии канал-поток (pipestreaming) XML, но более сложен. Все эти технологии демонстрируют хорошие достижения, но мы рассмотрим два проекта, которые (на мой взгляд) добились наилучшего баланса между простотой и эффективностью; затем можно рассмотреть пару обещающих разработок..

Во-первых, это XPipe от Шона Мак-Грата (Sean McGrath). Шон разработал также Pyxie (сейчас Pixie2), который превращает XML в построчно-ориентированный язык, пригодный для обработки стандартными каналами и фильтрами Linux. XPipe использует эту программу с расширяемым набором компонентов Java. Мне кажется, что Шон был на правильном пути, но, видимо, ему не хватило сил. Его сайт некоторое время не обновлялся, и Шон сообщил мне по электронной почте, что, поскольку у его компании есть коммерческая версия, разработку которой они продолжают, у него не было времени работать над версией с открытым исходным кодом, а если бы оно и было, то он в значительной степени изменил бы методы работы. Я думаю, его подход был хорош, но он мог бы быть проще при той же основной концепции.

Лучший конкурент, которого я нашел на сегодня - это Simple XML Pipeline, или SXPipe, Норма Уолша (Norm Walsh). В инфраструктуре присутствуют этапы почти для всех задач обработки XML, перечисленных мной в начале статьи (это не совпадение, просто я построил свой список, исходя из возможностей, предлагаемых SXPipe), при этом он хорошо определен, для него легко писать XML. Есть несколько пожеланий: по умолчанию он требует Java 1.5, который на OS X в настоящее время можно получить только в виде предварительной версии для разработчика, и сами этапы представляют собой довольно тяжелые компоненты Java, что делает систему менее простой для расширения, чем она могла бы быть, но это довольно мелкие проблемы по сравнению с тем, что в SXPipe реализовано правильно. Помимо того, что SXPipe имеет простой синтаксис и модель обработки, у него простая структура (всего пять элементов), он соответствует стандартам (использует XPath 1.0, XML Namespaces, XML Base, кроме того, он использует XSL Transformation и все это в надлежащем контексте (что бывает не всегда). При этом язык даже проще, чем комментарий W3C (редактирующий норму) "XML Pipeline Definition Language" (Язык описания каналов XML), хотя сохраняет основную эффективность и гибкость этой более ранней работы. В листинге 2 показан пример документа SXPipe:

Листинг 2. Документ SXPipe

<pipeline xmlns="http://sxpipe.dev.java.net/xmlns/sxpipe/">
    <stage process="Read" input="dw-article.xml"/>
    <stage process="Validate" schema="dw-article-5.0.xsd"/>
    <stage process="Transform" stylesheet="dw-article-5.0.xsl"/>
    <stage process="Write" output="dw-article.html"/>
</pipeline>

Этот пример довольно прост и красив. В моем воображении я мог бы расширить это при помощи языка Python. Затем, я мог бы, например, легко добавить этапы для обработки реструктурированного текста в XML в качестве части моего канала, или применить шаблоны Cheetah. Реализация SXPipe на языке Python не была бы слишком сложной, сложности могли возникнуть с ее переносимостью, поскольку Python по умолчанию не поставляется с библиотеками проверки корректности XSL или XML.

У технологии канал-поток (pipestreaming) светлое будущее. Во-первых, тот факт, что так много инструментов основано на одной идее, говорит о реальной необходимости этой технологии. Если человечество когда-либо стандартизует SXPipe (например), или продолжит разрабатывать что-либо свое, метафоры каналов и потоков должны остаться. С точки зрения моего любимого языка программирования Python, PullDom всегда оставалась частью стандартной библиотеки, и будет дополнена в будущем 2.5 выпуске отличной библиотекой ElementTree Фредерика Ланда (Fredrik Lundh). Я попытался реализовать SXPipe при помощи ElementTree, но в этой библиотеке все еще нет инструментов для трансформации и проверки корректности, а поддержка XPath крайне примитивна. Библиотека lxml Мартина Фассена (Martijn Faassen) включает очень эффективные, но трудные в применении библиотеки libxml2 и libxslt, написанные на языке Python, и предлагает такой же простой интерфейс, как ElementTree, а также XInclude, полную поддержку XPath, XSLT и различные формы проверки корректности. Когда этот проект стабилизируется, в нем будет относительно несложно создавать красивые реализации SXPipe на языке Python.

Обобщим полученные навыки

Теперь у вас есть некоторый контент в виде микроформата и инструмент для заполнения канала. И что теперь можно сделать со всем этим? Давайте рассмотрим несколько возможностей. Это умозрительный эксперимент, поэтому все URL - это просто примеры и в действительности никуда не ведут. Представим, что вы являетесь членом семьи из четырех человек по фамилии Nuclear: Ванда (мать), Ксатрес (отец), Йоланда (дочь) и Сандер (сын). Каждый из вас имеет календарь на своей Web-странице в формате http://example.com/calendar/[имя]/[период], где период может быть представлен в форме год, год-месяц, год-месяц-день или более естественной фразой вроде "завтра" или "на следующей неделе". Вам нужно взять все эти календари и периодически объединять их для импорта в программу вроде®iCal для Apple® или Mozilla®Sunbird™. Возьмем из интернета таблицу стилей трансформации XSLT для преобразования hCalendar в iCalendar, назовем файл "cal-transform.xsl" и используем исходный документ (source-calendar.xml) в листинге 3:

Листинг 3. source-calendar.xml

<calendar xmlns:xi="http://www.w3.org/2001/XInclude">
    <xi:include href="http://example.com/calendar/Wanda/today"/>
    <xi:include href="http://example.com/calendar/Xathrus/today"/>
    <xi:include href="http://example.com/calendar/Yolanda/today"/>
    <xi:include href="http://example.com/calendar/Zander/today"/>
</calendar>


Далее, применим канал из листинга 4 к исходному документу:

Листинг 4. добавление к исходному документу

<pipeline xmlns="http://sxpipe.dev.java.net/xmlns/sxpipe/">
    <stage process="Read" input="source-calendar.xml"/>
    <stage process="XInclude"/>
    <stage process="Transform" stylesheet="cal-transform.xsl"/>
    <stage process="Write" systemId="family-calendar.ics"/>
</pipeline>


При исходных данных, показанных выше, выполнение этого канала должно сформировать для вас один календарь, который вы сможете импортировать. Давайте рассмотрим еще одно применение. Когда микроформат войдет в моду, вы сможете загрузить свои данные из банка (состояние счета и кредита), продовольственного магазина (ваши счета в цифровом виде), даже из библиотеки. Корректность большинства данных не будет особенно вас заботить, но банковские данные вы захотите проверить на соответствие схеме. Для каждого источника данных вы захотите применить преобразование данных, чтобы получить их все в одном формате. Поэтому используйте ваше воображение (и на время забудьте о безопасности; в конце-концов, это воображаемый канал), чтобы объединить все эти несопоставимые источники в один поток, показанный в листинге 5:

Листинг 5. Отдельный поток

				

<pipeline xmlns="http://sxpipe.dev.java.net/xmlns/sxpipe/">

    <!-- Get my schedule for the day -->
    <stage process="Read" input="http://myjob.com/myappointments"/>
    <stage process="Transform" stylesheet="calendar-to-portal.xsl"/>
    <stage process="Write" systemId="work.xml"/>

    <!-- Do I have any books due back at the library? -->
    <stage process="Read" input="http://muni-library.gov/books-due"/>
    <stage process="Transform" stylesheet="library-to-portal.xsl"/>
    <stage process="Write" systemId="library.xml"/>

    <!-- Get latest transactions in my chequing account -->
    <stage process="Read" input="http://mybank.com/chequeing-acct"/>
    <stage process="Validate" schema="my-bank-acct.xsd"/>
    <stage process="Transform" stylesheet="chequing-to-portal.xsl"/>
    <stage process="Write" systemId="chequeing.xml"/>

    <!-- Get latest transactions on my credit card -->
    <stage process="Read" input="http://mybank.com/my-credit-acct"/>
    <stage process="Validate" schema="my-creditcard.xsd"/>
    <stage process="Transform" schema="creditcard-to-portal.xsl"/>
    <stage process="Write" systemId="creditcard.xml"/>

    <!-- Check the weather forecast -->
    <stage process="Read" input="http://localweather.com"/>
    <stage process="Transform" stylesheet="weather-to-portal.xsl"/>
    <stage process="Write" systemId="weather.xml"/>


    <!-- Create an XInclude document to glue it all together -->
    <stage process="Document" label="accumulator">
        <portal xmlns:xi="http://www.w3.org/2001/XInclude"
            xmlns:"http://www.example.com/portal">
            <xi:include href="work.xml"/>
            <xi:include href="library.xml"/>
            <xi:include href="chequeing.xml"/>
            <xi:include href="creditcard.xml"/>
            <xi:include href="weather.xml"/>
        </portal>
    </stage>
    <stage process="XInclude"/>

    <!-- Convert it all to HTML -->
    <stage process="Transform" stylesheet="portal-to-html.xsl"/>

    <!-- Viola! We have our own personal portal on the world -->
    <stage process="Write" systemId="my-daily-portal.html"/>
</pipeline>

Век атома

Хм, я видел, как вы подняли брови, увидев вопрос в последнем примере, но это потому, что я до сих пор не объяснил пересечение микроформатов и синдикации. Большая часть актуального содержимого микроформата разработана (или быстро переделана) для передачи через агрегаторы каналов новостей, которые сначала предназначались для чтения блогов в формате RSS. И через агрегаторы проходит гораздо больше, чем hCalendar, как я отметил в предыдущем примере: уже существуют микроформаты для обзоров и схем, событий и людей, но скоро вы увидите микроформаты для финансовых транзакций, просроченных книг, прогнозов погоды и вещей, которые сейчас даже сложно представить.

Вместе с микроформатами на горизонте появляется Atom, который по сути имеет две спецификации: формат централизованного распределения (синдикации) информации Atom и Atom API. Синдикация информации при помощи Atom очень напоминает централизованное распределение при помощи старых форматов RSS, но оно более четко определено (и соответствует стандарту IETF). Однако это тема для следующей статьи, в которой мы рассмотрим пересечение микроформатов и централизованного распределения Atom. А до тех пор пусть ваши каналы не знают утечек, а ваши потоки будут чисты.


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=2560