Использование XML и XSLT для создания LinuxFocus.org(/Nederlands)

ArticleCategory: [Artikel Kategorie]

Applications

AuthorImage:[Bild des Autors]

[Фото автора]

TranslationInfo:[Author and translation history]

original in en Egon Willighagen

en to ru Denis Kolobynin

AboutTheAuthor:[Über den Autor]

Собирается получить в этом году диплом специалиста и начать работать над получением звания доктора философии в chemometrics. Очень любит баскетбол, но на первом месте LinuxFocus и Linux.

Abstract:[Zusammenfassung]

Эта статья содержит июльское выступление сделаное на Libre Software Meeting в Bordeaux. Оно описывает базу данных XML, использующуюся для автоматической генерации страниц на сайте LinuxFocus.org(/Nederlands).

ArticleIllustration:[Titelbild des Artikels]

[Иллюстрация]

ArticleBody:[Der eigentliche Artikel]

Введение

Система используемая главным образом для управления документами и переводами на LinuxFocus, состоит из нескольких ASCII файлов, таких как resdb.txt, issuedb.txt и maindb.txt. Формат этих фалов фиксирован, и используется для генерации web-страниц. Но такую систему трудно расширить, а различные типы данных делают трудным просмотр всей информации в статье и ее анализ.

Когда я сделал новую базу данных, автоматическая генерация содержания страниц слабо использовалась на LinuxFocus. Как редактор Нидерландской команды, я страстно желал чтобы на сайте автоматически генерировались индексные страницы. На редактирование нескольких HTML файлов каждый раз когда переводилась новая статья уходило много усилий и этот процесс довольно часто был источником ошибок в ссылках. Вот почему я решил создать новую систему в которой я мог бы легко добавлять информацию и в которой можно было бы легко генерировать индексные страницы для сайта. Я начал работать над ней где-то летом 2000 года.

Выбор XML был совершенно случайным. Сначала я думал использовать реляционную базу данных, но поскольку я имею опыт по работе с XML и мне хотелось создать систему базирующуюся на текстовых файлах, я предпочёл XML. Надо было ввести новую единую систему нумерации, поскольку до этого использовалось две или три различных схем одновременно. Guido Socher приложил немало усилий и выполнил всю работу по перенумерации (спасибо!).

Определение типа документа (DTD) все еще разрабатывается, но для тестирования он кое-где используется в системе. С новой единой системой нумерации, оставалось только заполнить базу данных информацией. После добавления 20 статей, мне стало понятно что предстоит титанический труд. Можно было бы конечно написать скрипты для использования старых файлов, но во-первых отсутствовала кое-какая информация, которая должна была храниться в новой базе данных, а во-вторых, как уже говорилось, информация была рассредоточена по нескольким файлам. К счастью, к проекту присоединился Floris Lambrechts, который добавил большую часть информации в базу данных. Спасибо ему большое, без него система не была бы сегодня тем чем она есть.

Вместе с введением нового формата появилась возможность добавлять новую информацию. За прошлый год в базу данных были добавлены новые типы информации. Раньше существовали таблицы авторов, переводчиков, редакторов и других людей связанных с LinuxFocus и таблицы размещений файлов. Причиной добавления новой информации послужило то, что с момента основания LinuxFocus, существовало несколько схем именования файлов. После перенумерации их число уменьшилось до двух. Некоторые файлы используют SSI и имеют расширение .shtml, более старые статьи используют расширение .html. Тэг <file> может быть использован для переопределения установок по умолчанию. (Текущие установки используют формат "article" + номер статьи " + ".shtml". Возможно добавление ".meta", если это мета-файл LinuxFocus.).

После того, как база данных достигла своего критического минимума, я потестировал программы которые я написал на предмет выяснения быстродействия. В данный момент используемые таблицы стилей XSLT, это отнюдь не первая реализация. Сначала был код на Perl, но по мере увеличения размера базы данных, производительность стала важна, и первый прототип был заменен. Перед тем как я начну рассказывать про инструменты, давайте я объясню Вам формат базы данных.

Определение типа документа (Document Type Definition)

Прежде всего XML - это описание синтаксиса для языков разметки. Он определяет, что документ должен содержать один корневой элемент и что каждый элемент должен состоять из открывающего тэга, содержания (текст, дочерние элемены, или и то и другое) и закрывающего тэга. Тэги должны состоять из символа "<" за которым следует название тэга и конечный символ ">". В закрывающем тэге перед именем должен стоять символ "/". Также, открывающий тэг может содержать аттрибуты, которые тоже имеют свой собственный синтаксис. Таким образом синтаксис описывает последовательность символов с помощью которых можно получить правильный XML документ. Примером XML документа может служить следующий текст:

<greeting>Hello, world!</greeting>

Кроме синтаксиса, языки также содержат семантику. Она определяет как каждый элемент связан с другими. Если взять для примера HTML, то в нем семантика определяет что тэг <html> должен содержать тэг <body>, и не наоборот. Также определяется что тэг <img> и тэг <br> пустые. Если семантика дана в правильной нотации, то с помощью ее программа может проверить документ. Одна из официальных нотаций называется Document Type Definition (Определение типа документа), коротко DTD. Если документ проходит проверку, он называется правильным XML документом.

Теперь, после того как мы узнали что такое DTD, давайте взглянем на LinuxFocus XML Database DTD. Для некоторых определений будут даны примеры. Изучив эти примеры Вы получите представление о том как хранится информация в XML базе данных.

<database>

Корневой элемент XML базы данных LinuxFocus, или одно из ее расширений или локализаций - элемент <database>.

<!ELEMENT database    (themes?, persons?, issues?, articles?)>
    

Знак "?" подразумевает, что дочерний элемент может не появиться или появиться только один раз. Таким образом, база данных может содержать информацию о тематике, личностях, изданиях и статьях. Здесь всё просто, поэтому давайте перейдём к более интересному примеру.

<themes>

Все темы хранятся в элементе <themes>, который является дочерним для элемента <database>. Каждая тема имеет уникальный ID (идентификационный номер), название и как необязательные элементы - резюме и изображение.

<!ELEMENT themes      (theme+)>
  <!ELEMENT theme       (title*, desc?, img?)>
    <!ELEMENT title       (#PCDATA)>
    <!ELEMENT desc       (#PCDATA)>
    <!ELEMENT img         (EMPTY)>
    

Некоторые из этих элементов должны иметь аттрибуты. Они также описываются в DTD. У каждого элемента содержащего текст есть аттрибут xml:lang. Этот аттрибут определяет язык текста. Например - "en", "fr" и "nl". Аттрибуты id и xml:lang определены в оригинальной спецификации XML и являются частью синтаксиса XML.

<!ATTLIST theme       id            ID            #REQUIRED>
<!ATTLIST title       xml:lang      NMTOKEN       #REQUIRED>
<!ATTLIST desc        xml:lang      NMTOKEN       #REQUIRED>
<!ATTLIST img         src           CDATA         #REQUIRED>
    

База данных может выглядеть так:

<database>
  <themes>
    <theme id="hw">
      <title xml:lang="en">Hardware</title>
      <img src="Hardware.jpg"/>
    <theme>
  <themes>
</database>
    

<issues>

Номера содержатся в элементе <issues>. Также как и темы каждый номер имеет уникальный ID

<!ELEMENT issues      (issue+)>
  <!ELEMENT issue       (title+, published?, file*)>
    <!ELEMENT title       (#PCDATA)>
    <!ELEMENT published   (EMPTY)>
    <!ELEMENT file        (#PCDATA)>
    

Элемент <published> определяет опубликован номер или нет. Следующий номер и псевдо-номера SomeLanguage2Eng не имеют этого элемента. Элемент <title> опять же содержит аттрибут @xml:lang. Элемент <file> определяет каталог в котором размещен номер. Он не должен указывать на index.html, поскольку в последствии будет использоваться для определения размещения файлов.

Пример (аттрибут @code введен для сортировки):

    <issue id="ToBeWritten" code="999996">
      <title xml:lang="en">Not yet written articles</title>
    </issue>
    <issue id="September2001" code="200109">
      <title xml:lang="en">September2001</title>
    </issue>

<persons>

Информация об авторах и переводчиках хранится в элементе <person>. Каждая персона имеет уникальный ID.

  <!ELEMENT persons     (person+)>
    <!ELEMENT person      ((name|email)*,(homepage|nickname|desc|team)*)>
      <!ELEMENT email       (#PCDATA)>
      <!ELEMENT name        (#PCDATA)>
      <!ELEMENT homepage    (#PCDATA)>
      <!ELEMENT nickname    (#PCDATA)>
      <!ELEMENT desc        (#PCDATA|%html-els;)*>
      <!ELEMENT team        EMPTY>
    

Каждая персона может иметь следующую информацию: имя, адрес электронной почты (или несколько), адрес домашней странички (или несколько) и прозвища. Если персона также является членом команды переводчиков, то добавляется элемент <team>. Для того чтобы знать, например, что Floris член Нидерландской группы в элемент <person> добавляется следующая строка: <team xml:lang="nl"/>. Наконец каждая персона может иметь описание, которое может содержать дополнительные ссылки.

Пример:

    <person id="nl-ew">
      <name>Egon Willighagen</name>
      <email>egonw@linuxfocus.org</email>
      <team xml:lang="nl"/>
    </person>

<articles>

Безусловно статьи являются наиболее интересной частью базы данных.

  <!ELEMENT articles    (article+)>
    <!ELEMENT article     (title+, 
        (file|personref|abstract|issueref|themeref|
         nometa|nohtml|translation|proofread)*)>
      <!ELEMENT abstract    (#PCDATA)>
      <!ELEMENT nohtml      EMPTY>
      <!ELEMENT nometa      EMPTY>
      <!ELEMENT translation (personref*, (reserved|finished|proofread)*)>
        <!ELEMENT reserved    (#PCDATA)>
        <!ELEMENT finished    (#PCDATA)>
        <!ELEMENT proofread   (personref*, (reserved|finished)*)>
<!ATTLIST article     id            ID            #REQUIRED
                      xml:lang      NMTOKEN       #IMPLIED
                      type          (article|coverpage)
                                                  "article"
                      next          IDREF         #IMPLIED
                      prev          IDREF         #IMPLIED>
<!ATTLIST file        xml:lang      NMTOKEN       #REQUIRED
                      type          (target|meta) "target">
<!ATTLIST translation from          NMTOKEN       #REQUIRED
                      to            NMTOKEN       #REQUIRED>

    

Каждая статья имеет по крайней мере один заголовок; один для каждого языка. Элемент <file> может быть использован для задания размещения файла статьи, для META и HTML версий (смотри пример ниже). Если ни META ни HTML версии статьи не доступны, могут использоваться тэги <nohtml/> и <nometa/>. Каждая статья может иметь краткий обзор. Это резюме содержащееся в базе данных может быть использовано для индексирования страниц.

Элемент <article> имеет пять аттрибутов: обязательный @ID, необязательный аттрибут xml:lang для определения языка на котором написана статья, аттрибут @type используемый для обложки, которая для удобства перевода также представлена как статья. И наконец два необязательных аттрибута - @next и @prev, которые используются для связи статей в серии.

Статья связана с номером и темой элементами <issueref> и <themeref>, которые имеют аттрибут @href. Значением этого аттрибута является уникальный идентификатор - ID нужного номера или темы.

Пример:

    <article id="article206" xml:lang="en">
      <title xml:lang="en">Using XML and XSLT to build 
        LinuxFocus.org(/Nederlands)</title>
      <personref href="nl-ew"/>
      <issueref href="ToBeWritten"/>
      <themeref href="appl"/>
      <abstract xml:lang="en">
This article shows you how parts of the Dutch web site of LinuxFocus is 
generated with XSLT tools from the XML database. It compares this with 
the (very) much slower DOM tools in Perl.
      </abstract>
    </article>

Локализованая версия элемента <article> может выглядеть так:

    <article id="52">
      <title xml:lang="nl">Enlightenment</title>
      <file xml:lang="nl">Nederlands/July1998/article52.html</file>
      <translation from="en" to="nl">
        <personref href="nl-tu"/>
        <reserved>2000-09-06</reserved>
        <finished>2000-10-04</finished>
        <proofread>
          <personref href="nl-fl"/>
          <reserved>2000-10-04</reserved>
          <finished>2000-10-04</finished>
        </proofread>
      </translation>
      <abstract xml:lang="nl">
Enlightenment is een Linux window-manager met uitgebreide mogelijkheden. 
Dit artikel bespreekt ze, samen met de installatie en de instelling van E. 
Dit alles is niet voor beginners daar E op het moment nog in beta-stadium 
verkeert.
      </abstract>
    </article>

Здесь показано, что перевод начат в определённую дату, закончен, но в данный момент находится в вычитке. В любом случае персона, которая делала работу, определяется элементами <personref>.

Для всех элементов наилучшим описанием может служить сама база данных:

Автоматическое создание web-страниц

Одной из причин для создания нового формата базы данных являлась автоматическая генерация страниц. Теперь, когда мы разобрались с форматом базы данных, давайте посмотрим как мы можем генерировать с помощью нее web-страницы.

Сначала немного истории. Первая реализация использовала Perl-модули для связи с базой данных. Несмотря на то, что интерфейс очень прост, реализация была очень медленной. Затем информация содержалась в XML контейнере называемом Document Object Model (DOM). Большинство реализаций для DOM, очень медленны, по крайней мере немного медленее чем альтернативный Simple Application interface for XML (SAX).

Если задачей стоит только лишь генерация web-страниц то наилучшим вариантом вероятно будет третий: XSLT. Это основаный на XML язык трансформаций. На данный момент существует большое количество XSLT процессоров и поддерживаются большинство языков программирования. Некоторое время назад была статья на LinuxFocus XML::XSLT, одна из реализация на Perl XSLT. Со времен публикации этой статьи, вышло много реализаций и я хочу Вам порекомендовать следующие:

Нижеследующие примеры используют Sablotron.

XSLT процессор получает два файла на входе. Один из них, это XML-исходник который должен быть трансформирован. Другой - таблица стилей XSLT, которая определяет нужные трансформации. Для генерации web-страниц LinuxFocus используются следующие таблицы стилей XSLT:

Например для того, чтобы сгенерировать mainindex.html, Нидерландская команда запускает:

sabcmd stylesheets/mainindex.xslt db/lfdb.nl.xml > ../mainindex.html

Таблицы стилей находятся в корне Английской базы данных, и требуют на вход только локализованную XML базу данных. Некоторые из них требуют дополнительных параметров:

sabcmd stylesheets/theme.xslt db/lfdb.nl.xml '$theme=appl' > ../Themes/appl.html

Нидерландский index.html также генерируется из базы данных, но использует немного более сложный алгоритм. index.html получается с помощью lfpagecomposer Guido Socher'а из серии предварительно обработаных входящих файлов. Эти файлы в свою очередь генерируются с помощью *.pre файлов. Вот пример такого файла:

  <H2>Vorige nummers</H2>
 
<p>Dit zijn de uitgaven van LinuxFocus in het Nederlands:
<ul>
<!-- macro xslt previssues -->
</ul>

Обработка завершается запуском программы apply_stylesheets.pl которая ищет команды <!-- macro xslt [stylesheet] --> и разбирает с помощью неё базу данных. Заметьте, что расширение .xslt опущено. Наш Makefile содержит:

%.shtml: %.pre
        @echo "Making $*..."
        @../../xml/bin/apply_stylesheets.pl $*.pre

Полученые *.shtml файлы используются скриптом lfpagecomposer. Таблицы стилей, которые используются дле генерации index.html следующие: issuetoc.xslt, previssues.xslt и recently_translated.xslt.

Создание локализаций

Для использования этой системы для других языков, Вам надо сделать следующее:

  1. локализовать XML базу данных (как lfdb.nl.xml)
  2. локализовать таблицы стилей

Сделать второе чуть более сложнее чем первое. В принципе только текст на выходе должен быть локализован, но таблицы стилей пока не имеют свойств для определения локализации. Как бы то ни было реализовать это возможно.

Я могу порекомендовать редактор XML с поддержкой DTD. На Emac Вы можете использовать например основной режим psgml. nsgmls) предоставит Вам возможность проверки документов. Это поможет избежать ошибок. В Emac Вы также можете нажав правую кнопку мыши увидеть элементы и аттрибуты, которые можно вставить в определённое место в XML документе.

Если у Вас появились какие-то проблемы Вы можете всегда почитать эту статью. Если это не помогло, можете обратиться ко мне

Локализация таблиц стилей посложнее. Текст перемешан вместе с командами XSLT. Команды Вам трогать не стоит (если только Вы знаете что делаете), чтобы не нарушить функциональность. Я планирую в будущем создать такие таблицы стилей, которые предполагают редактирование текстового файла не содержащего XSLT команд.

Планы на будущее

Я надеюсь эта статья поможет Вам начать работу. Большая часть текста может быть скопирована с Нидерландских файлов. Все файлы находятся под лицензией FDL и GPL. А вот мои планы на следующий год: