<?xml version="1.0" encoding="windows-1251"?>
<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
 <stylesheet type="text/css">
               section section title { page-break-before: auto }
  image + p { page-break-before: avoid; margin-bottom: 1em }
  cite { font-style: normal }
 </stylesheet>
 <description>
  <title-info>
   <genre>comp_programming</genre>
   <author>
    <first-name>Алексей</first-name>
    <middle-name>Н.</middle-name>
    <last-name>Валиков</last-name>
   </author>
   <book-title>Технология XSLT</book-title>
   <annotation>
    <p>Книга посвящена разработке приложений для преобразования XML-документов с использованием XSLT — расширяемого языка стилей для преобразований. Обсуждается применение языков XSLT и XPath в решении практических задач: выводу документов в формате HTML, использованию различных кодировок для интернационализации и, в частности, русификации приложений, вопросам эффективности существующих подходов для решения проблем преобразования. Для иллюстрации материала используется большое количество примеров.</p>
    <p>Для начинающих и профессиональных программистов</p>
   </annotation>
   <date>2002</date>
   <coverpage>
    <image l:href="#img_0.jpeg"/></coverpage>
   <lang>ru</lang>
  </title-info>
  <document-info>
   <author>
    <nickname>honorato bonafe</nickname>
   </author>
   <program-used>ExportToFB21, FictionBook Editor Release 2.6</program-used>
   <date value="2012-04-25">25.04.2012</date>
   <id>OOoFBTools-2012-4-25-9-4-34-661</id>
   <version>1.0</version>
   <history>
    <p>1.0 djvu-&gt;fb2</p>
   </history>
  </document-info>
  <publish-info>
   <book-name>Технология XSLT</book-name>
   <publisher>БХВ-Петербург</publisher>
   <city>Санкт-Петербург</city>
   <year>2002</year>
   <sequence name="Мастер"/>
  </publish-info>
 </description>
 <body>
  <title>
   <p>Технология XSLT</p>
  </title>
  <epigraph>
   <p>Посвящается моей жене</p>
  </epigraph>
  <section>
   <title>
    <p>Предисловие</p>
   </title>
   <section>
    <title>
     <p>О чем эта книга?</p>
    </title>
    <p>Сложно переоценить влияние, которое за последнюю пару-тройку лет оказало на информационные технологии появление и распространение расширяемого языка разметки XML (от англ. extensible Markup Language). XML-технологии нашли применение во множестве областей и стали незаменимыми инструментами для многих решений.</p>
    <p>Вместе с тем, сам язык XML — это не более чем текстовый формат представления данных. XML не имеет особого смысла вне практических приложений и сила XML — прежде всего в прикладных технологиях, которые связаны с этим языком.</p>
    <p>Эта книга посвящена одной из таких технологий, языку XSLT. XSLT — это расширяемый язык стилей для преобразований (от англ. extensible Stylesheet Language for Transformations), который используется для описания преобразований структуры документов. XSLT позволяет трансформировать одни документы в другие, пользуясь простыми наборами правил преобразования.</p>
    <p>Одной из сильнейших сторон языка XML является возможность отделять данные от их представления, хранить информацию в простом и понятном формате, стандарт которого четко оговорен. Такой подход имеет целый ряд достоинств: универсальность решений, снижение времени и стоимости разработки систем, широкие возможности по интеграции и обмену данными, многоцелевое использование информации и тому подобное.</p>
    <p>Перечисляя преимущества этого метода, не следует забывать и о самом представлении, реализация которого, как правило, является довольно сложным делом. Например, в классических Web-решениях для визуализации информации, хранящейся в базе данных, применяется множество непростых технологий и языков программирования.</p>
    <p>Другая распространенная проблема, которая часто сопутствует использованию языка XML, является проблема несоответствия логических схем. Поскольку при создании XML-документов автор может изобрести свой собственный язык разметки, рано или поздно возникает ситуация, когда одни и те же данные описываются разными языками. Соответственно, эти разные логические схемы нужно каким-то образом приводить к общему знаменателю.</p>
    <p>Заметим, что эти две разные на первый взгляд задачи — представление данных и конвертация ХМL-документов различных логических схем — имеют общий корень. В обоих случаях для достижения результата документы должны быть <emphasis>преобразованы</emphasis>. В первом случае из исходного документа нужно получить документ, который может быть визуализирован (например — сгенерировать HTML). Во втором случае один из документов должен быть преобразован так, чтобы его схема соответствовала схеме другого документа.</p>
    <p>Вместе с тем, преобразование древовидно структурированных XML-документов при помощи обычных языков программирования (таких, например, как Java, С или Pascal) является очень трудоемкой задачей. Такие программы громоздки, сложны и дорогостоящи в поддержке, поскольку они крайне чувствительны к малейшим изменениям в формате преобразуемого документа.</p>
    <p>Для того чтобы просто, удобно и эффективно решить описанные выше проблемы и был создан расширяемый язык стилей для преобразований — XSLT. XSLT представляет собой мощную прикладную XML-технологию, которая может применяться везде, где есть два документа разной структуры. XSLT предоставляет высокоуровневые средства для манипуляции данными, которые хранятся в виде XML. Хотя XSLT не позиционируется, как язык запросов для XML, можно смело сравнить его с языком SQL, в котором определяются запросы к реляционным базам данных.</p>
    <p>В этой книге XSLT рассматривается совместно с языком XPath (от англ. XML Path Language — язык путей в XML-документах), который используется для обращения к частям XML-документов. XPath играет в XSLT крайне важную роль, предоставляя средства для вычисления выражений на XML-документах, но кроме XSLT он используется в таких XML-технологиях, как XPointer и XQuery.</p>
    <p>Использование XSLT позволяет сделать разработку преобразований действительно несложным занятием. Преобразования в XSLT — это не более чем наборы правил вида "если обнаружен узел определенного типа, то выполнить следующие действия". Во многих случаях преобразования, для записи которых понадобилась бы не одна страница на процедурном языке программирования, определяются в XSLT буквально в трех строчках.</p>
    <p>Естественно, столь простой язык (а XSLT, безусловно, несложный язык как в изучении, так и в использовании) имеет свои границы. Встречаются задачи, решения которых с помощью XSLT либо не существуют вообще, либо они неудобны. В этих случаях можно прибегнуть к расширениям языка, которые позволяют использовать в XSLT-преобразованиях подпрограммы, написанные на более традиционных языках программирования, например — Java или С++.</p>
    <p>Все это делает XSLT простым, понятным, удобным, но при этом чрезвычайно мощным и гибким языком. Ко всему этому автору хотелось бы добавить то субъективное мнение, что работать с XSLT просто интересно. Во многих случаях люди, столкнувшиеся с XSLT, становились энтузиастами и профессионалами этого языка.</p>
    <p>Таким образом, на вопрос "о чем эта книга?" можно ответить так: она написана о прикладных XML-технологиях преобразования, которые призваны облегчить использование структурированных данных в пользовательских приложениях, открывая новые возможности проектам самого различного масштаба. Изучая языки XSLT и XPath, мы на примерах увидим, как заставить XML-технологии работать — просто, удобно и эффективно.</p>
   </section>
   <section>
    <title>
     <p>Для кого эта книга?</p>
    </title>
    <p>Эта книга адресована всем разработчикам программного обеспечения, которые используют или собираются использовать в своей работе XML, Web-программистам и Web-дизайнерам, создающим технологичные Web-сайты, а также всем, кто интересуется языком XML и прикладными XML-технологиями.</p>
    <p>Поскольку XSLT и XPath являются уникальными языками, мало похожими на что-либо еще, знание других языков программирования для их изучения, в принципе, не обязательно, однако знакомство с основами алгоритмизации и базовыми концепциями программирования, конечно же, приветствуется.</p>
    <p>Из обычных языков программирования XSLT ближе всего к декларативным языкам типа Lisp и Prolog. Как показывает практика, разработчики, имеющие опыт функционального программирования, вникают в тонкости XSLT немного быстрее остальных. Но это ни в коем случае не означает, что XSLT — сложный язык, доступный лишь избранным, совсем нет. Скорее даже наоборот: XSLT — это простой и понятный язык, работать с которым очень легко и интересно.</p>
    <p>Многие из приводимых примеров будут ориентированы на web-решения — в этих случаях хорошую службу может сослужить знание основ web- технологий и языка HTML в частности.</p>
    <p>Одна из глав посвящена вопросам использования XSLT совместно с другими языками программирования. Эта информация будет полезна читателям, работающим с такими языками программирования, как Object Pascal, С или С++, Java, JavaScript, VBScript, Python и PL/SQL.</p>
    <p>В десятой главе рассматриваются основные принципы создания расширений языка XSLT. Основным языком для создания расширений является Java, потому желательно иметь представление о программировании на этом языке.</p>
   </section>
   <section>
    <title>
     <p>Как работать с книгой?</p>
    </title>
    <p>Книга одновременно является практическим руководством, созданным в помощь изучающим языки XSLT и XPath, и справочником, в котором изложены и подкреплены примерами многие особенности и нюансы этих языков.</p>
    <p>Сложность материала книги скомпонована по нарастающей. Повествование начинается с разбора основных идей, стоящих за XML и XSLT, продолжается рассказом об архитектуре и элементах преобразований и заканчивается такими чисто практическими аспектами, как использование XSLT в других языках, создание расширений и решение основных классов задач.</p>
    <p>Как и любая другая книга по программированию, эта книга не может обойтись без множества примеров, которые сопровождают текст, иллюстрируя и поясняя практический смысл сказанного. Пожалуй, будет очень полезно загрузить файлы примеров по адресу <strong>http://xpath.info</strong> и самостоятельно их опробовать.</p>
    <p><emphasis>Приложение 1</emphasis> содержит обзор наиболее популярных XSLT-процессоров с подробным перечислением их характеристик. Этот раздел ориентирован, прежде всего, на читателя, который оказался перед выбором процессора для практического применения. Однако, для того чтобы изучать XSLT и выполнять приведенные в книге примеры, мы настоятельно рекомендуем процессор Saxon и его облегченную версию для Windows — Instant Saxon.</p>
    <p>Причин тому несколько. Прежде всего, этот процессор, пожалуй, является наиболее стандартным в том смысле, что его поведение с точки зрения спецификации языка является практически идеальным. Вторая причина — переносимость. Поскольку Saxon написан на Java, работает он на любых Java- совместимых платформах. Наконец, Saxon почти идеален с точки зрения расширяемости.</p>
    <p>Загрузить Saxon можно по адресу <strong>http://saxon.sourceforge.net</strong>. Пользователям Windows мы рекомендуем воспользоваться версией Instant Saxon, архив которой состоит из единственного файла <code>saxon.exe</code>. Для того чтобы выполнить пример при помощи Instant Saxon, следует запустить команду:</p>
    <p><code>saxon -о result.xml source.xml stylesheet.xsl</code>,</p>
    <p>где <code>result.xml</code> — имя выходящего документа, <code>source.xml</code> — имя входящего документа, a <code>stylesheet.xsl</code> — имя файла преобразования.</p>
    <p>Справочная информация книги сосредоточена в развернутом виде в <emphasis>главах 6</emphasis>, <emphasis>7</emphasis> и <emphasis>8</emphasis>, а также в краткой форме в <emphasis>приложениях 2</emphasis> и <emphasis>3</emphasis>. Книга также содержит подробный глоссарий.</p>
   </section>
   <section>
    <title>
     <p>Структура книги</p>
    </title>
    <section>
     <p>Книга состоит из двенадцати глав и четырех приложений, содержание которых мы кратко опишем ниже.</p>
    </section>
    <section>
     <title>
      <p>Глава 1. Введение в XML</p>
     </title>
     <p>Первая глава книги об XSLT не случайно посвящена языку XML (от англ. extensible Markup Language — расширяемый язык разметки). XML — это фундаментальная концепция, по отношению к которой XSLT является прикладной технологией и поэтому для эффективного применения XSLT нужно хорошо понимать основы XML.</p>
     <p>Мы разделяем мнение множества экспертов о том, что лучшая документация по XML — это спецификация языка, снабженная внятными аннотациями, комментариями и примерами. Первая глава описывает синтаксис и конструкции языка XML именно в том виде, в каком они приведены в технической рекомендации Консорциума W3, акцентируя внимание на важных с точки зрения XSLT моментах.</p>
     <p>Помимо синтаксиса и физической модели ХМL-документа, в первой главе раскрывается концепция XML, идея, которая за всем этим стоит. Краткий обзор практических аспектов использования XML подкреплен описаниями архитектуры типовых проектов, основанных на XML-технологиях.</p>
     <p>Завершающая часть первой главы посвящена истории языка XML.</p>
    </section>
    <section>
     <title>
      <p>Глава 2. Введение в XSLT</p>
     </title>
     <p>Вторая глава содержит базовую информацию о языке XSLT. В ней поясняется потребность в преобразованиях структурированных документов, описывается архитектура преобразований, синтаксические и семантические особенности XSLT как языка.</p>
     <p>Особое внимание уделяется практическому использованию XSLT в составе информационных систем. Во второй главе рассматриваются наиболее естественные области применения технологии XSLT.</p>
     <p>Глава заканчивается краткой справкой об истории языка XSLT.</p>
    </section>
    <section>
     <title>
      <p>Глава 3. Идея и модель языка XSLT</p>
     </title>
     <p>Третья глава посвящена моделям, которые используются в языке XSLT. В ней рассматривается древовидная модель XML-документа, модель данных, используемая в языках XSLT и XPath, переменные, выражения, а также модель самого процесса преобразования. Можно сказать, что третья глава представляет взгляд на XSLT "изнутри". Эта информация важна для понимания того, как работают преобразования и <emphasis>почему</emphasis> это работает именно так.</p>
    </section>
    <section>
     <title>
      <p>Глава 4. Структура преобразования</p>
     </title>
     <p>Четвертая глава рассказывает о том, что представляет собой программа на языке XSLT, как она строится и из каких частей состоит. Кроме этого, рассматривается упрощенная форма преобразований, модульная организация преобразований и способы объединения преобразования и преобразуемого документа. В четвертой главе также освещаются такие чисто практические аспекты, как литеральные элементы результата и шаблоны значений атрибутов.</p>
    </section>
    <section>
     <title>
      <p>Глава 5. Шаблонные правила</p>
     </title>
     <p>В пятой главе рассматриваются основные структурные единицы преобразования, называемые шаблонными правилами, а также множество особенностей их использования: способы вызова, режимы выполнения, типы, приоритет, конфликты и так далее. Дополнительно разбирается использование в шаблонах переменных и параметров.</p>
    </section>
    <section>
     <title>
      <p>Глава 6. XPath-выражения</p>
     </title>
     <p>Шестая глава посвящена языку XPath, который используется в XSLT для выборок и вычислений на ХМL-документах. В этой главе рассматривается синтаксис и семантика XPath-выражений и паттернов XSLT и детально описываются функции базовой библиотеки XPath.</p>
    </section>
    <section>
     <title>
      <p>Глава 7. Основные элементы XSLT</p>
     </title>
     <p>В этой главе описываются основные элементы XSLT — элементы, которые непосредственно создают части выходящего документа, вычисляют выражения, производят копирование, обеспечивают условную и циклическую обработку. Основные элементы предоставляют "базовый набор услуг", без которых, как правило, не обходится ни одно преобразование.</p>
    </section>
    <section>
     <title>
      <p>Глава 8. Дополнительные элементы и функции языка XSLT</p>
     </title>
     <p>В восьмой главе разбираются возможности, которые предоставляются дополнительными элементами и функциями языка XSLT. Эти элементы и функции предоставляют сервисные возможности, которые не связаны непосредственно с созданием выходящего документа, но имеют значение для построения сложных преобразований. К этим возможностям относятся создание и обработка ключей, манипуляции с пробельным пространством, обращение ко внешним XML-документам, сортировка и многое другое.</p>
    </section>
    <section>
     <title>
      <p>Глава 9. Использование XSLT совместно с другими языками программирования</p>
     </title>
     <p>Эта глава поможет сделать первые шаги разработчикам, которым необходимо использовать XSLT совместно с другими языками программирования. В ней приведены простые примеры вызова преобразований из программ на таких языках программирования, как Object Pascal, C/C++, VBScript, JavaScript, Java и некоторых других.</p>
    </section>
    <section>
     <title>
      <p>Глава 10. Расширения языка XSLT</p>
     </title>
     <p>Десятая глава посвящена вопросам создания и использования функций и элементов расширения. В этой главе разбирается процесс написания и подключения функций и элементов расширения на примере интерфейсов таких процессоров, как Saxon, Xalan и Oracle XSLT Processor, а также вопросы, связанные с обеспечением переносимости и отработкой исключительных ситуаций в преобразованиях, использующих расширения.</p>
    </section>
    <section>
     <title>
      <p>Глава 11. Готовые решения</p>
     </title>
     <p>Одиннадцатая глава написана для тех, кто не любит изобретать лишний раз велосипед. В ней описываются решения некоторых наиболее распространенных проблем, как-то: группировка, циклические и рекурсивные вычисления, операции над множествами и так далее.</p>
    </section>
    <section>
     <title>
      <p>Глава 12. Развитие технологий</p>
     </title>
     <p>Последняя глава книги позволяет забежать немного вперед и предугадать, что будет с языком XSLT в следующих его версиях. Выводы, которые делаются в этой главе, основаны на изменениях, предложенных в черновой версии XSLT 1.1, а также на требованиях, которые были сформированы ко второй версии языка. Анализ этой информации в будущем позволит безболезненно перейти на новую версию XSLT.</p>
    </section>
    <section>
     <title>
      <p>Приложение 1. Обзор XSLT-процессоров</p>
     </title>
     <p>В первом приложении произведен обзор наиболее распространенных XSLT- процессоров с тем, чтобы помочь читателю выбрать наиболее подходящий инструмент. Помимо этого, в начале приложения приводятся статистические сведения о производительности и популярности различных XSLT-процессоров.</p>
    </section>
    <section>
     <title>
      <p>Приложение 2. Краткий справочник элементов и атрибутов XSLT</p>
     </title>
     <p>Второе приложение содержит справочную информацию об элементах и атрибутах языка XSLT. В одну таблицу сведены синтаксис элементов и атрибутов и краткое описание их семантики.</p>
    </section>
    <section>
     <title>
      <p>Приложение 3. Краткий справочник функций XSLT и XPath</p>
     </title>
     <p>Третье приложение содержит справочную информацию о функциях базовой библиотеки языка XPath и функциях языка XSLT, которые дополняют эту библиотеку.</p>
    </section>
    <section>
     <title>
      <p>Приложение 4. Интернет-ресурсы, посвященные XSLT</p>
     </title>
     <p>В четвертом приложении приведен небольшой список полезных интернет-ресурсов, так или иначе связанных с XSLT. Сюда относятся списки часто задаваемых вопросов, уроки по XSLT, архивы библиотек и инструментов, официальные спецификации Консорциума W3 и так далее.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Соглашения</p>
    </title>
    <section>
     <title>
      <p>Расширенная форма Бэкуса-Наура</p>
     </title>
     <p>Несмотря на то, что эта книга главным образом посвящена языку XSLT, в ней также описываются расширяемый язык разметки XML и язык обращения к частям ХМL-документов, называемый XPath. Подробное и точное описание этих языков невозможно без четких определений синтаксических конструкций.</p>
     <p>Для описания синтаксиса рассматриваемых языков мы будем использовать расширенные формы Бэкуса-Наура (РФБН, или, по-английски, Extended Backus-Naur Form, EBNF). EBNF — это современная модификация методологии, которая впервые была использована для описания языка программирования Алгол-60. За прошедшие десятилетия формы Бэкуса-Наура были доработаны множеством авторов и сейчас в расширенном виде используются для описания ряда языков программирования различной степени сложности. EBNF-нотация также широко используется в технических рекомендациях Консорциума W3, которые фактически и являются стандартами рассматриваемых нами языков.</p>
     <p>Нотация EBNF определяет язык как набор синтаксических правил, определяющих нетерминалы (конструкции языка) через терминалы (символы языка), а также другие нетерминалы. Правило состоит из двух частей, разделенных символами "<code>::=</code>":</p>
     <p><code><emphasis>конструкция</emphasis> ::= <emphasis>определение конструкции</emphasis></code></p>
     <p>В левой части правила стоит терминал определяемой конструкции, в правой — выражение, определяющее эту конструкцию. Правила EBNF также иногда называют продукциями, и мы тоже часто будем использовать этот термин, чтобы не путать эти правила с шаблонными правилами преобразований, которые главным образом и составляют преобразования в языке XSLT.</p>
     <p>Терминалы, которые могут быть как отдельными символами, так и их последовательностями, определяются в нотации EBNF следующим образом:</p>
     <p>&#9633; <code>#x<emphasis>N</emphasis></code>, где <code><emphasis>N</emphasis></code> — шестнадцатеричный код, соответствует символу Unicode с кодом <code><emphasis>N</emphasis></code>. Например, <code>#х410</code> соответствует символу <code>А</code> кириллического алфавита (<emphasis>см. раздел "Использование Unicode" главы 1</emphasis>).</p>
     <p>&#9633; <code>[a-zA-z]</code>, <code>[#x<emphasis>N</emphasis>-#x<emphasis>N</emphasis>]</code> — соответствует символу указанного интервала. К примеру, <code>[a-f]</code> соответствует любому из символов <code>а</code>, <code>b</code>, <code>с</code>, <code>d</code>, <code>e</code>, <code>f</code>.</p>
     <p>&#9633; <code>[abc]</code>, <code>[#x<emphasis>N</emphasis>#x<emphasis>N</emphasis>#x<emphasis>N</emphasis>]</code> — соответствует любому из перечисленных символов. Например, <code>[#х410#х411#х412]</code> соответствует любому из символов <code>А</code>, <code>Б</code>, <code>В</code>. Символьные интервалы и перечисления могут использоваться совместно в одних квадратных скобках.</p>
     <p>&#9633; <code>[^a-z]</code>, <code>[^#х<emphasis>N</emphasis>-#x<emphasis>N</emphasis>]</code> — соответствует любому символу, кроме символов указанного интервала. К примеру, <code>[^#х410-#x42F]</code> соответствует любому символу, кроме заглавных букв русского алфавита.</p>
     <p>&#9633; <code>[^abc]</code>, <code>[^#x<emphasis>N</emphasis>#x<emphasis>N</emphasis>#x<emphasis>N</emphasis>]</code> — соответствует любому, кроме перечисленных символов. Например, <code>[^xyz]</code> соответствует любому символу, кроме символов <code>x</code>, <code>y</code> и <code>z</code>. Аналогично разрешенным интервалам и последовательностям символов, запрещенные интервалы и последовательности также могут использоваться совместно.</p>
     <p>&#9633; <code>"строка"</code> — соответствует строке, которая приведена в двойных кавычках. Например, <code>"stylesheet"</code> соответствует строке <code>stylesheet</code>.</p>
     <p>&#9633; <code>'строка'</code> — соответствует строке, которая приведена в одинарных кавычках. Например, <code>'template'</code> соответствует строке <code>template</code>.</p>
     <p>Терминалы могут использоваться совместно с нетерминальными конструкциями в более сложных выражениях.</p>
     <p>&#9633; <code>A?</code> означает, что выражение <code>A</code> необязательно и может быть пропущено.</p>
     <p>&#9633; <code>A | B</code> соответствует либо выражению <code>A</code>, либо выражению <code>B</code>, но не им обоим одновременно (строгое "или"). Выражения такого вида называют иначе <emphasis>выбором</emphasis>.</p>
     <p>&#9633; <code>A B</code> означает, что за выражением <code>A</code> следует выражение <code>B</code>. Последовательность имеет приоритет по сравнению с выбором — <code>A B | C D</code> означает последовательность выражений <code>A</code> и <code>B</code> или последовательность выражений <code>C</code> и <code>D</code>.</p>
     <p>&#9633; <code>A - B</code> соответствует строке, которая соответствует выражению <code>A</code>, но не выражению <code>B</code>.</p>
     <p>&#9633; <code>A+</code> означает последовательность из одного или более выражения <code>A</code>. Оператор "<code>+</code>" в EBNF старше оператора выбора, <code>A+ | B+</code> означает последовательность из одного или более выражения <code>A</code> или последовательность из одного или более выражения <code>B</code>.</p>
     <p>&#9633; <code>A*</code> означает последовательность из нуля или более выражений <code>A</code>. Аналогично оператору "<code>+</code>", оператор "<code>*</code>" старше оператора выбора</p>
     <p>&#9633; <code>(<emphasis>выражение</emphasis>)</code> — круглые скобки используются для группировки выражений. Выражения, заключенные в скобки, рассматриваются, как отдельная единица, которая может быть свободно использована в приведенных выше конструкциях. Например, выражение <code>A B C | B C | A D C | D C | C</code> можно переписать в виде <code>(A? (B | D) ) C</code>.</p>
     <p>Нотация расширенных форм Бэкуса-Наура может с первого взгляда показаться очень сложной, однако, на самом деле это не так. Достаточно разобрать несколько примеров, как все встанет на свои места.</p>
     <subtitle>Пример</subtitle>
     <p>Рассмотрим реальную продукцию <code>Digits</code> языка XPath. <code>Digits</code> — это последовательность из нескольких цифр от <code>0</code> до <code>9</code> и определяется она следующим образом:</p>
     <p><code>Digits ::= [0-9] +</code></p>
     <p>Как правило, продукции в спецификациях языков пронумерованы для того, чтобы было легче на них ссылаться. Мы будем по возможности приводить эти номера так, как они указаны в технических рекомендациях — в квадратных скобках, например:</p>
     <p><code>[31] Digits ::= [0-9]+</code></p>
     <p>При помощи продукции Digits определяется такая продукция, как Number, которая соответствует числу. Число — это последовательность цифр, разделенная точкой на целую и дробную части:</p>
     <p><code>[30] Number ::= Digits ('.' Digits?)?</code></p>
     <p><code>                | '.' Digits</code></p>
     <p>Чтобы лучше понять EBNF, попробуем немного упростить эту продукцию. Выражение <code>Digits?</code> внутри круглых скобок означает, что <code>Digits</code> может как присутствовать, так и быть опущенным, то есть <code>('.' Digits?) ?</code> равносильно <code>'.' ? | ('.' Digits)?</code>. Повторяя еще раз подобное упрощение с каждым из полученных выражений, в итоге преобразуем правило <code>Number</code> к виду:</p>
     <p><code>Number ::= Digits</code></p>
     <p><code>           | Digits '.' Digits</code></p>
     <p><code>           | Digits '.'</code></p>
     <p><code>           | '.' Digits</code></p>
     <p>Следовательно, число имеет четыре варианта синтаксиса:</p>
     <p>&#9633; последовательность цифр, например <code>12345</code>;</p>
     <p>&#9633; последовательность цифр, разделенная точкой на целую и дробную части, например <code>3.14</code>;</p>
     <p>&#9633; последовательность цифр, заканчивающаяся точкой, например <code>6.</code> — что эквивалентно <code>6.0</code>;</p>
     <p>&#9633; последовательность цифр, начинающаяся точкой, например <code>.5</code>, что эквивалентно <code>0.5</code>.</p>
     <p>Разберем еще одну продукцию языка XPath — определение <emphasis>литерала</emphasis>. Литерал в XPath — это последовательность символов, заключаемая в одинарные или двойные кавычки, которая используется в качестве строкового параметра в функциях и т.д. Единственным и вполне логичным ограничением на синтаксис литерала является то, что он не может содержать символ собственных кавычек — в этом случае непонятно, где же на самом деле литерал кончается, а где начинается (например, <code>'ab'cd'</code>).</p>
     <p>Конструкция <code>Literal</code> задается следующим образом:</p>
     <p><code>[29] Literal ::= '"' [^"]* '"'</code></p>
     <p><code>                 | "'" [^']* "'"</code></p>
     <p>В первом случае синтаксис литерала начинается двойными кавычками (<code>'"'</code>), затем идет последовательность, состоящая из любых символов, кроме двойных кавычек (<code>[^"]*</code>), затем закрывающие двойные кавычки (<code>'"'</code>). Во втором случае синтаксис имеет точно такой же вид с точностью до замены одинарных кавычек двойными и наоборот.</p>
     <p>Другим очень часто используемым правилом является правило, определяющее пробельное пространство (англ. space или whitespace). Пробельными символами в XML-языках считаются такие символы, как табуляция, перевод строки, возврат каретки и сам пробел. Продукция <code>S</code> пробельного пространства задается, как последовательность из одного или более пробельного символа:</p>
     <p><code>[3] S ::= (#х20 | #х9 | #xD | #хА)+</code></p>
     <p>Как правило, EBNF-продукции языков XML-группы составлены довольно просто, но в некоторых случаях они разбиты на несколько правил, которые определены в разных частях спецификации. В таких случаях мы будем по возможности упрощать продукции, записывая их в раскрытом виде.</p>
    </section>
    <section>
     <title>
      <p>Обозначения</p>
     </title>
     <p>Для того чтобы текст книги был более понятен, мы будем использовать некоторые соглашения.</p>
     <p>Прежде всего, код программ и текст XML-документов будет выделяться моноширинным шрифтом <code>Courier</code>. Листингам многих примеров будут предшествовать заголовки вида</p>
     <subtitle>Листинг 2.1. Входящий документ</subtitle>
     <p><code>&lt;!-- Текст входящего документа --&gt;</code></p>
     <p>Для того чтобы текст XML-документов был более наглядным, в листингах он будет форматироваться с пробельными отступами, например:</p>
     <p><code>&lt;foo bar="1"&gt;</code></p>
     <p><code> &lt;FOO/&gt;</code></p>
     <p><code>&lt;/foo&gt;</code></p>
     <p>Еще раз повторим, что это форматирование применяется только в целях наглядности исходного кода, когда это не противоречит смыслу документа. В предыдущем случае документ на самом деле мог выглядеть как:</p>
     <p><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;foo bar="1"&gt;&lt;FOO&gt;&lt;/foo&gt;</code></p>
     <p>В тех случаях, когда позиции пробельных символов документа важны для повествования, они будут особым образом выделяться. Для обозначения пробела мы будем использовать символ "<code>&#9633;</code>", а для обозначения символа переноса строки — символ "<code>¶</code>", например:</p>
     <p><code>&lt;а xmlns:d="urn:d"&gt;¶</code></p>
     <p><code>&#9633;&#9633;&lt;d:b&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;с&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;e&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;/e&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;/с&gt;¶</code></p>
     <p><code>&#9633;&#9633;&lt;/d:b&gt;¶</code></p>
     <p><code>&lt;/а&gt;</code></p>
     <p>Базовые понятия или моменты, на которые следует обратить повышенное внимание, выделяются в тексте <emphasis>курсивом</emphasis>. Иностранные аббревиатуры и термины расшифровываются и переводятся в скобках, например: XSLT (от англ. extensible Stylesheet Language for Transformations — расширяемый язык стилей для преобразований). Ссылки на другие книги берутся в квадратные скобки с указанием года издания, например, [Кнут 2001]. Более точные библиографические данные можно найти в списке литературы.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Благодарности</p>
    </title>
    <p>Прежде всего, хотелось бы выразить признательность группе Систем Баз Данных (DBS) Исследовательского Центра Информатики (Forschungszentrum Informatik, FZI) при университете г. Карлсруэ, где мне посчастливилось работать. Эта книга написана главным образом благодаря практическому опыту, полученному во множестве проектов Европейской Комиссии, которыми занимается наш центр.</p>
    <p>Эта книга не состоялась бы без участия Майкла Кея (разработчика XSLT-процессора Saxon и редактора новой версии языка XSLT), Стива Мюнха (руководителя XML-проектов Oracle), Кена Холлмана (Crane Softwrights Ltd.), Олега Ткаченко (MultiConn International Ltd.) и многих других людей, которые советами и конкретными примерами помогали готовить этот непростой материал.</p>
    <p>Отдельной благодарностью хочется упомянуть всех участников конференций <strong>fido7.ru.xml</strong>, <strong>comp.text.xml</strong> и списка рассылки XSL List, которые своими вопросами подсказывали, какие проблемы интересуют XSLT-разработчиков на практике. Большинство примеров, которые приводятся в этой книге, были ответами на вопросы участников конференций.</p>
    <p>Большое спасибо моим научным руководителям — профессору Н.И. Юсуповой и профессору П.X. Локеману, за мудрые слова и внимание, которое они мне уделяли.</p>
    <p>Выражаю признательность также сотрудникам издательства "БХВ-Петербург": Евгению Рыбакову, Анне Кузьминой и Леониду Кочину — за помощь при подготовке книги к печати.</p>
    <p>И, наконец, большое спасибо моей семье и моим добрым друзьям — Юре Лотнику, Антону Кузнецову и Юле Кирилловой за поддержку, которая чувствовалась за несколько тысяч километров.</p>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 1</p>
    <p>Введение в XML</p>
   </title>
   <section>
    <title>
     <p>Что такое XML?</p>
    </title>
    <section>
     <p>За последние несколько десятков лет, прошедших с создания первых электронных устройств, в игру с природой человеком была введена третья сторона — вычислительные машины. Человек постепенно доверил им свою память, переложил на них сложные алгоритмические задачи, вычисления, принятие решений, и вообще все то, с чем плохо справлялся сам в информационном мире.</p>
     <p>Но на всем пути становления информационных систем человек неизбежно сталкивался с одной и той же проблемой — с проблемой понимания. Если два человека, говорящие на разных языках, попробуют объяснить что- нибудь друг другу, то это легко может получиться, когда проблема проста, например, "как пройти к большому зданию с куполом наверху?". Однако же, в случае, если объяснить нужно что-нибудь более сложное, то, не зная языка собеседника, сделать это будет очень трудно.</p>
     <p>Проблема понимания между человеком и машиной усугубляется еще и тем, что машина — это цифровое устройство, и все данные в ней состоят из атомов информации — битов, принимающих только два значения — "0" (что иногда понимается, как "нет" или "ложь") и "1" ("да", "истина"). Изначально цифровые устройства вообще использовались только для решения математических задач — расчета баллистики, шифрации и тому подобного.</p>
     <p>Для машинной записи естественных языков люди ставили в соответствие символам числа, организуя, таким образом, текстовую информацию в машинном представлении. Это был первый шаг на пути взаимопонимания между машинами и человеком — отпала необходимость писать программы в двоичных кодах. В течение короткого времени было создано множество языков программирования, одновременно понятных как человеку, поскольку они использовали синтаксические конструкции естественных языков, так и машине, потому как могли быть переведены (транслированы) в машинные коды.</p>
     <p>Затем произошел взрыв. Программирование, которое во времена машинных кодов было уделом энтузиастов, стало массовым, идеи и вложения полились рекой, и дальнейшее развитие информационных технологий можно сравнить с распространением ударной волны.</p>
     <p>В жизни современного общества сложно переоценить эффект, произведенный появлением и повсеместным распространением нового глобального пространства обмена информации — сетью Интернет. То, что начиналось как военная разработка для доставки электронных сообщений и депеш, вылилось в новое информационное измерение пространства, не знающее географических границ. Интернет позволил обмениваться информацией в электронном виде, объемы которой к тому времени уже были огромны.</p>
     <p>Однако, Интернет, в свою очередь, возродил старую проблему понимания — вопрос "как ты поймешь то, что я тебе скажу?" был заменен проблемой "как система В сможет переработать информацию, которую предоставит ей система A?". Пытаясь ответить на это, люди стали создавать стандарты и протоколы, которые позволили бы системам общаться на одних языках. Вместе с тем, по мере глобализации Интернета и увеличения числа систем, обменивающихся информацией (от рабочих станций обычных пользователей — до суперсерверов с огромными базами данных), объем информации, требовавшей стандартного выражения, прогрессировал экспоненциально.</p>
     <p>Расширяемый язык разметки XML (extensible Mark-up Language) — это результат довольно успешной попытки создать язык для текстового выражения структурированной информации в стандартном виде. XML — это метаязык в том смысле, что сам по себе он не имеет операторов, не определяет никакую алгоритмическую последовательность действий и не выполняет никаких вычислений, его цель — описывать новые языки документов.</p>
    </section>
    <section>
     <title>
      <p>Разметка документов</p>
     </title>
     <p>Идею разметки документов будет проще всего проиллюстрировать на примере. Представим себе следующий рекламный текст:</p>
     <p><code>Предлагаем Вашему вниманию новый 3-х камерный холодильник "Горск" объемом 250 л. и стоимостью всего 4500 рублей! Новый дизайн, быстрое охлаждение и низкое энергопотребление, 3-х годовая гарантия на все узлы и агрегаты, а также бесплатная доставка по городу! Заказывайте прямо сейчас по телефону 091-12-15. Фирма "Горск-Холод".</code></p>
     <p>Размещая это объявление где-нибудь на Web-сайте, нам может понадобиться выделить некоторые части, чтобы получить представление вида:</p>
     <p><code>Предлагаем Вашему вниманию новый 3-х камерный холодильник <strong>"Горск"</strong> объемом 250 л. и стоимостью всего <strong>4500</strong> рублей! Новый дизайн, <emphasis>быстрое охлаждение и низкое энергопотребление</emphasis>, <strong>3-х годовая гарантия</strong> на все узлы и агрегаты, а также бесплатная доставка по городу! Заказывайте прямо сейчас по телефону 091-12-15.</code></p>
     <p><code>Фирма "Горск-Холод".</code></p>
     <p>Идея разметки состоит в том, чтобы использовать для выделения частей документа простые текстовые метки, называемые <emphasis>тегами</emphasis>. Теги разграничивают документ, выделяя в нем части и присваивая им некоторые особенности (например, указывая на то, что часть текста надо подчеркнуть).</p>
     <p>Простым примером языка разметки является уже, скорее всего, знакомый читателю HTML — язык разметки гипертекста. В HTML задан набор тегов для визуального форматирования документа, например:</p>
     <p>&#9633; <code>&lt;P&gt;<emphasis>содержимое</emphasis>&lt;/P&gt;</code> — выделяет содержимое, как параграф;</p>
     <p>&#9633; <code>&lt;BR&gt;</code> — задает перенос строки;</p>
     <p>&#9633; <code>&lt;B&gt;<emphasis>содержимое</emphasis>&lt;/B&gt;</code> — выделяет содержимое полужирным шрифтом;</p>
     <p>&#9633; <code>&lt;I&gt;<emphasis>содержимое</emphasis>&lt;/I&gt;</code> — выделяет содержимое курсивом;</p>
     <p>&#9633; <code>&lt;U&gt;<emphasis>содержимое</emphasis>&lt;/U&gt;</code> — подчеркивает содержимое.</p>
     <p>Теги могут быть <emphasis>парными</emphasis> и <emphasis>одиночными</emphasis>. Парные теги (например, <code>&lt;B&gt;<emphasis>содержимое</emphasis>&lt;/B&gt;</code>) выделяют часть документа, одиночные (например, <code>&lt;BR&gt;</code>) задают некую инструкцию.</p>
     <p>В предыдущем примере текст может быть размечен следующим образом.</p>
     <subtitle>Листинг 1.1. HTML-разметка рекламного объявления</subtitle>
     <p><code>&lt;Р&gt;Предлагаем Вашему вниманию новый 3-х камерный холодильник &lt;В&gt;"Горск"&lt;/В&gt; объемом 250 л. и стоимостью всего &lt;В&gt;4500&lt;/В&gt; рублей! Новый дизайн, &lt;I&gt;быстрое охлаждение&lt;/I&gt; и &lt;I&gt;низкое энергопотребление&lt;/I&gt;, &lt;В&gt;3-х годовая гарантия&lt;/В&gt; на все узлы и агрегаты, а также &lt;I&gt;бесплатная доставка по городу&lt;/I&gt;! Заказывайте прямо сейчас по телефону &lt;U&gt;091-12- 15&lt;U&gt;. &lt;BR&gt;&lt;BR&gt;Фирма "Горск-Холод".&lt;/Р&gt;</code></p>
     <p>Теперь этот документ несет в себе не только данные о коммерческом предложении, но и примитивную информацию о том, как он должен выглядеть визуально. Это делает документ более понятным, но понятным для человека, а не для машины. Словосочетания "быстрое охлаждение" и "бесплатная доставка по городу", выделенные в тексте одинаковыми тегами, на самом деле описывают совершенно разные вещи. Первое — свойство продукта, второе — сервис, предоставляемый фирмой. Иначе говоря, одни и те же теги в этом документе имеют разный смысл — один и тот же синтаксис выражает разную семантику.</p>
     <p>Для решения этой проблемы несоответствия, XML предлагает очень простой и весьма эффективный способ — расширить множество используемых тегов так, чтобы они могли полностью выразить всю семантику, которой только может обладать документ. Например.</p>
     <subtitle>Листинг 1.2 XML-разметка рекламного объявления</subtitle>
     <p><code>&lt;advert&gt;</code></p>
     <p><code> Предлагаем Вашему вниманию новый &lt;room&gt;3&lt;/room&gt;-x камерный</code></p>
     <p><code> &lt;product&gt;холодильник&lt;/product&gt; &lt;product-title&gt;"Горск"&lt;/product-title&gt;</code></p>
     <p><code> объемом &lt;volume&gt;250 л.&lt;/volume&gt; и стоимостью всего &lt;price&gt;4500&lt;/price&gt;</code></p>
     <p><code> рублей!</code></p>
     <p><code> Новый дизайн, &lt;feature&gt;быстрое охлаждение&lt;/feature&gt; и</code></p>
     <p><code> &lt;feature&gt;низкое энергопотребление&lt;/feature&gt;,</code></p>
     <p><code> &lt;guarantee&gt;3-x годовая гарантия&lt;/guarantee&gt; на все узлы и агрегаты, а</code></p>
     <p><code> также &lt;service&gt;бесплатная доставка по городу&lt;/service&gt;!</code></p>
     <p><code> &lt;order&gt;</code></p>
     <p><code>  Заказывайте прямо сейчас по телефону &lt;phone&gt;0-91-12-15&lt;/phone&gt;.</code></p>
     <p><code> &lt;/order&gt;</code></p>
     <p><code> &lt;company&gt;Фирма "Горск-Холод".&lt;/company&gt;</code></p>
     <p><code>&lt;/advert&gt;</code></p>
     <p>В таком виде этот документ содержит гораздо более подробную информацию о своей структуре: внутри тега <code>&lt;product-title&gt;</code> указано наименование продукта, внутри тега <code>&lt;price&gt;</code> — цена, внутри тега <code>&lt;service&gt;</code> — какой сервис предоставляет фирма и так далее. Такой текст уже можно обработать программно. Если понадобится составить таблицу, содержащую названия холодильников, объем, цену, название фирмы и телефон, все, что потребуется сделать — это получить содержимое тегов <code>&lt;product-title&gt;</code>, <code>&lt;volume&gt;</code>, <code>&lt;price&gt;</code>, <code>&lt;company&gt;</code> и <code>&lt;phone&gt;</code>. При этом совершенно не теряется возможность визуального представления документа: нужно лишь определить, как будет выглядеть содержимое того или иного тега.</p>
     <p>Таким образом, просто расширив множество тегов, мы убили сразу двух зайцев.</p>
     <p>&#9633; Явным образом выделили в документе структуру данных. Это делает возможной дальнейшую машинную обработку документа, который при этом все еще остается понятным человеку.</p>
     <p>&#9633; Отделили данные, содержащиеся в документе, от того, каким образом документ будет представлен визуально. Это дает широкие возможности для публикации документов на различных носителях — на бумаге, в Интернет, на мобильных устройствах.</p>
     <p>В этих двух положениях и есть смысл XML (англ. extensible Mark-up Language, расширяемый язык разметки) — отделять данные от представления и создавать в текстовом виде документы со структурой, указанной явным образом.</p>
     <p>Синтаксически в XML, по сравнению с HTML, нет ничего нового. Это такой же текст, размеченный тегами, но с той лишь разницей, что в HTML существует ограниченный набор тегов, которые можно использовать в документах, в то время как XML позволяет создавать и использовать любую разметку, которая только может понадобиться для подробного описания данных.</p>
    </section>
   </section>
   <section>
    <title>
     <p>XML снаружи и изнутри</p>
    </title>
    <section>
     <p>Несомненным достоинством XML является также и то, что это чрезвычайно простой язык. Основных конструкций в XML очень мало, но, несмотря на это, с их помощью можно создавать разметку документов практически любой сложности.</p>
     <p>Для того чтобы познакомиться с устройством XML-документов, рассмотрим простой пример:</p>
     <p><code>&lt;?xml version="1.0"?&gt;</code></p>
     <p><code>&lt;advert&gt;</code></p>
     <p><code> &lt;product title="Слон"&gt;</code></p>
     <p><code>  Покупайте наших слонов!</code></p>
     <p><code> &lt;/product&gt;</code></p>
     <p><code>&lt;/advert&gt;</code></p>
     <p>Первая строка документа определяет его как XML-документ, построенный в соответствии с первой версией языка. Следующая строка содержит открывающий тег <code>&lt;advert&gt;</code>. Далее находится открывающий тег <code>&lt;product&gt;</code>, который имеет атрибут <code>title</code> со значением <code>"Слон"</code>. Четвертая строка в документе — рекламный лозунг <code>"Покупайте наших слонов!"</code>. Затем следует закрывающий тег <code>&lt;/product&gt;</code> и, наконец, закрывающий тег <code>&lt;/advert&gt;</code>.</p>
     <p>XML использует ту же теговую разметку, что и HTML, но при этом теги в XML не просто ограничивают часть текста документа — они выделяют в документе один <emphasis>элемент</emphasis>. В предыдущем примере документ имел два элемента — <code>advert</code>:</p>
     <p><code>&lt;advert&gt;</code></p>
     <p><code> &lt;product title="Слон"&gt;</code></p>
     <p><code>  Покупайте наших слонов!</code></p>
     <p><code> &lt;/product&gt;</code></p>
     <p><code>&lt;/advert&gt;</code></p>
     <p>и <code>product</code>:</p>
     <p><code>&lt;product title="Слон"&gt;</code></p>
     <p><code> Покупайте наших слонов!</code></p>
     <p><code>&lt;/product&gt;</code></p>
     <p>Как видно, элемент <code>product</code> включен в элемент <code>advert</code>. Точно так же, как в HTML одни теги могли находиться внутри других тегов, в XML элементы могут содержать другие элементы, а также иметь атрибуты и содержать текст. В следующем разделе мы подробно рассмотрим основные конструкции XML, которые понадобятся нам в дальнейшем.</p>
    </section>
    <section>
     <title>
      <p>Конструкции XML</p>
     </title>
     <section>
      <p>Помимо элементов, атрибутов и текста, документы могут также содержать другие конструкции, такие как комментарии, инструкции по обработке и секции символьных данных. Эти базовые составляющие используются для того, чтобы гибко, но в четком соответствии со стандартом, размечать документы любой сложности. Далее мы подробно разберем каждую из основных конструкций XML-документа.</p>
     </section>
     <section>
      <title>
       <p>Элемент</p>
      </title>
      <p>Теги в XML-документе не просто размечают текст — они выделяют объект, который и называется <emphasis>элементом</emphasis>. Элементы являются основными структурными единицами XML — именно они иерархически организуют информацию, содержащуюся в документе.</p>
      <p>Элементы могут быть пустыми, то есть не содержать ни данных, ни других конструкций, либо непустыми — включать в себя текст, другие элементы и т.п.</p>
      <p>Пустой элемент имеет следующий вид:</p>
      <p><code>&lt;<emphasis>имя атрибут1</emphasis>="<emphasis>значение1</emphasis>" <emphasis>атрибут2</emphasis>="<emphasis>значение2</emphasis>" <emphasis>и т.д.</emphasis>/&gt;</code></p>
      <subtitle>Примеры</subtitle>
      <p><code>&lt;img src="image.gif"/&gt;</code></p>
      <p><code>&lt;br/&gt;</code></p>
      <p><code>&lt;answer question="To be or not to be?" value="Perhaps"/&gt;</code></p>
      <p>Непустые элементы имеют вид:</p>
      <p><code>&lt;<emphasis>имя атрибут1</emphasis>="<emphasis>значение1</emphasis>" <emphasis>атрибут2</emphasis>="<emphasis>значение2</emphasis>" <emphasis>и т.д.</emphasis>&gt;</code></p>
      <p><code> ...</code></p>
      <p><code><emphasis> содержимое элемента</emphasis></code></p>
      <p><code>...</code></p>
      <p><code> &lt;/<emphasis>имя</emphasis>&gt;</code></p>
      <subtitle>Пример</subtitle>
      <p><code>&lt;myelement myattribute="myvalue"&gt;</code></p>
      <p><code> &lt;mysubnode&gt;</code></p>
      <p><code>  sometext</code></p>
      <p><code> &lt;/mysubnode&gt;</code></p>
      <p><code>&lt;/myelement&gt;</code></p>
      <p>И в том, и в другом случае, имя задает имя элемента, а конструкции вида <code><emphasis>атрибутX</emphasis>="<emphasis>значениеХ</emphasis>"</code> — определяют значения его атрибутов. Имена в XML являются регистро-зависимыми, то есть имена <code>MyElement</code>, <code>myelement</code> и <code>MYELEMENT</code> различаются. Кроме того, имена в XML могут принадлежать различным <emphasis>пространствам имен</emphasis>, о которых мы поговорим чуть позже.</p>
      <p>Элементы являются основной конструкцией языка XML. Организуя содержимое в элементах, можно явно выделить иерархическую структуру документа. Легко заметить, что документ, состоящий из вложенных друг в друга элементов, устроен подобно дереву: родительский элемент является корнем, в то время как дочерние элементы, которые включаются в него, являются ветками, а если они не содержат ничего более, то и листьями. Следующий пример (рис. 1.1) иллюстрирует эту концепцию.</p>
      <image l:href="#img_1.png"/>
      <p><strong>Рис. 1.1</strong>. Документ и соответствующее ему дерево элементов</p>
      <p>Очень важно понять, что XML-документ логически организован в виде дерева. Дерево является довольно простой структурой для обработки, но при этом выразительная сложность его весьма велика. Древовидная структура является одной из наиболее подходящих абстракций для описания объектов и отношений в реальном мире — возможно именно древовидное устройство наряду с простотой использования обеспечили XML такой потрясающий успех.</p>
      <p>Обратимся теперь к синтаксису элементов. EBNF-правило, определяющее элемент, выглядит следующим образом:</p>
      <p><code>[39] element ::= EmptyElemTag</code></p>
      <p><code>                 | STag content ETag</code></p>
      <p>Пустому элементу соответствует нетерминал <code>EmptyElemTag</code>. Непустой элемент начинается открывающим тегом (нетерминал <code>STag</code>), включает некоторое содержимое (<code>content</code>) и заканчивается закрывающим тегом (<code>ETag</code>).</p>
      <p>Открывающий тег состоит из имени (<code>Name</code>) и последовательности определений атрибутов (<code>Attribute</code>), которые разделены пробельными символами:</p>
      <p><code>[40] STag ::= '&lt;' Name (S Attribute)* S? '&gt;'</code></p>
      <p>В ряде случаев атрибуты тега могут отсутствовать.</p>
      <p>Перед закрывающей угловой скобкой тега могут также стоять пробельные символы, поэтому вполне корректной будет следующая запись:</p>
      <p><code>&lt;а</code></p>
      <p><code> href="http://www.xsltdev.ru"</code></p>
      <p><code>&gt;</code></p>
      <p>В закрывающем теге имени предшествует косая черта ("<code>/</code>") и перед закрывающей угловой скобкой тоже могут стоять пробелы:</p>
      <p><code>[42] ETag ::= '&lt;/' Name S? '&gt;'</code></p>
      <p>Имена в открывающем и закрывающем тегах должны совпадать.</p>
      <p>Содержимое элемента может состоять из элементов (нетерминал <code>element</code>), сущностей (<code>Reference</code>), секций символьных данных (<code>CDSect</code>), инструкций по обработке (<code>PI</code>) и комментариев (<code>Comment</code>), перемешанных с символьными данными (<code>CharData</code>):</p>
      <p><code>[43] content ::= CharData?</code></p>
      <p><code>                 ((element</code></p>
      <p><code>                 | Reference</code></p>
      <p><code>                 | CDSect</code></p>
      <p><code>                 | PI</code></p>
      <p><code>                 | Comment) CharData?)*</code></p>
      <p>Пустой элемент не имеет содержимого и задается продукцией <code>EmptyElemTag</code> в следующем виде:</p>
      <p><code>[44] EmptyElemTag ::= '&lt;' Name (S Attribute)* S? '/&gt;'</code></p>
      <p>Тег пустого элемента выглядит точно так же, как и тег непустого элемента с той лишь разницей, что перед закрывающей угловой скобкой стоит символ косой черты ("<code>/</code>"). В этом, кстати, одно из главных отличий синтаксиса языка XML от HTML. Например, вместо <code>&lt;HR&gt;</code> в XML следует писать <code>&lt;HR/&gt;</code>.</p>
      <cite>
       <subtitle>Замечание</subtitle>
       <p>Для того чтобы привести синтаксис HTML в соответствие со стандартом XML, был создан язык XHTML. Этот язык полностью соответствует синтаксису XML, что делает возможным обработку XHTML-документов XML-средствами, но при этом набор тегов XHTML идентичен набору тегов языка HTML. К сожалению, далеко не все браузеры поддерживают XHTML. Чаще всего проблемы возникают именно с пустыми элементами (или одиночными тегами в терминах HTML): например, браузеры могут некорректно воспринимать запись вида <code>&lt;br/&gt;</code>. В большинстве случаев проблема решается использованием перед косой чертой пробела: запись вида <code>&lt;br /&gt;</code>, скорее всего, будет обработана корректно.</p>
      </cite>
     </section>
     <section>
      <title>
       <p>Атрибут</p>
      </title>
      <p>В элементах можно использовать атрибуты с присвоенными им значениями. Атрибут задается в следующем виде:</p>
      <p><code><emphasis>атрибут</emphasis>="<emphasis>значение</emphasis>"</code></p>
      <p>Например, в записи гипертекстовой ссылки</p>
      <p><code>&lt;а href="http://www.xsltdev.ru"&gt;Заходите к нам!&lt;/а&gt;</code></p>
      <p>элемент <code>а</code> имеет атрибут <code>href</code>, которому присвоено значение <code>"http://www.xsltdev.ru"</code>.</p>
      <p>В языке XML атрибуты всегда должны иметь значения. Например, атрибут <code>selected</code> в записи элемента</p>
      <p><code>&lt;option selected&gt;</code></p>
      <p><code><emphasis> выбранный элемент</emphasis></code></p>
      <p><code>&lt;/option&gt;</code></p>
      <p>будет задан с точки зрения XML некорректно, поскольку ему не присвоено значение. Заметим, что в HTML такое определение является вполне нормальным. Такую ошибку легко исправить следующим образом:</p>
      <p><code>&lt;option selected="selected"&gt;</code></p>
      <p><code><emphasis> выбранный элемент</emphasis></code></p>
      <p><code>&lt;/option&gt;</code></p>
      <p>Значения атрибутов заключаются в кавычки — одинарные или двойные, например, в предыдущем случае можно написать:</p>
      <p><code>&lt;option selected='selected'&gt;</code></p>
      <p><code><emphasis> выбранный элемент</emphasis></code></p>
      <p><code>&lt;/option&gt;</code></p>
      <p>На практике часто бывает необходимым использовать в значениях атрибутов кавычки (например, для записи литералов). Следующий пример иллюстрирует, как это можно делать:</p>
      <p><code>&lt;auth login='"scott"' password="'tiger'"/&gt;</code></p>
      <p>Атрибуту <code>login</code> присвоено значение <code>"scott"</code> (включая двойные кавычки), атрибуту <code>password</code> — значение <code>'tiger'</code> (включая одинарные кавычки).</p>
      <p>В XML один элемент не может иметь атрибуты с одинаковыми именами.</p>
      <p>Определение атрибута состоит из имени, за которым следует знак равенства, а затем, значение атрибута:</p>
      <p><code>[41] Attribute ::= Name Eq Attribute</code></p>
      <p><code>[25] Eq ::= S? '=' S?</code></p>
      <p><code>[10] AttValue ::= '"' ([^&lt;&amp;"] | Reference)* '"'</code></p>
      <p><code>                  | "'" ([^&lt;&amp;'] | Reference)* "'"</code></p>
      <p>Значение атрибута записывается в одинарных или двойных кавычках, причем оно не может содержать символов '<code>&lt;</code>' и '<code>&amp;</code>', которые используются в XML как управляющие символы (<code>&lt;</code> открывает тег элемента, а <code>&amp;</code> — сущность). Вместе с тем, значение атрибута может содержать сущность (нетерминал <code>Reference</code>) — специальную конструкцию, о которой мы поговорим чуть позже.</p>
     </section>
     <section>
      <title>
       <p>Инструкция по обработке</p>
      </title>
      <p>В XML-документы могут быть включены не относящиеся к содержимому документа инструкции, несущие информацию для приложения, которое будет этот документ обрабатывать. Инструкции по обработке имеют вид:</p>
      <p><code>&lt;?приложение содержимое?&gt;</code></p>
      <p>Инструкция по обработке всегда заключается в угловые скобки со знаками вопроса. Первая часть инструкции, <emphasis>приложение</emphasis>, определяет программу или систему, которой предназначена вторая часть, ее <emphasis>содержимое</emphasis>.</p>
      <p>Примером инструкции по обработке может послужить следующая запись:</p>
      <p><code>&lt;?serv cache-document?&gt;</code></p>
      <p>В данном случае целевое приложение имеет имя '<code>serv</code>', а сама инструкция может быть интерпретирована как указание серверу на то, что документ нужно сохранить в кэше. Естественно, инструкции по обработке имеют смысл только для тех приложений, которым они адресуются.</p>
      <p>Продукции инструкций по обработке имеют следующий вид:</p>
      <p><code>[16] PI ::= '&lt;?' PITarget</code></p>
      <p><code>            (S (Char* - (Char* '?&gt;' Char*)))? '?&gt;'</code></p>
      <p>В этом правиле выражение <code>(S (Char* - (Char* '?&gt;' Char*)))?</code> означает, что приложение и содержимое инструкции по обработке разделены пробельными символами, причем содержимое состоит из любых символов, кроме последовательности <code>'?&gt;'</code>, которая обозначает конец инструкции.</p>
      <p>Целевое приложение может иметь любое имя (кроме "<code>xml</code>" в любом регистре символов). Имя целевого приложения определяется EBNF-правилом <code>PITarget</code>:</p>
      <p><code>[17] PITarget ::= Name - (('X' | 'х') ('М' | 'm') ('L' | 'l'))</code></p>
      <p>В XML определена особая конструкция, называемая ХМL-декларацией (XML declaration). Она имеет вид:</p>
      <p><code>&lt;?xml version="<emphasis>версия</emphasis>" encoding="<emphasis>кодировка</emphasis>" standalone="yes | no"/&gt;</code></p>
      <p>Несмотря на то, что XML-декларация очень похожа на инструкцию по обработке, с точки зрения стандарта она таковой не является. Если же подходить менее строго, то смысл XML-декларации полностью соответствует смыслу инструкции по обработке: она сообщает обрабатывающему данный документ программному обеспечению информацию о некоторых свойствах этого документа. XML-декларация может содержать <emphasis>псевдоатрибуты</emphasis> <code>version</code>, <code>encoding</code> и <code>standalone</code>, которые мы рассмотрим ниже.</p>
      <cite>
       <subtitle>Замечание</subtitle>
       <p>В отличие от элементов, XML-декларация, как и инструкции по обработке не могут иметь атрибутов. Однако их содержимое очень часто образуется в форме <code><emphasis>имя</emphasis>="<emphasis>значение</emphasis>"</code> — такие объявления и называются псевдоатрибутами.</p>
      </cite>
      <p>Псевдоатрибут <code>version</code> содержит информацию о версии XML, в соответствии с которой был создан этот документ. Текущей версией языка XML является 1.0, поэтому в большинстве случаев указывается <code>version="1.0"</code>.</p>
      <subtitle>Пример</subtitle>
      <p><code>&lt;?xml version="1.0"?&gt;</code></p>
      <p>Псевдоатрибут <code>encoding</code> сообщает, в какой кодировке создан данный документ. По умолчанию выбрана Unicode-кодировка UTF-8 (подробнее см. "Использование Unicode"), но точно так же может быть использована и любая другая кодировка, лишь бы только ее поддерживало программное обеспечение, обрабатывающее документ.</p>
      <subtitle>Пример</subtitle>
      <p>Большинство документов, созданных на русском языке, используют кириллические кодировки <code>windows-1251</code> и <code>KOI8-R</code>; XML-декларации для этих документов будут иметь вид:</p>
      <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
      <p>и</p>
      <p><code>&lt;?xml version="1.0" encoding="KOI8-R"?&gt;</code></p>
      <p>соответственно.</p>
      <p>Для документов, в которых использовались только нижние 127 символов ASCII, то есть, символы с кодами, не превышающими <code>#x7F</code>, псевдоатрибут <code>encoding</code> указывать необязательно. В этой области символов кодировка UTF-8 совпадает с ASCII.</p>
      <p>Псевдоатрибут <code>standalone</code> говорит о том, использует ли этот документ какие-либо внешние объявления или нет. Как мы узнаем чуть позже, XML-документы могут использовать информацию, которая находится во внешних документах. Опция <code>standalone</code>, имеющая значение <code>"yes"</code>, означает, что документ не содержит таких объявлений, и, значит, может быть обработан без обращения к внешним источникам.</p>
      <p>Декларации XML соответствует продукция <code>XMLDecl</code>, которая, в свою очередь, использует несколько дочерних правил:</p>
      <p><code>[23] XMLDecl ::= '&lt;?xml' VersionInfo EncodingDecl?</code></p>
      <p><code>                  SDDecl? S? '?&gt;'</code></p>
      <p>Продукция <code>VersionInfo</code> определяет синтаксис псевдоатрибута <code>version</code>:</p>
      <p><code>[24] VersionInfo ::= S? 'version' Eq</code></p>
      <p><code>                     ("'" VersionNum "'"</code></p>
      <p><code>                     | "" VersionNum "")</code></p>
      <p>Значение версии документа может состоять из латинских букв и цифр, а также символов "<code>_</code>", "<code>.</code>", "<code>:</code>" и "<code>-</code>":</p>
      <p><code>[26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+</code></p>
      <p>Кодировка объявляется продукцией <code>EncodingDecl</code>, которая синтаксически похожа на <code>VersionInfo</code>:</p>
      <p><code>[80] EncodingDecl ::= S? 'encoding' Eq</code></p>
      <p><code>                      ("'" EncName "'"</code></p>
      <p><code>                      | '"' EncName '"')</code></p>
      <p>Имя кодировки, <code>EncName</code>, может состоять только из латинских букв, цифр и символов "<code>.</code>", "<code>_</code>" и "<code>-</code>", причем первым символом названия кодировки всегда должна быть буква:</p>
      <p><code>[81] EncName [A-Za-z] ([A-Za-z0-9.-] | '-')*</code></p>
      <p>Используемое в документе название кодировки должно быть известно программному обеспечению, которое этот документ обрабатывает. В противном случае могут возникнуть ошибки и несоответствия. В спецификации рекомендуется использовать названия кодировок, одобренные IANA (Internet Assigned Numbers Authority — Комитет присвоенных кодов Интернет). Кириллице, которая используется в русском языке, в списках IANA присваивается около десятка кодировок. Самыми распространенными из них являются следующие:</p>
      <p>&#9633; Windows-1251;</p>
      <p>&#9633; KOI8-R;</p>
      <p>&#9633; Cp866;</p>
      <p>&#9633; ISO-8859-5.</p>
      <p>Техническая рекомендация XML оговаривает, что. в тех случаях, когда имя использованной кодировки не является стандартным, оно должно указываться с префиксом "<code>x-</code>", например:</p>
      <p><code>&lt;?xml version="1.0" encoding="x-BK-CYR"?&gt;</code></p>
      <p>Псевдоатрибуту <code>standalone</code> соответствует EBNF-правило <code>SDDecl</code>:</p>
      <p><code>[32] SDDecl ::= S 'standalone' Eq</code></p>
      <p><code>                (("'" ('yes' | 'no') "'")</code></p>
      <p><code>                | ( '"' ('yes' | 'no') '"' ) )</code></p>
      <p>Расшифровывается это правило очень просто: псевдоатрибут <code>standalone</code> может иметь значение <code>yes</code> или <code>no</code>, заключенное в одинарные или двойные кавычки.</p>
     </section>
     <section>
      <title>
       <p>Секции СDATA</p>
      </title>
      <p>Секции CDATA выделяют части документа, внутри которых текст не должен восприниматься как разметка. CDATA означает буквально "character data" — символьные данные. Секции CDATA задаются следующим образом:</p>
      <p><code>&lt;![CDATA[<emphasis>содержимое</emphasis>]]&gt;</code></p>
      <p>Поскольку синтаксис разметки документов в XML имеет текстовую форму, часто бывает, что само содержимое документа может быть воспринято как разметка. В том случае, когда этого желательно избежать, самым простым выходом будет поместить такие данные внутрь секции CDATA.</p>
      <subtitle>Пример</subtitle>
      <p>Следующий текст в документе</p>
      <p><code>&lt;slogan&gt;Покупайте наших слонов!&lt;/slogan&gt;</code></p>
      <p>будет воспринят как разметка. Для того чтобы избежать этого, достаточно написать</p>
      <p><code>&lt;![СDАТА[&lt;slogan&gt;Покупайте наших слонов!&lt;/slogan&gt;]]&gt;</code></p>
      <p>Такая конструкция уже будет воспринята как символьные данные. Другим примером может быть использование символов "<code>&lt;</code>" и "<code>&amp;</code>":</p>
      <p><code>&lt;![CDATA[ if ( а &lt; b &amp;&amp; b &lt; с ) {...} ]]&gt;</code></p>
      <p>Секции символьных данных задаются четырьмя довольно простыми правилами:</p>
      <p><code>[18] CDSect  ::= CDStart CData CDEnd</code></p>
      <p><code>[19] CDStart ::= '&lt;![CDATA['</code></p>
      <p><code>[20] CData   ::= Char* - (Char* ']]&gt;' Char*))</code></p>
      <p><code>[21] CDEnd   ::= ']]&gt;'</code></p>
      <p>Содержимое секции символьных данных, отвечающее продукции CData, может состоять из любых символов, в том числе "<code>&lt;</code>" и "<code>&amp;</code>", которые не будут восприниматься как разметка. Единственное, чего секции CDATA не могут включать — это последовательность "<code>]]&gt;</code>", которая завершает символьную секцию.</p>
     </section>
     <section>
      <title>
       <p>Комментарии (comments)</p>
      </title>
      <p>XML-документ может содержать комментарии, которые записываются следующим образом:</p>
      <p><code>&lt;!-- <emphasis>текст комментария</emphasis> --&gt;</code></p>
      <p>Текст комментария может состоять из любых символов, кроме двух минусов</p>
      <p>подряд ("<code>--</code>"). Кроме этого, комментарий не должен заканчиваться символом "<code>-</code>" .</p>
      <p>Пример комментария:</p>
      <p><code>...</code></p>
      <p><code>&lt;!-- product title="Слон"&gt;</code></p>
      <p><code> Покупайте наших слонов!</code></p>
      <p><code>&lt;/product--&gt;</code></p>
      <p><code>...</code></p>
      <p>Продукция комментария называется в XML <code>Comment</code> и имеет следующий вид:</p>
      <p><code>[15] Comment ::= '&lt;!--' ((Char - '-') | ('-' (Char- '-')))* '--&gt;'</code></p>
      <p>Выражение <code>((Char - '-') | ('-' (Char - '-')))*</code> означает, что содержимое комментария не должно оканчиваться на знак "<code>-</code>" или содержать два таких знака последовательно.</p>
     </section>
    </section>
    <section>
     <title>
      <p>Пространства имён</p>
     </title>
     <section>
      <p>XML позволяет создавать наборы элементов с любыми синтаксически допустимыми именами и определять с их помощью логическую структуру документов практически произвольной сложности.</p>
      <p>За время существования XML была создана разметка для большого числа задач. На таких Web-сайтах, как <strong>http://www.xml.org</strong>, <strong>http://www.schema.net</strong> и <strong>http://www.ebxml.org</strong> можно с большой вероятностью найти определения структуры документов для огромного количества предметных областей. Во многих случаях уже созданные схемы помогут сократить этап концептуального моделирования документов.</p>
      <p>Часто случается, что различные логические схемы документов используют одни и те же имена элементов в различных смыслах. Это не является проблемой, если в документе используется только одна схема. Но представьте себе ситуацию, когда в одном и том же документе необходимо использовать элементы нескольких различных схем — будет попросту невозможно определить, какой элемент относится к какой схеме, и, вообще, какие схемы были использованы в документе. Для решения этих проблем в XML используются пространства имен (англ. namespaces).</p>
      <p>Чтобы различать схемы документов, каждой из них ставится в соответствие уникальный идентификатор ресурса (URI). Две схемы будут считаться тождественными тогда и только тогда, когда их уникальные идентификаторы будут совпадать, поэтому нужно осторожно выбирать URI для создаваемой схемы документа. Очень часто в качестве URI используются URL различных Web-сайтов. Это совсем не означает, что по указанному адресу должно что-либо находиться, просто такой способ практически гарантирует уникальность — вряд ли кому придет в голову использовать адрес чужого сервера в качестве идентификатора своей схемы.</p>
      <subtitle>Пример</subtitle>
      <p>Уникальный идентификатор языка XSLT, которому посвящена эта книга, имеет вид:</p>
      <p><code>http://www.w3.org/1999/XSL/Transform</code></p>
      <p>Для того чтобы определить, какой схеме принадлежит тот или иной элемент в документе, можно использовать механизм префиксов. Префиксы пространств имен задаются как атрибуты с именами, начинающимися последовательностью <code>xmlns</code>, и имеют следующий вид:</p>
      <p><code>&lt;<emphasis>префикс</emphasis>:<emphasis>элемент</emphasis> xmlns:<emphasis>префикс</emphasis>="<emphasis>URI</emphasis>"&gt;</code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/<emphasis>префикс</emphasis>:<emphasis>элемент</emphasis>&gt;</code></p>
      <subtitle>Пример</subtitle>
      <p>В XSLT чаще всего используется префикс <code>xsl</code>, который задается, как правило, следующим образом:</p>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
      <p><code> version="1.0"&gt;</code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <p>При этом ничто не мешает использовать любой другой префикс. Например, следующий фрагмент документа будет совершенно идентичен предыдущему:</p>
      <p><code>&lt;www:stylesheet</code></p>
      <p><code> xmlns:www="http://www.w3.org/1999/XSL/Transform"</code></p>
      <p><code> version="1.0"&gt;</code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/www:stylesheet&gt;</code></p>
      <p>Префиксы, которые были определены в некотором элементе, могут быть использованы в его собственном имени, а также в именах всех элементов, которые включены в него.</p>
      <subtitle>Пример</subtitle>
      <p><code>&lt;!-- Здесь еще нельзя использовать префикс aaa --&gt;</code></p>
      <p><code>&lt;aaa:element xmlns:aaa="http://www.aaa.com"&gt;</code></p>
      <p><code> &lt;!-- Здесь уже можно использовать префикс aaa --&gt;</code></p>
      <p><code> &lt;ааа:anotherelement/&gt;</code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/aaa:element&gt;</code></p>
      <p><code>&lt;!-- А здесь снова нельзя --&gt;</code></p>
      <p>Принадлежность элементов той или иной схеме определяется не префиксами, а тем, какие уникальные идентификаторы поставлены этим префиксам в соответствие. То есть два элемента с разными префиксами, заданными одинаковыми идентификаторами, будут считаться принадлежащими одной схеме.</p>
      <subtitle>Пример</subtitle>
      <p>В следующем фрагменте</p>
      <p><code>&lt;xslt:stylesheet</code></p>
      <p><code> xmlns:xslt="http://www.w3.org/1999/XSL/Transform" </code></p>
      <p><code> version="1.0"&gt;</code></p>
      <p><code> &lt;xsl:template xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/&gt; </code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/xslt:stylesheet&gt;</code></p>
      <p>элементы <code>stylesheet</code> и <code>template</code> имеют различные префиксы, но, несмотря на это, принадлежат одной и той же схеме.</p>
      <p>В одном элементе можно определять несколько префиксов пространств имен. Как правило, при использовании множества префиксов, все они определяются в корневом элементе, а затем используются по всему документу.</p>
      <subtitle>Пример</subtitle>
      <p><code>&lt;aaa:element</code></p>
      <p><code> xmlns:aaa="http://www.ааа.com"</code></p>
      <p><code> xmlns:bbb="http://www.bbb.com"</code></p>
      <p><code> xmlns:ccc="http://www.ccc.com"&gt;</code></p>
      <p><code> &lt;aaa:anotherelement/&gt;</code></p>
      <p><code> &lt;ccc:element/&gt;</code></p>
      <p><code> &lt;bbb:anotherelement/&gt;</code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/aaa:element&gt;</code></p>
      <p>Весьма удобной является возможность использования пространства имен по умолчанию. Определение пространства имен в виде</p>
      <p><code>&lt;<emphasis>элемент</emphasis> xmlns="URI"&gt;</code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/<emphasis>элемент</emphasis>&gt;</code></p>
      <p>позволяет опускать префиксы в именах элементов.</p>
      <subtitle>Пример</subtitle>
      <p>Документ в предыдущем примере может быть переписан следующим образом:</p>
      <p><code>&lt;element xmlns="http://www.aaa.com"&gt; </code></p>
      <p><code> &lt;anotherelement/&gt;</code></p>
      <p><code> &lt;ссс:element xmlns:ccc="http://www.ccc.com"/&gt; </code></p>
      <p><code> &lt;anotherelement xmlns="http://www.bbb.com"/&gt;</code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/element&gt;</code></p>
      <p>Обратим внимание, что пространство имен по умолчанию может быть изменено повторным использованием атрибута <code>xmlns</code> в дочерних элементах.</p>
      <subtitle>Пример</subtitle>
      <p>Документ</p>
      <p><code>&lt;element xmlns="http://www.ааа.com"&gt;</code></p>
      <p><code> &lt;element/&gt;</code></p>
      <p><code> &lt;element xmlns="http://www.bbb.com"&gt; </code></p>
      <p><code>  &lt;element/&gt;</code></p>
      <p><code>  &lt;element xmlns="http://www.ccc.com"/&gt; </code></p>
      <p><code> &lt;/element&gt;</code></p>
      <p><code>&lt;/element&gt;</code></p>
      <p>эквивалентен документу</p>
      <p><code>&lt;aaa:element</code></p>
      <p><code> xmlns:aaa="http://www.aaa.com" </code></p>
      <p><code> xmlns:bbb="http://www.bbb.com" </code></p>
      <p><code> xmlns:ccc="http://www.ccc.com"&gt; </code></p>
      <p><code> &lt;aaa:element/&gt;</code></p>
      <p><code> &lt;bbb:element&gt;</code></p>
      <p><code>  &lt;bbb:element/&gt;</code></p>
      <p><code>  &lt;ccc:element/&gt;</code></p>
      <p><code> &lt;/bbb:element&gt;</code></p>
      <p><code>&lt;/aaa:element&gt;</code></p>
      <p>Таким образом, пространства имен — это механизм выделения в тексте XML-документа элементов и атрибутов, принадлежащих различным логическим схемам документов. Более того, термин "пространство имен" часто используется как эквивалент логической схеме документа, например, когда говорят "элемент <code>template</code> принадлежит пространству имен XSLT", подразумевается, что элемент <code>template</code> определен в языке XSLT и описывается в соответствующей схеме.</p>
      <p>Синтаксические правила, которые описывают определения пространств имен, задаются не в спецификации XML, а в другом документе — в технической рекомендации "Namespaces in XML" (пространства имен в XML), которая доступна по адресу <strong>http://www.w3.org/TR/REC-xml-names</strong>. Для того чтобы отличать эти продукции от продукций языка XML, мы будет давать им номера вида <code>[NS1]</code>, <code>[NS2]</code> и так далее.</p>
      <p>Продукция <code>NSAttName</code> описывает имена атрибутов, декларирующих пространства имен:</p>
      <p><code>[NS1] NSAttName       ::= PrefixedAttName | DefaultAttName</code></p>
      <p><code>[NS2] PrefixedAttName ::= 'xmlns:' NCName</code></p>
      <p><code>[NS3] DefaultAttName  ::= 'xmlns'</code></p>
      <p>Имя <code>NCName</code>, которое использовалось в правиле <code>PrefixedAttName</code>, — это имя префикса, который будет использоваться для обозначения принадлежности элементов определенному пространству имен. Это имя отличается от имен, которые отвечают продукции <code>Name</code> тем, что оно не может содержать двоеточия:</p>
      <p><code>[NS4] NCName     ::= (Letter | '_') (NCNameChar)*</code></p>
      <p><code>[NS5] NCNameChar ::= Letter | Digit | '.' | '-' | '_'</code></p>
      <p><code>                     | CombiningChar | Extender</code></p>
     </section>
     <section>
      <title>
       <p>Расширенные имена</p>
      </title>
      <p>Использование пространств имен значительно изменяет понятие имени. Действительно, если <code>www:template</code>, <code>xsl:template</code> или просто <code>template</code> могут быть одинаковыми именами, то именем в таком случае должна считаться не просто символьная последовательность, которая его составляет, а нечто большее.</p>
      <p>Вследствие этого в спецификациях группы XML-языков вводится такое понятие, как расширенное имя, которое состоит из двух частей: локальной части и идентификатора пространства имен, которое соответствует префиксу имени.</p>
      <subtitle>Пример</subtitle>
      <p>Представим себе элемент вида</p>
      <p><code>&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/&gt;</code></p>
      <p>Расширенное имя этого элемента будет состоять из локальной, части <code>stylesheet</code> и идентификатора пространств имен <code>http://www.w3.org/1999/XSL/Transform</code>.</p>
      <p>Расширенные имена считаются совпадающими, если их локальные части равны и, при этом, они относятся к одному пространству имен.</p>
      <p>Префикс в расширенном имени может быть опущен. В таком случае идентификатор пространства имен будет либо выбран по умолчанию (если имеется соответствующее объявление), либо будет нулевым.</p>
      <p>Для описания имен элементов и атрибутов, которые должны иметь расширенное представление, используется продукция <code>QName</code>:</p>
      <p><code>[NS6] QName ::= (Prefix ':')? LocalPart</code></p>
      <p>Нетерминалу <code>Prefix</code> соответствует префикс имени, который может быть опущен вместе со следующим за ним разделяющим двоеточием, <code>LocalPart</code> соответствует локальной части имени.</p>
      <p><code>[NS7] Prefix    ::= NCName</code></p>
      <p><code>[NS8] LocalPart ::= NCName</code></p>
     </section>
    </section>
    <section>
     <title>
      <p>Структура XML-документа</p>
     </title>
     <section>
      <p>В погоне за выразительной мощностью XML не следует забывать один из основополагающих принципов — нужно не просто выражать информацию, нужно выражать ее стандартным образом. Это включает в себя не только синтаксические принципы разметки текста, изложенные выше, но и ограничения, накладываемые на логическую структуру документов. Изобретая свой собственный набор элементов и атрибутов, мы вместе с этим набором изобретаем логический формат, а именно то, каким образом элементы и атрибуты должны формировать документ, какая информация должна присутствовать обязательно, а какая является опциональной, какие данные должны содержать те или иные атрибуты и элементы.</p>
      <p>В первой версии XML для определения логической структуры документов использовался набор формальных правил, называемый DTD — декларацией типа документа (document type declaration). Помимо этого, в начале мая 2001 года была принята новая техническая рекомендация языка под названием XML-схема (XML Schema), которая также формально задает логическую структуру документа, определяет используемые типы данных, количество повторений и многое другое.</p>
      <p>В этой главе мы разберем основы логического построения ХМL-документов с использованием DTD.</p>
     </section>
     <section>
      <title>
       <p>Декларация типа документа (DTD)</p>
      </title>
      <p>Декларация типа документа состоит из одного или нескольких правил-ограничений структуры документа. В частности, DTD позволяет задавать следующие правила:</p>
      <p>&#9633; <code>ELEMENT</code> — определение элемента;</p>
      <p>&#9633; <code>ATTLIST</code> — определение списка атрибутов элемента;</p>
      <p>&#9633; <code>ENTITY</code> — определение сущности;</p>
      <p>&#9633; <code>NOTATION</code> — определение нотации.</p>
      <p>Эти определения могут быть заданы с использованием конструкции <code>DOCTYPE</code> непосредственно в документе:</p>
      <p><code>&lt;!DOCTYPE advert [</code></p>
      <p><code>&lt;!-- <emphasis>определение</emphasis> --&gt;</code></p>
      <p><code>&lt;!-- <emphasis>определение</emphasis> --&gt;</code></p>
      <p><code><emphasis>и т.д.</emphasis></code></p>
      <p><code>]&gt;</code></p>
      <p>Другой возможностью определения декларации документа является использование внешнего файла:</p>
      <p><code>&lt;!DOCTYPE advert SYSTEM "advert.dtd"&gt;</code></p>
      <p>В этом случае можно также дополнять внешние определения внутренними:</p>
      <p><code>&lt;!DOCTYPE advert SYSTEM "advert.dtd" [</code></p>
      <p><code>&lt;!-- <emphasis>определение</emphasis> --&gt;</code></p>
      <p><code>&lt;!-- <emphasis>определение</emphasis> --&gt;</code></p>
      <p><code><emphasis>и т.д.</emphasis></code></p>
      <p><code>]&gt;</code></p>
      <p>Декларация типа документа определяется следующей EBNF-продукцией:</p>
      <p><code>[28] doctypedecl ::= '&lt;!DOCTYPE' S Name (S ExternalID)? S?</code></p>
      <p><code>                     ('[' (markupdecl | DeclSep)* ']' S?)? '&gt;'</code></p>
      <p>Имя, соответствующее продукции <code>Name</code>, которая идет следом за ключевым словом <code>DOCTYPE</code>, определяет имя корневого элемента ХМL-документа. В предыдущем примере в корне документа должен стоять элемент <code>advert</code>.</p>
      <p>Выражение <code>(S ExternalID) ?</code> указывает на то, что декларация типа документа может указываться во внешнем источнике (например, в файле), который описывается внешним идентификатором <code>ExternalID</code>.</p>
      <p><code>[75] ExternalID ::= 'SYSTEM' S SystemLiteral</code></p>
      <p><code>                    | 'PUBLIC' S PubidLiteral S SystemLiteral</code></p>
      <p>В случае системного идентификатора (<code>"SYSTEM"</code>), <code>SystemLiteral</code> определяет URI определения типа документа. В случае публичного идентификатора, к этому параметру добавляется <code>PubidLiteral</code>, сообщающий дополнительную информацию о ресурсе. Обрабатывающее программное обеспечение может включать в себя DTD для заданного публичного идентификатора. Например, документы, написанные на языке XHTML, должны начинаться следующим объявлением:</p>
      <p><code>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"</code></p>
      <p><code> "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd"&gt;</code></p>
      <p>Программа, обрабатывающая документ с таким заголовком, сможет по публичному идентификатору понять, что документ создан на языке XHTML, а значит, обрабатывать его нужно в соответствии со стандартом этого языка. Если же обрабатывающая программа не в курсе определений XHTML, она сможет загрузить декларацию типа по адресу <strong>http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd</strong>. Публичные идентификаторы, как правило, используются в языках, получающих широкое распространение, поскольку в этом случае формат логической структуры будет известен и без загрузки DTD.</p>
      <p>Выражение <code>('[' (markupdecl | DeclSep) * ']' S?) ?</code> в продукции <code>doctypedecl</code> означает, что в декларации типа документа в квадратных скобках может содержаться последовательность нетерминалов <code>markupdecl</code> и <code>DeclSep</code>.</p>
      <p>Первый из этих нетерминалов, <code>markupdecl</code>, показывает, определения какого вида содержатся в DTD:</p>
      <p><code>[29] markupdecl ::= elementdecl</code></p>
      <p><code>                    | AttlistDecl</code></p>
      <p><code>                    | EntityDecl</code></p>
      <p><code>                    | NotationDecl</code></p>
      <p><code>                    | PI</code></p>
      <p><code>                    | Comment</code></p>
      <p>С правилами <code>PI</code> и <code>Comment</code> мы уже знакомы — в данной продукции они показывают, что в DTD также можно использовать инструкции по обработке и комментарии.</p>
      <p>Нетерминалы <code>elementdecl</code>, <code>AttlistDecl</code>, <code>EntityDecl</code> и <code>NotationDecl</code> соответствуют определениям элемента, списка атрибутов, сущности и нотации. Они будут подробно разобраны в следующих четырех разделах.</p>
      <p>Нетерминал <code>DeclSep</code> соответствует разделителю объявлений, которые перечисляются в DTD. Этот разделитель может быть либо пробельным пространством, либо параметризованной сущностью:</p>
      <p><code>[28а] DeclSep ::= PEReference | S</code></p>
      <p>В случае, если определения в DTD разделяются сущностью-параметром, ее содержимое интерпретируется как обычные определения вида <code>markupdecl</code>.</p>
     </section>
     <section>
      <title>
       <p>Определение элемента</p>
      </title>
      <p>Определение элемента задает имя и тип содержимого элемента в следующем виде:</p>
      <p><code>&lt;!ELEMENT имя содержимое&gt;</code></p>
      <p>Имя элемента должно начинаться с буквы, подчеркивания ("<code>_</code>") или двоеточия ("<code>:</code>") и содержать буквы, цифры, некоторые знаки пунктуации (такие, как "<code>_</code>" — подчеркивание, "<code>:</code>" — двоеточие, "<code>.</code>" — точка, "<code>-</code>" — тире или знак минуса) и модифицирующие символы (<emphasis>см. разд. "Базовые продукции ХМL" данной главы</emphasis>).</p>
      <p>Примером имени элемента может быть "<code>A</code>", "<code>B:12</code>", "<code>MyEasyName</code>", "<code>doc.xml</code>".</p>
      <p>В качестве содержимого элемента может быть указано:</p>
      <p>&#9633; <code>EMPTY</code>, в случае, когда элемент обязан быть пустым;</p>
      <p>&#9633; <code>ANY</code>, в случае, когда элемент может содержать что угодно;</p>
      <p>&#9633; формальное правило, определяющее элементы, и данные, которые может содержать элемент, а также порядок их следования.</p>
      <p>Первые два случая определения элемента довольно просты. Их использование может быть продемонстрировано на следующем примере:</p>
      <p><code>Декларация</code></p>
      <p><code>&lt;!DOCTYPE advert [</code></p>
      <p><code>&lt;!ELEMENT advert ANY&gt;</code></p>
      <p><code>&lt;!ELEMENT product ANY&gt;</code></p>
      <p><code>&lt;!ELEMENT classified EMPTY&gt;</code></p>
      <p><code>]&gt;</code></p>
      <p>определяет документ с корневым элементом <code>advert</code>, в котором могут встречаться также элементы <code>product</code> и <code>classified</code>, причем элементы <code>advert</code> и <code>product</code> могут содержать любые данные и любые из объявленных элементов, а элемент <code>classified</code> всегда должен быть пустым.</p>
      <p>Приведем пример документа, построенного в соответствии с этой декларацией.</p>
      <subtitle>Листинг 1.3. Документ с декларацией типа</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code></p>
      <p><code>&lt;!DOCTYPE advert [</code></p>
      <p><code>&lt;!ELEMENT advert ANY&gt;</code></p>
      <p><code>&lt;!ELEMENT product ANY&gt;</code></p>
      <p><code>&lt;!ELEMENT classified EMPTY&gt;</code></p>
      <p><code>]&gt;</code></p>
      <p><code>&lt;advert&gt;</code></p>
      <p><code> &lt;product&gt;</code></p>
      <p><code>  Покупайте наших слонов!</code></p>
      <p><code> &lt;/product&gt;</code></p>
      <p><code> &lt;classified/&gt;</code></p>
      <p><code>&lt;/advert&gt;</code></p>
      <p>В третьем случае содержимое элемента определяется при помощи формальных правил, которые очень похожи на те, которые используются в расширенных формах Бэкуса-Наура. Подобно тому, как в EBNF формальные правила используются для того, чтобы стандартизировать последовательность символов, составляющую конструкции некоторого языка, в определениях элементов они используются для описания содержимого элемента — последовательности из символьных данных и дочерних элементов.</p>
      <p>Количество, с которым элемент может появляться в этой последовательности, формально записывается с использованием символов-модификаторов "<code>*</code>", "<code>?</code>", "<code>+</code>", которые имеют следующие значения:</p>
      <p>&#9633; <code>а?</code> — означает, что элемент <code>а</code> может быть пропущен в последовательности;</p>
      <p>&#9633; <code>а</code> — означает, что элемент <code>а</code> должен присутствовать в последовательности на этом месте ровно один раз;</p>
      <p>&#9633; <code>а*</code> — задает последовательность из нуля или более элементов <code>а</code>;</p>
      <p>&#9633; <code>a+</code> — задает последовательность из одного или более элементов <code>а</code>.</p>
      <p>Кроме того, содержимое может моделироваться как перечисление и выбор элементов.</p>
      <p>Элементы перечисляются через запятую в круглых скобках, например <code>(a, b, c)</code> — это последовательность, состоящая из элементов <code>a</code>, <code>b</code>, <code>c</code>. Такая запись означает, что первым должен идти элемент <code>a</code>, затем сразу же за ним элемент <code>b</code> и элемент <code>c</code>.</p>
      <p>Выбор элемента задается аналогично перечислению, только разделительным символом является не запятая, а знак '<code>|</code>'. Например, (<code>a | b | c</code>) задает выбор одного из трех элементов <code>a</code>, <code>b</code> или <code>c</code>.</p>
      <p>При записи выбора и перечисления элементы могут также указываться с использованием модификаторов количества.</p>
      <subtitle>Пример</subtitle>
      <p><code>(a* | b? | с | d+)</code></p>
      <p>определяет содержимое, как последовательность, состоящую из нуля или более элементов <code>a</code> <emphasis>или</emphasis> одного элемента <code>b</code>, который может быть пропущен, <emphasis>или</emphasis> ровно одного элемента <code>с</code>, <emphasis>или</emphasis> последовательностью, состоящей из одного или более элементов <code>d</code>.</p>
      <p>Помимо этого, формальные правила могут использовать при записи другие формальные правила.</p>
      <subtitle>Пример</subtitle>
      <p><code>((a | b), (с | d))</code></p>
      <p>задает содержимое, первым элементом которого является <code>a</code> или <code>b</code>, вторым — элемент <code>с</code> или <code>d</code>.</p>
      <p>Содержимое элементов может также включать символьные данные, которые обозначаются при помощи ключевого слова <code>#PCDATA</code> (parsable character data — разбираемые символьные данные).</p>
      <subtitle>Пример</subtitle>
      <p><code>&lt;!ELEMENT product (#PCDATA)&gt;</code></p>
      <p>означает, что элемент <code>product</code> должен содержать только символьные данные.</p>
      <p>Помимо текста элементы могут также включать в себя другие элементы. Содержимое такого типа называется <emphasis>смешанным</emphasis>. Формальные правила смешанного содержимого должны всегда иметь вид <code>(#PCDATA | ... | ... ) *</code>.</p>
      <p>При помощи формальных правил можно точно и гибко задавать логическую структуру элементов документа. В качестве примера приведем определения элементов для нашего документа с рекламным объявлением.</p>
      <subtitle>Пример</subtitle>
      <p>Предположим, мы хотим определить документ со следующей логической структурой:</p>
      <p>&#9633; корневым элементом документа является элемент <code>advert</code>;</p>
      <p>&#9633; элемент <code>advert</code> содержит последовательность, состоящую из нескольких элементов product и одного элемента <code>classified</code>, который может быть пропущен;</p>
      <p>&#9633; элемент <code>product</code> может содержать текст и другие элементы <code>product</code> в любом порядке;</p>
      <p>&#9633; элемент <code>classified</code> не имеет содержимого.</p>
      <p>Документ соответствующей логической структуры может быть задан следующим образом.</p>
      <subtitle>Листинг 1.4</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code></p>
      <p><code>&lt;!DOCTYPE advert [</code></p>
      <p><code>&lt;!ELEMENT advert (product+, classified*)&gt;</code></p>
      <p><code>&lt;!ELEMENT product (#PCDATA | product)*&gt;</code></p>
      <p><code>&lt;!ELEMENT classified EMPTY&gt;</code></p>
      <p><code>]&gt;</code></p>
      <p><code>&lt;advert&gt;</code></p>
      <p><code> &lt;product&gt;</code></p>
      <p><code>  Покупайте наших слонов!</code></p>
      <p><code> &lt;/product&gt;</code></p>
      <p><code> &lt;classified/&gt;</code></p>
      <p><code>&lt;/advert&gt;</code></p>
      <p>Определению элемента соответствует EBNF-продукция <code>elementdecl</code>:</p>
      <p><code>[45] elementdecl ::= '&lt;!ELEMENT' S Name S contentspec S? '&gt;'</code></p>
      <p>Нетерминал <code>contentspec</code>, следующий через пробельное пространство за именем элемента, определяет тип содержимого, которое может иметь этот элемент:</p>
      <p><code>[46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children</code></p>
      <p>Строка "<code>EMPTY</code>" соответствует пустому элементу, "<code>ANY</code>" — любому содержимому, нетерминал <code>Mixed</code> — смешанному содержимому, <code>children</code> — содержимому, которое определяется формальными правилами.</p>
      <p><code>[47] children ::= (choice | seq) ('?' | '*' | '+')?</code></p>
      <p><code>[48] cp       ::= (Name | choice | seq) ('?' | '*' | '+')?</code></p>
      <p><code>[49] choice   ::= '(' S? cp ( S? '|' S? cp )+ S? ')'</code></p>
      <p><code>[50] seq      ::= '(' S? cp ( S? ',' S? cp )* S? ')'</code></p>
      <p><code>[51] Mixed    ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'</code></p>
      <p><code>                  | '(' S? '#PCDATA' S? ')'</code></p>
     </section>
     <section>
      <title>
       <p>Определение списка атрибутов</p>
      </title>
      <p>Список атрибутов некоторого элемента задается следующим образом:</p>
      <p><code>&lt;!ATTLIST <emphasis>элемент</emphasis></code></p>
      <p><code><emphasis> атрибут1 тип1 значение1</emphasis></code></p>
      <p><code><emphasis> атрибут2 тип2 значение2</emphasis></code></p>
      <p><code><emphasis> и т. д</emphasis>...&gt;</code></p>
      <p>В этом определении <code><emphasis>элемент</emphasis></code> задает имя элемента, для которого определяется данный список атрибутов, <code><emphasis>атрибут</emphasis></code> — имя атрибута, <code><emphasis>тип</emphasis></code> — тип атрибута и <code><emphasis>значение</emphasis></code> — значение атрибута.</p>
      <p><code><emphasis>Имя</emphasis></code> атрибута отвечает в XML тем же самым требованиям, что и имя элемента — оно должно начинаться с буквы и может содержать другие буквы, цифры и некоторые знаки препинания.</p>
      <p><code><emphasis>Тип</emphasis></code> атрибута может быть одним из следующих:</p>
      <p>&#9633; <code>CDATA</code> — символьные данные;</p>
      <p>&#9633; <code>ID</code> — уникальный идентификатор;</p>
      <p>&#9633; <code>IDREF</code> — ссылка на уникальный идентификатор;</p>
      <p>&#9633; <code>IDREFS</code> — набор ссылок;</p>
      <p>&#9633; <code>ENTITY</code> — сущность;</p>
      <p>&#9633; <code>ENTITIES</code> — набор сущностей;</p>
      <p>&#9633; <code>NMTOKEN</code> — именной токен;</p>
      <p>&#9633; <code>NMTOKENS</code> — набор именных токенов;</p>
      <p>&#9633; <code>NOTATION</code> — нотация;</p>
      <p>&#9633; перечисление возможных значений атрибута.</p>
      <p>Следует поподробнее остановиться на типе <code>ID</code>, поскольку атрибуты этого типа играют важную роль в повышении эффективности обработки XML-документов. Атрибуты типа <code>ID</code> могут содержать значения, которые однозначным образом идентифицируют элемент в документе. То есть, если тип атрибута объявлен как <code>ID</code>, его значение <emphasis>должно</emphasis> быть уникальным внутри документа. Это позволяет создавать для элементов с <code>ID</code>-атрибутами индексы по значению атрибута, для более быстрого доступа. Например, в языке XPath, имеется функция <code>id</code>, которая по данному строковому параметру возвращает множество, состоящее из элемента, <code>ID</code>-атрибут которого совпадает с этим параметром. Естественно, тип <code>ID</code> не гарантирует, что доступ к элементам в любом случае будет производиться быстрее — это зависит от реализации обрабатывающих программ. Однако большинство современных XML-процессоров при работе с <code>ID</code>-атрибутами используют механизмы оптимизации.</p>
      <p>Тип <code>ID</code> может быть полезен и при создании кросс-ссылок между элементами в самих XML-документах, для описания информации, структура которой выходит за рамки обычных деревьев. Уникальные значения, заданные в атрибуте <code>ID</code> могут использоваться в атрибутах типов <code>IDREF</code> (ссылка на идентифицирующее значение) и <code>IDREFS</code> (набор таких ссылок).</p>
      <p><code><emphasis>Значение</emphasis></code> определяет, как и какие значения должны быть присвоены атрибуту. <code><emphasis>Значением</emphasis></code> может быть:</p>
      <p>&#9633; ключевое слово <code>#REQUIRED</code>, которое показывает, что этот атрибут должен всегда присутствовать в элементе и иметь некоторое значение;</p>
      <p>&#9633; ключевое слово <code>#IMPLIED</code>, которое показывает, что атрибут является необязательным и может отсутствовать в элементе;</p>
      <p>&#9633; ключевое слово <code>#FIXED</code>, за которым следует значение, заключенное в кавычки — это задает атрибут, который всегда должен иметь одно и то же фиксированное значение;</p>
      <p>&#9633; значение, заключенное в кавычки, определяет значение атрибута по умолчанию.</p>
      <subtitle>Примеры</subtitle>
      <p>Декларация</p>
      <p><code>&lt;!ATTLIST product</code></p>
      <p><code> title CDATA #REQUIRED</code></p>
      <p><code> id ID #IMPLIED</code></p>
      <p><code> quantity CDATA "1"</code></p>
      <p><code> value CDATA #FIXED "дорого"</code></p>
      <p><code> color (серый|белый) "серый"&gt;</code></p>
      <p>определяет в элементе <code>product</code> следующие атрибуты:</p>
      <p>&#9633; обязательный атрибут <code>title</code>, содержащий символьные данные;</p>
      <p>&#9633; необязательный атрибут <code>id</code>, который может содержать уникальный идентификатор элемента внутри документа;</p>
      <p>&#9633; атрибут <code>quantity</code>, который может и не присутствовать в документе — в этом случае его значение будет равно <code>1</code>;</p>
      <p>&#9633; атрибут <code>value</code>, который всегда должен иметь значение <code>"дорого"</code>;</p>
      <p>&#9633; атрибут <code>color</code>, который может иметь одно из значений — <code>"серый"</code> или <code>"белый"</code>, по умолчанию <code>"серый"</code>.</p>
      <p>Разберем синтаксис определения списка атрибутов более детально. Этому определению соответствует следующее правило:</p>
      <p><code>[52] AttlistDecl ::= '&lt;!ATTLIST' S Name AttDef* S? '&gt;'</code></p>
      <p>В этом правиле <code>Name</code> задает имя элемента, a <code>AttDef*</code> — набор определяемых атрибутов. Каждый атрибут задается правилом <code>AttDef</code>:</p>
      <p><code>[53] AttDef ::= S Name S AttType S DefaultDecl</code></p>
      <p>Здесь <code>Name</code> — имя, <code>AttType</code> — тип, a <code>DefaultDecl</code> — значение атрибута по умолчанию.</p>
      <p><code>[54] AttType ::= StringType | TokenizedType | EnumeratedType</code></p>
      <p>В соответствии со спецификацией, значения атрибутов бывают трех видов — строки (<code>StringType</code>), токены (<code>TokenizedType</code>) и тип перечисления (<code>EnumeratedType</code>).</p>
      <p><code>[55] StringType    ::= 'CDATA'</code></p>
      <p><code>[56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY'</code></p>
      <p><code>                       | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'</code></p>
      <p>Тип перечисления (<code>EnumeratedType</code>) может задаваться нотациями (<code>NotationType</code>) и собственно перечислениями (<code>Enumeration</code>):</p>
      <p><code>[57] EnumeratedType ::= NotationType | Enumeration</code></p>
      <p><code>[58] NotationType   ::= 'NOTATION' S</code></p>
      <p><code>                        '(' S? Name (S? '|' S? Name)* S? ')'</code></p>
      <p>Перечисление — это один или несколько именных токенов, которые разделены пробелами и знаками "<code>|</code>". Перечисление задает несколько возможных вариантов значения атрибута, например <code>(серый | белый)</code>.</p>
      <p><code>[59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'</code></p>
      <p>Значение атрибута описывается продукцией <code>DefaultDecl</code> следующим образом:</p>
      <p><code>[60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED'</code></p>
      <p><code>                     | (('#FIXED' S)? AttValue)</code></p>
     </section>
     <section>
      <title>
       <p>Определение сущности</p>
      </title>
      <p>Для того чтобы обеспечить достаточно выразительную мощность документов, XML позволяет разбивать их на отдельные поименованные объекты, называемые <emphasis>сущностями</emphasis>. Сущности в XML не имеют ничего общего с сущностями в методологии "сущность-связь". Самый близкий аналог в традиционных языках программирования — это макроподстановка.</p>
      <p>Существует два способа определения сущности — внутреннее и внешнее.</p>
      <p>Первый способ используется для того, чтобы определить именованный текстовый объект в самом документе, а затем использовать его содержимое посредством ссылки.</p>
      <p>Внутреннее определение сущности имеет вид:</p>
      <p><code>&lt;!ENTITY <emphasis>имя</emphasis> "<emphasis>значение</emphasis>"&gt;</code></p>
      <p>Ссылка на сущность записывается как <code>&amp;<emphasis>имя</emphasis>;</code> (амперсант, затем имя сущности, затем точка с запятой).</p>
      <subtitle>Пример</subtitle>
      <p>В документе</p>
      <p><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code></p>
      <p><code>&lt;!DOCTYPE advert [</code></p>
      <p><code> &lt;!ENTITY animal "слон"&gt;</code></p>
      <p><code>]&gt;</code></p>
      <p><code>&lt;advert&gt;</code></p>
      <p><code> &lt;product title="&amp;animal;"&gt;</code></p>
      <p><code>  Продается настоящий &amp;animal;!</code></p>
      <p><code> &lt;/product&gt;</code></p>
      <p><code>&lt;/advert&gt;</code></p>
      <p>сущность <code>animal</code> имеет значение <code>"слон"</code>. Ссылка на сущность используется дважды — в атрибуте <code>title</code> и в тексте элемента <code>product</code>. Этот документ эквивалентен документу</p>
      <p><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code></p>
      <p><code>&lt;advert&gt;</code></p>
      <p><code> &lt;product title="слон"&gt;</code></p>
      <p><code>  Продается настоящий слон!</code></p>
      <p><code> &lt;/product&gt;</code></p>
      <p><code>&lt;/advert&gt;</code></p>
      <p>Если в будущем фирма переквалифицируется, и будет продавать, скажем, жирафов, можно будет, не изменяя всего документа, заменить только значение сущности:</p>
      <p><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code></p>
      <p><code>&lt;!DOCTYPE advert [</code></p>
      <p><code> &lt;!ENTITY animal "жираф"&gt;</code></p>
      <p><code>]&gt;</code></p>
      <p><code>&lt;advert&gt;</code></p>
      <p><code> &lt;product title="&amp;animal;"&gt;</code></p>
      <p><code>  Продается настоящий &amp;animal;!</code></p>
      <p><code> &lt;/product&gt;</code></p>
      <p><code>&lt;/advert&gt;</code></p>
      <p>Спецификация XML определяет несколько встроенных сущностей, которые перечислены в табл 1.1.</p>
      <empty-line/>
      <p><emphasis><strong>Таблица 1.1.</strong> Встроенные сущности XML</emphasis></p>
      <table>
       <tr>
        <th align="left">Имя сущности</th>
        <th align="left">Значение</th>
        <th align="left">Описание</th>
       </tr>
       <tr>
        <td align="left"><code>lt</code></td>
        <td align="left"><code>&lt;</code></td>
        <td align="left">знак "меньше"</td>
       </tr>
       <tr>
        <td align="left"><code>gt</code></td>
        <td align="left"><code>&gt;</code></td>
        <td align="left">знак "больше"</td>
       </tr>
       <tr>
        <td align="left"><code>amp</code></td>
        <td align="left"><code>&amp;</code></td>
        <td align="left">амперсант</td>
       </tr>
       <tr>
        <td align="left"><code>apos</code></td>
        <td align="left"><code>'</code></td>
        <td align="left">апостроф или одинарные кавычки</td>
       </tr>
       <tr>
        <td align="left"><code>quot</code></td>
        <td align="left"><code>"</code></td>
        <td align="left">двойные кавычки</td>
       </tr>
      </table>
      <p>Встроенные сущности могут быть использованы для замены некоторых символов там, где они могут быть восприняты, как разметка. В частности, символы <code>&lt;</code> (знак "меньше") и <code>&amp;</code> (амперсант) вообще не могут появляться в тексте документа иначе, кроме как в виде сущностей.</p>
      <subtitle>Пример</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code></p>
      <p><code>&lt;advert&gt;</code></p>
      <p><code> &lt;product title="слон"&gt;</code></p>
      <p><code>  Продается серый слон весом &amp;gt; 5 тонн!</code></p>
      <p><code>  Компания &amp;quot;слон &amp;amp; Слон&amp;quot;.</code></p>
      <p><code> &lt;/product&gt;</code></p>
      <p><code>&lt;/advert&gt;</code></p>
      <p>На самом же деле в элементе <code>product</code> заключен текст</p>
      <p><code>Продается серый слон весом &gt; 5 тонн!</code></p>
      <p><code>Компания "Слон &amp; Слон".</code></p>
      <p>Довольно часто бывает необходимо использовать в документе символы набора Unicode, обращаясь к ним по десятичным или шестнадцатеричным кодам. В таких случаях можно использовать символьные сущности.</p>
      <p>Символьная сущность (или, как ее еще называют, символьная ссылка) записывается в виде <code>&amp;#<emphasis>код</emphasis>;</code> или <code>&amp;#x<emphasis>код;</emphasis></code>, где <code><emphasis>код</emphasis></code> — десятеричный и шестнадцатеричный Unicode-код символа в первом и втором случае соответственно.</p>
      <subtitle>Пример</subtitle>
      <p>Фраза "<code>Миру-мир!</code>" может быть записана с использованием символьных сущностей следующим образом:</p>
      <p><code>&amp;#х41С;&amp;#х438;&amp;#х440;&amp;#х443; - &amp;#1084;&amp;#1080;&amp;#1088;!</code></p>
      <p>Первое слово, "<code>Миру</code>" записано с использованием шестнадцатеричных unicode-кодов кириллицы, второе слово, "<code>мир</code>", записано с использованием десятичных кодов.</p>
      <p>Внешние сущности содержатся во внешних файлах. Если ссылка на внешнюю сущность появляется в документе, то на ее место копируется содержимое внешнего файла.</p>
      <p>Определение внешней сущности имеет следующий синтаксис:</p>
      <p><code>&lt;!ENTITY <emphasis>имя</emphasis> SYSTEM "<emphasis>URI</emphasis>"&gt;</code></p>
      <p>В этом определении <code><emphasis>имя</emphasis></code> точно так же, как и во внутренней сущности определяет имя сущности, в то время как <code><emphasis>URI</emphasis></code> определяет абсолютное или относительное местоположение файла.</p>
      <subtitle>Пример</subtitle>
      <p>Предположим, что мы создали файл <code>animal.ent</code> со следующим содержанием:</p>
      <p><code>огромное серое животное</code></p>
      <p>Для того чтобы использовать содержимое этого файла в документе, мы должны объявить внешнюю сущность следующим образом:</p>
      <p><code>&lt;!ENTITY animal SYSTEM "ent/animal.ent"&gt;</code></p>
      <p>где <code>ent/animal</code> есть относительный путь до файла <code>animal.ent</code>. Если бы мы расположили файл на сервере, скажем, <code>www.animalhost.com</code>, сущность могла бы быть объявлена как</p>
      <p><code>&lt;!ENTITY animal SYSTEM "http://www.animalhost.com/animal.ent"&gt;</code></p>
      <p>В документе ссылаться на объявленную внешнюю сущность мы будем точно так же, как ссылались бы на внутреннюю сущность:</p>
      <p><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code></p>
      <p><code>&lt;!DOCTYPE advert [</code></p>
      <p><code> &lt;!ENTITY animal SYSTEM "ent/animal.ent"&gt;</code></p>
      <p><code>]&gt;</code></p>
      <p><code>&lt;advert&gt;</code></p>
      <p><code> &lt;product title="слон"&gt;</code></p>
      <p><code>  Продается &amp;animal; весом &amp;gt; 5 тонн!</code></p>
      <p><code>  Рождественские скидки!</code></p>
      <p><code> &lt;/product&gt;</code></p>
      <p><code>&lt;/advert&gt;</code></p>
      <p>В этом случае элемент <code>product</code> будет иметь текст</p>
      <p><code>Продается огромное серое животное весом &gt; 5 тонн!</code></p>
      <p><code>Рождественские скидки!</code></p>
      <p>Внешняя сущность может быть также объявлена при помощи так называемого публичного идентификатора. В этом случае, при объявлении указывается не только местоположение сущности, но еще и идентификатор, который предоставляет программному обеспечению, обрабатывающему документ, некоторую дополнительную информацию. Например, в некоторых случаях XML-процессор может уже включать в себя определение внешней сущности, и ему не нужно будет получать содержимое файла, находящегося на удаленном сервере.</p>
      <p>Такой способ определения внешней сущности имеет следующий синтаксис:</p>
      <p><code>&lt;!ENTITY <emphasis>имя</emphasis> PUBLIC "<emphasis>идентификатор</emphasis>" "<emphasis>URL</emphasis>"&gt;</code></p>
      <p>Например, сущность <code>animal</code> мы можем переопределить как</p>
      <p><code>&lt;!ENTITY animal PUBLIC "-//ZOO//Elephant//Description"</code></p>
      <p><code> "http://www.animalhost.com/animal.ent"&gt;</code></p>
      <p>Специальный процессор зоологических XML-файлов, встретив публичный идентификатор <code>-//ZOO//Elephant//Description</code> поймет, что речь идет о слоне, и не станет загружать файл <code>animal.ent</code> с удаленного сервера, вставив собственное описание слона.</p>
      <p>Подводя итог, можно выделить следующие случаи, когда следует использовать сущности:</p>
      <p>&#9633; замена часто повторяющихся частей документа;</p>
      <p>&#9633; разбивка одного XML-документа на отдельные модули;</p>
      <p>&#9633; замена некоторых символов, которые иначе были бы восприняты, как разметка;</p>
      <p>&#9633; использование символов с соответствующими кодами Unicode.</p>
      <p>Синтаксис использования сущностей в тексте документа довольно прост. Символьная сущность определяется продукцией <code>CharRef</code> следующим образом:</p>
      <p><code>[66] CharRef ::= '&amp;#' [0-9]+ ';' | "&amp;#x' [0-9a-fA-F]+ ';'</code></p>
      <p><code>CharRef</code> — это либо десятичная, либо шестнадцатеричная символьная сущность. В первом случае вместо имени сущности стоит набор, цифр от <code>0</code> до <code>9</code>, во втором — к этому набору добавляются буквы <code>a</code>, <code>b</code>, <code>c</code>, <code>d</code>, <code>e</code>, <code>f</code> в любом регистре символов. Ведущие нули не имеют никакого значения, <code>&amp;#х0020;</code> точно так же, как и <code>&amp;#х20;</code> соответствует пробельному символу.</p>
      <p>Обычной сущности, объявленной внутри или вне документа, соответствует продукция <code>EntityRef</code>:</p>
      <p><code>[68] EntityRef ::= '&amp;' Name</code></p>
      <p>Символьная и обычная сущности объединяются в продукцию <code>Reference</code>:</p>
      <p><code>[67] Reference ::= EntityRef | CharRef</code></p>
      <p>Здесь следует сделать небольшое отступление и сказать о том, что конструкции вида <code>&amp;<emphasis>имя</emphasis>;</code> или <code>&amp;#x<emphasis>код</emphasis>;</code>, о которых мы говорили как о сущностях, на самом деле являются не сущностями, а <emphasis>ссылками</emphasis> на сущности. <code>&amp;#x<emphasis>код</emphasis>;</code> — это ссылка на символьную, а <code>&amp;<emphasis>имя</emphasis>;</code> — на обычную сущность. Сама сущность — это именованный объект, к которому обрабатывающая программа должна обращаться при обработке ссылки с соответствующим именем. Однако, поскольку связь между сущностью и ссылкой на нее однозначна (одно не существует без другого), сами ссылки очень часто называют сущностями. Название продукции <code>Reference</code> переводится с английского как "ссылка", но пониматься в данном контексте может, в том числе, и как сущность.</p>
      <p>Определение обычной сущности соответствует следующей продукции:</p>
      <p><code>[71] GEDecl ::= '&lt;!ENTITY' S Name S EntityDef S? '&gt;'</code></p>
      <p><code>Name</code>, как обычно, определяет имя, a <code>EntityDef</code>, соответственно, значение сущности. Это значение может быть задано как внутри документа (первый вариант выбора, <code>EntityValue</code>), так и вне его (второй вариант, <code>ExternalID NDataDecl?</code>).</p>
      <p><code>[73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)</code></p>
      <p><code>EntityValue</code> — это всего лишь символьное значение, взятое в кавычки.</p>
      <p>Второй вариант синтаксиса <code>EntityDef</code> соответствует определению внешней сущности, то есть сущности, определение которой не содержится в самом документе.</p>
      <p>Внешние сущности могут быть двух типов:</p>
      <p>&#9633; разбираемые внешние сущности (англ. parsed entity) — данные, которые воспринимаются и обрабатываются как XML;</p>
      <p>&#9633; неразбираемые внешние сущности (англ. unparsed entity) — данные не-XML типа (например, изображения или бинарные файлы, которые необходимо использовать в данном документе).</p>
      <p>Неразбираемые сущности определяются наличием нетерминала <code>NDataDecl</code> в определении.</p>
      <p><code>[76] NdataDecl ::= S 'NDATA' S Name</code></p>
      <p>Мы до сих пор не упомянули еще один важный случай сущности — параметризованные сущности или сущности-параметры. Сущности этого типа используются в DTD для более гибкого описания логической структуры документа.</p>
      <p>Синтаксически сущности-параметры очень похожи на обычные сущности. При объявлении и использовании сущности-параметра ее имени должен предшествовать символ '<code>%</code>'. Отличием сущностей-параметров является то, что они определяются и используются только внутри DTD.</p>
      <subtitle>Пример</subtitle>
      <p>В качестве примера объявим параметризованную сущность <code>coords</code>, которую впоследствии будем использовать в определениях элементов:</p>
      <p><code>&lt;!ENTITY % coords "x, y, z"&gt;</code></p>
      <p>Используя объявленную сущность-параметр, элемент <code>sphere</code>, состоящий из элементов <code>x</code>, <code>y</code>, <code>z</code> (координаты сферы) и <code>R</code> (радиус), можно определить следующим образом:</p>
      <p><code>&lt;!ELEMENT sphere (%coords;, R)&gt;</code></p>
      <p>Такое определение равносильно определению <code>&lt;!ELEMENT sphere (x, y, z, r) &gt;</code>, но при этом оно является гораздо более гибким — если в новой версии создаваемого XML-языка вдруг произойдет смена регистра имен элементов <code>x</code>, <code>y</code> и <code>z</code> на <code>X</code>, <code>Y</code> и <code>Z</code>, декларацию типа документа изменять не придется.</p>
      <p>Сущности-параметры широко используются в спецификациях Консорциума W3. Язык XSLT тоже имеет свою декларацию типа документа, но ее невозможно будет понять, не понимая механизма сущностей-параметров.</p>
      <p>Синтаксис использования сущности-параметра (вернее, ссылки на нее) соответствует продукции <code>PEReference</code>, которая практически совпадает с продукцией <code>EntityRef</code>:</p>
      <p><code>[69] PEReference ::= '%' Name ';'</code></p>
      <p>Определение сущности-параметра также очень схоже с определением обычной сущности:</p>
      <p><code>[72] PEDecl ::= '&lt;!ENTITY' S '%' S Name S PEDef S? '&gt;'</code></p>
      <p><code>[74] PEDef  ::= EntityValue | ExternalID</code></p>
      <p>Продукция <code>EntityDecl</code>, соответствующая определению сущности, как обычной, так и сущности-параметра, имеет следующий вид:</p>
      <p><code>[70] EntityDecl ::= GEDecl | PEDecl</code></p>
      <p>Напомним, что <code>GEDecl</code> соответствует объявлению обычной, a <code>PEDecl</code> — параметризованной сущности.</p>
     </section>
     <section>
      <title>
       <p>Определение нотации</p>
      </title>
      <p>С точки зрения физической модели, XML-документы являются не более чем текстом. Содержимое документов и их разметка имеет исключительно текстовый вид. Вместе с тем, во многих случаях документы должны включать данные других форматов, например, графические изображения или двоичные файлы. Несовместимость физической реализации XML и внешних данных такого типа не позволяет включать их в документ посредством обычных сущностей — для этих целей используются неразбираемые сущности и нотации.</p>
      <p><emphasis>Нотация</emphasis> — это ни что иное, как определение формата неразбираемой сущности. Нотация дает формату имя и предоставляет некоторую информацию о приложении, которое следует использовать для обработки этого формата.</p>
      <subtitle>Пример</subtitle>
      <p>Предположим, что мы используем графические изображения в формате <code>GIF</code>, для просмотра которых используется приложение <code>gif-viewer.exe</code>. Определение нотации будет иметь следующий вид:</p>
      <p><code>&lt;!NOTATION GIF SYSTEM "gif-viewer.ехе"&gt;</code></p>
      <p>Эта запись определяет нотацию с именем <code>GIF</code> и указывает имя приложения, которое может быть использовано для обработки внешних сущностей этого формата.</p>
      <p>Информация о вспомогательном приложении-обработчике (англ. helper application) указывается при определении нотации системным или публичным идентификатором. В отличие от определения внешней сущности, публичный идентификатор в нотации может указываться без системного идентификатора. Фактически, нотация имеет три варианта определения:</p>
      <p><code>&lt;!NOTATION <emphasis>имя</emphasis> SYSTEM "<emphasis>системный ид-р</emphasis>"&gt;</code></p>
      <p><code>&lt;!NOTATION <emphasis>имя</emphasis> PUBLIC "<emphasis>публичный ид-р</emphasis>" "<emphasis>системный ид-р</emphasis>"&gt;</code></p>
      <p><code>&lt;!NOTATION <emphasis>имя</emphasis> PUBLIC "<emphasis>публичный ид-р</emphasis>"&gt;</code></p>
      <p>Если информация о вспомогательном приложении несущественна, можно воспользоваться определением следующего вида:</p>
      <p><code>&lt;!NOTATION <emphasis>имя</emphasis> SYSTEM ""&gt;</code></p>
      <p>Существует два основных способа применения нотаций. Первый — объявление неразбираемых сущностей и использование их имен в атрибутах типа <code>ENTITY</code> или <code>ENTITIES</code>, второй — указание имени нотации в атрибуте типа <code>NOTATION</code> для того, чтобы задать формат данных, который содержит данный элемент.</p>
      <p>Первый способ можно продемонстрировать простым документом, который задает меню (листинг 1.5).</p>
      <subtitle>Листинг 1.5. Использование неразбираемых сущностей в атрибутах элементов</subtitle>
      <p><code>&lt;!DOCTYPE menu [</code></p>
      <p><code> &lt;!ELEMENT menu (menuitem*)&gt;</code></p>
      <p><code> &lt;!ELEMENT menuitem EMPTY&gt;</code></p>
      <p><code> &lt;!ATTLIST menuitem</code></p>
      <p><code>  image ENTITY #REQUIRED</code></p>
      <p><code>  title CDATA #REQUIRED</code></p>
      <p><code>  href CDATA #REQUIRED&gt;</code></p>
      <p><code> &lt;!NOTATION gif SYSTEM "gif-viewer.exe"&gt;</code></p>
      <p><code> &lt;!NOTATION jpg SYSTEM "jpg-viewer.exe"&gt;</code></p>
      <p><code> &lt;!ENTITY news SYSTEM "news.gif" NDATA gif&gt;</code></p>
      <p><code> &lt;!ENTITY products SYSTEM "prod.jpg" NDATA jpg&gt;</code></p>
      <p><code> &lt;!ENTITY support SYSTEM "support.gif" NDATA gif&gt;</code></p>
      <p><code>]&gt;</code></p>
      <p><code>&lt;menu&gt;</code></p>
      <p><code> &lt;menuitem image="news" title="News" href="news.htm"/&gt;</code></p>
      <p><code> &lt;menuitem image="products" title="Products" href="prods.htm"/&gt;</code></p>
      <p><code> &lt;menuitem image="support" title="Support" href="support.htm"/&gt;</code></p>
      <p><code>&lt;/menu&gt;</code></p>
      <p>Проанализируем декларацию типа этого документа.</p>
      <p>&#9633; Декларация типа <code>&lt;!DOCTYPE menu [..] &gt;</code> говорит о том, что корневым элементом этого документа является элемент <code>menu</code>.</p>
      <p>&#9633; В соответствии с определением <code>&lt;!ELEMENT menu (menuitem* )&gt;</code> этот элемент состоит из нескольких субэлементов <code>menuitem</code>.</p>
      <p>&#9633; В соответствии с определением <code>&lt;!ELEMENT menuitem EMPTY&gt;</code> элемент <code>menuitem</code> должен быть пустым.</p>
      <p>&#9633; Запись <code>&lt;!ATTLIST menuitem ... &gt;</code> определяет в элементе <code>menuitem</code> следующие атрибуты:</p>
      <p> • обязательный атрибут <code>image</code>, в котором должно указываться имя сущности;</p>
      <p> • обязательный атрибут <code>title</code>, содержащий символьные данные;</p>
      <p> • обязательный атрибут <code>href</code>, содержащий символьные данные.</p>
      <p>&#9633; Запись <code>&lt;!NOTATION gif SYSTEM "gif-viewer.exe"&gt;</code> определяет нотацию с именем <code>gif</code> и закрепляет за ней приложение <code>gif-viewer.exe</code>.</p>
      <p>&#9633; Запись <code>&lt;!NOTATION jpg SYSTEM "jpg-viewer.ехе"&gt;</code> определяет нотацию с именем <code>jpg</code> и закрепляет за ней приложение <code>jpg-viewer.exe</code>.</p>
      <p>&#9633; Запись <code>&lt;!ENTITY news SYSTEM "news.gif" NDATA gif&gt;</code> определяет внешнюю неразбираемую сущность с именем <code>news</code>, которая имеет формат (нотацию) <code>gif</code>.</p>
      <p>&#9633; Запись <code>&lt;!ENTITY products SYSTEM "prod.jpg" NDATA jpg&gt;</code> определяет внешнюю неразбираемую сущность с именем <code>products</code>, которая имеет нотацию <code>jpg</code>.</p>
      <p>&#9633; Запись <code>&lt;!ENTITY support SYSTEM "support.gif" NDATA gif&gt;</code> определяет внешнюю неразбираемую сущность с именем <code>support</code>, которая имеет нотацию <code>gif</code>.</p>
      <p>Посмотрим теперь, какую информацию нам дают такие громоздкие определения. Обратимся к записи одного из элементов <code>menuitem</code>:</p>
      <p><code>&lt;menuitem image="products" title="Products" href="prods.htm"/&gt;</code></p>
      <p>С атрибутами <code>title</code> и <code>href</code> все ясно: они содержат простые символьные данные. Атрибут <code>image</code> несколько сложнее, он предоставляет гораздо больше информации. Типом этого атрибута является <code>ENTITY</code>, значит текст, который он содержит, является не просто символьными данными: он задает имя сущности, связанной с данным атрибутом. Иначе говоря, с атрибутом <code>image</code> связывается сущность.</p>
      <p>Анализируя определение сущности <code>products</code>, обрабатывающая программа может понять, что это — неразбираемая внешняя сущность формата <code>jpg</code>, которая хранится в файле <code>prod.jpg</code> и для обработки которой можно использовать приложение <code>jpg-viewer.exe</code>.</p>
      <p>Вторым способом использования нотаций является присвоение определенного формата содержимому элемента. Один (но не более чем один) из атрибутов элемента может иметь тип <code>NOTATION</code>. Значением этого атрибута должно быть имя нотации, которое и будет задавать формат содержимого элемента.</p>
      <subtitle>Пример</subtitle>
      <subtitle>Листинг 1.6. Использование нотаций для определения формата содержимого элемента</subtitle>
      <p><code>&lt;!DOCTYPE root [</code></p>
      <p><code> &lt;!ELEMENT root (#PCDATA)&gt;</code></p>
      <p><code> &lt;!ATTLIST root</code></p>
      <p><code>  type NOTATION (rtf|htm|txt) #REQUIRED&gt;</code></p>
      <p><code> &lt;[NOTATION rtf SYSTEM "winword.exe"&gt;</code></p>
      <p><code> &lt;!NOTATION htm SYSTEM "iexplore.exe"&gt;</code></p>
      <p><code> &lt;!NOTATION txt SYSTEM "notepad.exe"&gt;</code></p>
      <p><code>]&gt;</code></p>
      <p><code>&lt;root type="htm"&gt;</code></p>
      <p><code> &lt;![CDATA[</code></p>
      <p><code>  &lt;html&gt;</code></p>
      <p><code>   &lt;head&gt;</code></p>
      <p><code>    ...</code></p>
      <p><code>   &lt;/head&gt;</code></p>
      <p><code>   &lt;body&gt;</code></p>
      <p><code>    ...</code></p>
      <p><code>   &lt;/body&gt;</code></p>
      <p><code>  &lt;/html&gt;]]&gt;</code></p>
      <p><code>&lt;/root&gt;</code></p>
      <p>В этом документе определяется три нотации, три формата данных: <code>rtf</code>, <code>htm</code> и <code>txt</code>. Атрибут <code>type</code> элемента <code>root</code> указывает формат данных, которые содержатся в этом элементе — в данном случае это <code>"htm"</code> (что, очевидно, соответствует HTML-документу).</p>
      <p>Несмотря на то, что нотации являются довольно мощным механизмом, ввиду очевидной сложности, широкого распространения их использование не получило. Почти того же самого эффекта можно добиться более простыми способами, например, используя в элементах дополнительные атрибуты.</p>
     </section>
    </section>
    <section>
     <title>
      <p>Символьные данные в XML-документах</p>
     </title>
     <section>
      <p>Каковы бы ни были структура и синтаксис текстового документа, основой его всегда являются символы. Для хранения и обработки текста на компьютерах, которые по своей природе являются цифровыми устройствами, каждому символу нужно поставить в соответствие числовой код.</p>
      <p>Проблема многих языков заключается в том, что для них существует несколько альтернативных кодировок символов. Например, для кириллицы существуют такие кодировки, как CP-866, KOI8-R, CP-1251, ISO-8859-5, кодовая страница Macintosh и другие, но вместе с тем не существует единого стандарта, принятого де-факто. В итоге, для того, чтобы быть уверенным, что документ будет прочтен, его нужно представлять в трех или четырех кодировках, что очень неудобно.</p>
      <p>Для того чтобы решить эти и некоторые другие проблемы, был создан стандарт Unicode. Unicode присваивает уникальный код любому символу, независимо от платформы, независимо от программы, независимо от языка. Символам кириллицы Unicode присваивает коды в диапазоне от <code>#x400</code> до <code>#x4ff</code>. Таблица кодов для кириллицы может быть найдена в формате PDF на Web-сайте Unicode:</p>
      <p><strong>http://www.unicode.org/charts/PDF/U0400.pdf</strong>.</p>
     </section>
     <section>
      <title>
       <p>Использование Unicode</p>
      </title>
      <p>Для описания символов сотен языков всего мира, а также других символьных обозначений (например, математических символов) Unicode позволяет использовать три формы кодирования — UTF-8, UTF-16 и UTF-32.</p>
      <subtitle>UTF-8</subtitle>
      <p>В UTF-8 символы разных диапазонов кодируются последовательностями, состоящими из разного количества байт в соответствии со следующими правилами.</p>
      <p>&#9633; Символы с кодами в интервале <code>#x0</code>–<code>#x7F</code> кодируются одним байтом, первый бит которого равен нулю.</p>
      <p>&#9633; Для остальных символов число байт определяется количеством ведущих единиц первого байта последовательности.</p>
      <p>&#9633; Два первые бита каждого последующего байта равны единице и нулю соответственно.</p>
      <p>&#9633; Все остальные биты используются для кодирования символа.</p>
      <p>В табл. 1.2 для каждого интервала символов показано количество байт, нужных для кодирования символа, форма кодирования и количество бит, доступных для кода.</p>
      <empty-line/>
      <p><emphasis><strong>Таблица 1.2</strong>. Формы кодирования символов в UTF-8</emphasis></p>
      <table>
       <tr>
        <th align="left">Диапазон</th>
        <th align="left">Кол-во байт</th>
        <th align="left">Форма кодирования</th>
        <th align="left">Кол-во бит</th>
       </tr>
       <tr>
        <td align="left"><code>#x0-#x7F</code></td>
        <td align="left">1</td>
        <td align="left">0xxxxxxx</td>
        <td align="left">7</td>
       </tr>
       <tr>
        <td align="left"><code>#x80-#x7FF</code></td>
        <td align="left">2</td>
        <td align="left">110xxxxx 10xxxxxx</td>
        <td align="left">11</td>
       </tr>
       <tr>
        <td align="left"><code>#x800-#xFFFF</code></td>
        <td align="left">3</td>
        <td align="left">1110xxxx 10xxxxxx 10xxxxxx</td>
        <td align="left">16</td>
       </tr>
       <tr>
        <td align="left"><code>#x10000- #x1FFFFF</code></td>
        <td align="left">4</td>
        <td align="left">11110xxx 10xxxxxx 10xxxxxx 10xxxxxx</td>
        <td align="left">21</td>
       </tr>
      </table>
      <p>К примеру, символу "<code>Э</code>" (заглавной русской букве "<code>Э</code>") Unicode присваивает код <code>#x42D</code> или <code>10000101101</code> в двоичном представлении. Это значение входит в интервал <code>#x80-#x7ff</code>, значит, для кодирования нужно использовать двух-байтовую форму вида <code>110xxxxx 10xxxxxx</code>, где символы "<code>x</code>" обозначают 11 бит, доступных для кодировки. Таким образом, данному символу будет соответствовать следующий двоичный код:</p>
      <p><code><strong>110</strong><emphasis>10000 </emphasis><strong>10</strong><emphasis>101101</emphasis></code></p>
      <p>или <code>#xD0AD</code> в шестнадцатеричном представлении.</p>
      <p>Полужирным шрифтом выделены управляющие биты UTF-8 (<code><strong>110</strong></code> означает, что символ закодирован двухбайтной последовательностью, <code><strong>10</strong></code> определяет второй байт последовательности), курсивом — биты кода символа.</p>
      <p>Удобство UTF-8 заключается в том, что кодировка первых 127 символов совпадает с широко распространенной 7-битной кодировкой ASCII. Это делает возможным использование уже существующего программного обеспечения для обработки текста в UTF-8, например текстовых редакторов.</p>
      <subtitle>UTF-16</subtitle>
      <p>Для записи наиболее часто используемых символов с кодами, меньшими <code>#xFFFF</code>, UTF-16 использует двухбайтные последовательности, в которых каждый бит соответствует биту кода. Помимо этого, в UTF-16 могут быть также представлены символы с кодами в диапазоне <code>#10000-#FFFFF</code>. Для кодирования этих символов в UTF-16 применяются пары 16-битных значений в интервале <code>#xD800-#xDFFF</code> (ранее зарезервированные Unicode), называемые суррогатными парами (surrogate pairs). Младшие 10 бит каждого значения отводятся на кодировку символа, что в итоге дает 20 бит, достаточных для записи любого кода, не превышающего <code>#xFFFFF</code> (табл. 1.3).</p>
      <empty-line/>
      <p><emphasis><strong>Таблица 1.3</strong>. Формы кодирования символов в UTF-16</emphasis></p>
      <table>
       <tr>
        <th align="left">Диапазон</th>
        <th align="left">Кол-во байт</th>
        <th align="left">Форма кодирования</th>
        <th align="left">Кол-во бит</th>
       </tr>
       <tr>
        <td align="left"><code>#x0-#xD7FF</code></td>
        <td align="left">2</td>
        <td align="left"><code>xxxxxxxx xxxxxxxx</code></td>
        <td align="left">16</td>
       </tr>
       <tr>
        <td align="left"><code>#xD800-#xDFFF</code></td>
        <td/>
        <td align="left"><emphasis>Зарезервированы</emphasis></td>
        <td/>
       </tr>
       <tr>
        <td align="left"><code>#xE000-#xFFFF</code></td>
        <td align="left">2</td>
        <td align="left"><code>xxxxxxxx xxxxxxxx</code></td>
        <td align="left">16</td>
       </tr>
       <tr>
        <td align="left"><code>#x10000-#xFFFFF</code></td>
        <td align="left">4</td>
        <td align="left"><code>110110xxxxxxxxxx 110110xxxxxxxxxx</code></td>
        <td align="left">20</td>
       </tr>
      </table>
      <subtitle>Примеры</subtitle>
      <p>Символ "<code>Э</code>" с кодом <code>#x42D</code> будет записан в UTF-16 в виде последовательности из двух байт — <code>#x042D</code>.</p>
      <p>Для символа с кодом <code>#x153DC</code> (в двоичном представлении — <code>10101001111011100</code>) понадобится 4 байта. Он будет записан в виде</p>
      <p><code><strong>110110</strong><emphasis>0001010100 </emphasis><strong>110110</strong><emphasis>1111011100</emphasis></code></p>
      <p>или <code>#xD854DBDC</code> в шестнадцатеричном исчислении.</p>
      <p>Полужирным шрифтом выделены управляющие биты UTF-16, курсивом — биты кода символа.</p>
      <subtitle>UTF-32</subtitle>
      <p>UTF-32 является самой простой формой кодирования — для каждого символа, вне зависимости от диапазона, используются 4 байта. Такой способ, несомненно, не является самым экономичным с точки зрения объема хранимой информации, но во многих случаях предоставляет определенные преимущества при обработке текста, так как символы не нужно декодировать.</p>
     </section>
     <section>
      <title>
       <p>Коды некоторых символов Unicode</p>
      </title>
      <p>В таблицах символов Unicode кодируются не только символы и знаки различных языков, но также и некоторые управляющие символы, например, неразрываемый пробел (no-break space), табуляция, перенос строки и так далее. Коды некоторых из этих символов, часто использующихся в XML-технологиях, мы приводим в табл. 1.4.</p>
      <empty-line/>
      <p><emphasis><strong>Таблица 1.4</strong>. Unicode-коды некоторых символов</emphasis></p>
      <table>
       <tr>
        <th align="left">Код</th>
        <th align="left">Обозначение</th>
        <th align="left">Описание</th>
       </tr>
       <tr>
        <td align="left"><code>#х9</code></td>
        <td align="left"><code>[НТ]</code></td>
        <td align="left">Горизонтальная табуляция (horizontal tabulation)</td>
       </tr>
       <tr>
        <td align="left"><code>#xA</code></td>
        <td align="left"><code>[LF]</code></td>
        <td align="left">Перевод строки (line feed)</td>
       </tr>
       <tr>
        <td align="left"><code>#xD</code></td>
        <td align="left"><code>[CR]</code></td>
        <td align="left">Возврат каретки (carriage return)</td>
       </tr>
       <tr>
        <td align="left"><code>#x20</code></td>
        <td align="left"><code>[SP]</code></td>
        <td align="left">Пробел (space)</td>
       </tr>
       <tr>
        <td align="left"><code>#x21</code></td>
        <td align="left"><code>!</code></td>
        <td align="left">Восклицательный знак (exclamation sign)</td>
       </tr>
       <tr>
        <td align="left"><code>#x22</code></td>
        <td align="left"><code>"</code></td>
        <td align="left">Двойные кавычки (quotation mark)</td>
       </tr>
       <tr>
        <td align="left"><code>#x26</code></td>
        <td align="left"><code>&amp;</code></td>
        <td align="left">Амперсант (ampersand)</td>
       </tr>
       <tr>
        <td align="left"><code>#x27</code></td>
        <td align="left"><code>'</code></td>
        <td align="left">Апостроф или одинарные кавычки (apostrophe)</td>
       </tr>
       <tr>
        <td align="left"><code>#x3C</code></td>
        <td align="left"><code>&lt;</code></td>
        <td align="left">Знак "меньше" или левая угловая скобка (less-than sign)</td>
       </tr>
       <tr>
        <td align="left"><code>#x3F</code></td>
        <td align="left"><code>?</code></td>
        <td align="left">Вопросительный знак (question mark)</td>
       </tr>
       <tr>
        <td align="left"><code>#xA0</code></td>
        <td align="left"><code>[NBSP]</code></td>
        <td align="left">Неразрываемый пробел (no-break space)</td>
       </tr>
      </table>
      <p>Коды многих других символов можно найти на Web-сайте Unicode Consortium в разделе Code Charts: <strong>http://www.unicode.org/charts/</strong>.</p>
     </section>
    </section>
    <section>
     <title>
      <p>Базовые продукции XML</p>
     </title>
     <p>Теперь, когда мы разобрали модель символов Unicode, которая используется в XML, можно дать EBNF-определения основных базовых конструкций языка — символов, имен, именных токенов и их последовательностей.</p>
     <p>В XML можно использовать любые символы Unicode, кроме суррогатных блоков и символов с кодами <code>#xFFFE</code> и <code>#xFFFF</code>:</p>
     <p><code>[2] Char ::= #x9 | #xA | #xD | [#x20 - #xD7FF]</code></p>
     <p><code>             | [#хЕ000 - #xFFFD) | [#х10000 - #x10FFFF]</code></p>
     <p>Для удобства все множество символов разделено на несколько категорий.</p>
     <p>&#9633; Буквы, которые соответствуют продукции <code>Letter</code>, в свою очередь, делятся на основные (<code>BaseChar</code>) и идеографические (<code>Ideographic</code>). Буквы относятся к алфавитам, из которых состоят слова различных языков. Продукции букв чрезвычайно просты, но громоздки, поскольку перечисляют символы различных алфавитов. Читатель может легко найти их в технической рекомендации XML по адресу <strong>http://www.w3.org/TR/REC-xml.html</strong> под номерами [84] (<code>Letter</code>), [85] (<code>BaseChar</code>) и [86] (<code>Ideographic</code>).</p>
     <p>&#9633; Цифры, которые составляют в различных культурах числа. Цифры определяются продукцией <code>Digit</code> с номером [88].</p>
     <p>&#9633; Модифицирующие символы (<code>CombiningChar</code>), которые изменяют написание или звучание символов, как, например, #x308 — двойная точка сверху символа, которая используется для обозначения умляута в немецком и для замены <code>e</code> на <code>ё</code> в русском языке. Продукция <code>CombiningChar</code> имеет номер [87].</p>
     <p>&#9633; Символы расширения (<code>Extender</code>). Продукция <code>Extender</code> имеет порядковый номер [89].</p>
     <p>Следующей простейшей символьной конструкцией является пробельное пространство <code>S</code>. Приведем еще раз его продукцию:</p>
     <p><code>[3] S ::= (#х9 | #хА | #xD | #x20)+</code></p>
     <p>Во многих продукциях XML-языков используются имена. Например, имена даются элементам, атрибутам, переменным XPath и так далее. В основе определения имени лежат именные символы <code>NameChar</code>:</p>
     <p><code>[4] NameChar ::= Letter | Digit | CombiningChar | Extender</code></p>
     <p><code>                 | '.' | '-' | '_' | ':'</code></p>
     <p>Имя начинается либо буквой, либо символами "<code>_</code>" или "<code>:</code>" и состоит из последовательности именных символов:</p>
     <p><code>[5] Name ::= (Letter | '_' | ' :') (NameChar*)</code></p>
     <p>В некоторых правилах XML используется последовательность имен, соответствующая продукции <code>Names</code>:</p>
     <p><code>[6] Names ::= Name (S Name)*</code></p>
     <p>Кроме того, техническая рекомендация определяет так называемый именной токен <code>NmToken</code> — строку, которая может состоять из одного или более именных символов и последовательности таких токенов, <code>NmTokens</code>.</p>
     <p><code>[7] NmToken  ::= (NameChar)+</code></p>
     <p><code>[8] NmTokens ::= NmToken (S NmToken)*</code></p>
     <p>Символьные данные могут заключаться в кавычки для того, чтобы формировать литералы. В XML определены следующие литералы: значение сущности (<code>EntityValue</code>), значение атрибута (<code>AttValue</code>), системный литерал (<code>SystemLiteral</code>), а также <code>PubidLiteral</code> — литерал, определяющий публичный идентификатор ресурса (<emphasis>см. раздел "Определение сущности" данной главы</emphasis>):</p>
     <p><code>[9] EntityValue    ::= '"' ([^%&amp;"] | PEReference | Reference)* '"'</code></p>
     <p><code>                       | "'" ([^%&amp;'] | PEReference | Reference)* "'"</code></p>
     <p><code>[10] AttValue      ::= '"' ([^&lt;&amp;"] | Reference)* '"'</code></p>
     <p><code>                       | ([^&lt;&amp;"] | Reference)* "'"</code></p>
     <p><code>[11] SystemLiteral ::= ('"' [^"]* '"')</code></p>
     <p><code>                       | ("'" [^']* "'")</code></p>
     <p><code>[12] PubidLiteral  ::= '"' PubidChar* '"'</code></p>
     <p><code>                       | "'" (PubidChar - "'")*</code></p>
     <p><code>[13] PubidChar     ::= #x20 | #xD | #xA</code></p>
     <p><code>                       | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]</code></p>
     <p>В литералах <code>EntityValue</code> и <code>AttValue</code> допустимо использовать продукции сущностей (<code>PEReference</code>, <code>Reference</code>). Это означает, что при определении значений сущностей и атрибутов можно использовать ссылки на сущности, например, в элементе заданном как:</p>
     <p><code>&lt;song title="Крейсер &amp;quot;Aвpopa&amp;quot; "/&gt;</code></p>
     <p>атрибут <code>title</code> имеет значение крейсер <code>"Аврора"</code>. Двойные кавычки были определены посредством встроенных сущностей.</p>
     <p>Символьные данные, которые задаются продукцией <code>CharData</code>, могут состоять из любых символов, кроме символов "<code>&lt;</code>" и "<code>&amp;</code>", которые используются в XML в качестве управляющих. <code>CharData</code> главным образом используется в секциях <code>CDATA</code>, и, соответственно, не может содержать терминирующую последовательность "<code>]]&gt;</code>".</p>
     <p><code>[14] CharData ::= [^&lt;&amp;]* - ([^&lt;&amp;]* ']]&gt;' [^&lt;&amp;]*)</code></p>
    </section>
    <section>
     <title>
      <p>XML-документы с точки зрения спецификации</p>
     </title>
     <p>Теперь, когда мы разобрали практически все структурные единицы XML, осталось определить стандартным образом синтаксис для самих XML-документов. Им соответствует продукция <code>document</code>:</p>
     <p><code>[1] document ::= prolog element Misc</code></p>
     <p>Итак, XML-документ состоит из пролога, единственного корневого элемента и дополнительного нетерминала <code>Misc</code>, который может включать инструкции по обработке, комментарии и пробельные символы:</p>
     <p><code>[27] Misc ::= Comment | PI | S</code></p>
     <p>Остановимся отдельно на прологе XML-документа. Пролог состоит из необязательной декларации XML (<code>XMLDecl</code>), необязательной декларации типа документа (<code>doctypedecl</code>), инструкций, комментариев и пробельных символов:</p>
     <p><code>[22] prolog ::= XMLDeci? Misc* (doctypedecl Misc*)?</code></p>
     <p>В зависимости от того, насколько строго документы соответствуют спецификации XML и собственным DTD-объявлениям, они могут быть <emphasis>хорошо оформленными</emphasis> (well-formed) и <emphasis>правильными</emphasis> (valid).</p>
     <p>Хорошо оформленный документ соответствует всем синтаксическим правилам XML и некоторым дополнительным ограничениям, например:</p>
     <p>&#9633; имя открывающего тега элемента должно совпадать с именем его закрывающего тега;</p>
     <p>&#9633; имена атрибутов элемента не должны повторяться;</p>
     <p>&#9633; в значении атрибута нельзя использовать символ "<code>&lt;</code>". Этот символ должен обязательным образом заменяться на сущность;</p>
     <p>&#9633; сущности должны быть определены до использования;</p>
     <p>&#9633; сущности-параметры могут быть использованы только в блоках DTD;</p>
     <p>&#9633; документ должен иметь единственный корневой элемент, содержащий все остальные элементы и символьные данные этого документа. Вне корневого документа допускаются только комментарии, инструкции по обработке, декларация XML и блок DTD.</p>
     <p>Правильные документы должны быть хорошо оформленными, и при этом их логическая структура должна удовлетворять объявлениям, которые содержатся в декларации типа документа (DTD).</p>
     <p>Для того чтобы документ мог быть обработан различными приложениями стандартным образом, он должен как минимум быть хорошо оформленным. Выполнение этого требования означает, что документ корректен с точки зрения синтаксиса, и для его логического представления можно использовать любую из стандартных моделей. Например, если в элементе документа приведены два атрибута с одинаковыми именами, возможно, с точки зрения автора, это логично и корректно, однако, стандартными средствами такой документ обработать не удастся.</p>
     <p>Требование правильности означает четкое соответствие выбранной логической схеме документа. Объявления декларации типа документа накладывают на логическую структуру документа определенные ограничения с тем, чтобы он мог быть стандартным образом обработан не только синтаксическими, но и семантическими процессорами, то есть программами, которые не только могут распознать синтаксис XML-документа, но и "понять" его смысл, переданный разметкой.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Использование технологии XML</p>
    </title>
    <section>
     <p>Вряд ли удастся описать все множество приложений и задач, в которых можно успешно применять XML-технологии, однако существуют области, в которых использование XML стало уже классикой. Чуть ниже мы рассмотрим несколько наиболее типичных классов задач XML.</p>
     <p>Пока же необходимо сказать следующее — несмотря на всю мощь XML, это далеко не панацея и не решение всех проблем, которые могут возникнуть. Нужно хорошо понимать, что XML — это всего лишь формат описания данных. Четкий, конкретный, независимый, мощный формат описания данных — но не более! XML-технологии могут решить проблемы представления, несоответствия синтаксиса семантике и многие другие проблемы организации данных в документе, но они не смогут решить чисто программистских задач — как обрабатывать эти документы. XML не имеет особого смысла вне прикладных задач.</p>
     <p>В качестве типичного примера можно привести язык XSLT (язык расширяемых стилей для преобразований, extensible Stylesheet Language for Transformations), который находится в фокусе этой книги. Программы, написанные на XSLT, называются преобразованиями, и они являются в прямом смысле XML-документами, но при этом удовлетворяют логической схеме языка XSLT. При этом преобразования не имели бы смысла без XSLT-процессора, который может применять их к другим документам. Они были бы просто текстом.</p>
     <p>Создание XML-документов без программного обеспечения, которое будет понимать их семантику — это все равно, что писать программы на языке программирования, для которого не существует трансляторов и интерпретаторов. Они могут быть безупречно корректными, но совершенно бесполезными.</p>
     <p>Стандартизированный и совсем не сложный синтаксис XML позволил многим компаниям разработать средства для синтаксического разбора XML-документов. Программы такого рода называют XML-парсерами (англ. parse — разбирать, анализировать). В настоящее время существует два основных типа XML-парсеров: SAX-парсеры и DOM-парсеры. Оба типа широко используются в различных приложениях — парсеры избавляют от необходимости писать собственные синтаксические анализаторы, штудировать спецификации и так далее. Мы коротко опишем каждый из этих типов.</p>
    </section>
    <section>
     <title>
      <p>SAX-парсеры</p>
     </title>
     <p>SAX расшифровывается как Simple API for XML, что означает буквально "Простой прикладной интерфейс программирования для XML". Это так и есть — идеология SAX очень проста. Программист должен описать, как следует обрабатывать ту или иную конструкцию документа, а парсер при обработке документа уже сам будет выполнять соответствующие действия. Иными словами, обработка документа производится в виде реакции на события, которые возникают, когда парсер встречает в документе тот или иной элемент, атрибут, комментарий и так далее.</p>
     <p>В отличие от DOM-парсеров, SAX-парсеры не создают никакого внутреннего представления документа, оставляя эту задачу на совести программиста. Вследствие этого SAX-парсеры менее требовательны к ресурсам, что часто бывает критичным. Однако это никак не сказывается на их функциональности, таким образом SAX-парсеры являются незаменимыми инструментами для синтаксического разбора XML-документов. Зачастую, более сложные DOM-парсеры используют SAX как составную часть.</p>
    </section>
    <section>
     <title>
      <p>DOM-парсеры</p>
     </title>
     <p>Как уже было упомянуто абзацем выше, легкие SAX-парсеры не создают внутреннего представления ХМL-документов, вполне справедливо считая, что этим придется заняться программисту.</p>
     <p>Вместе с тем, древовидная организация данных в ХМL-документах настолько очевидна, что внутренние представления, которые использовались в совершенно разных приложениях, совпадали практически в точности. Такая ситуация привела к решению разработать единый интерфейс не для обработчика документа, как это было сделано в SAX, а для внутреннего представления XML-документа целиком.</p>
     <p>Набор таких интерфейсов получил название DOM (document object model, объектная модель документа). DOM-парсер обрабатывает документ, создавая при этом его внутреннее объектное представление. При этом DOM содержит только определения интерфейсов, никоим образом не регулируя внутреннюю реализацию самой модели документа. Все обращения к данным и структуре, которыми обладает документ, происходят посредством вызова методов, определенных в соответствующих интерфейсах.</p>
     <p>Объектную модель документа полезно использовать там, где требуется работать с документом целиком, как с деревом. Представление всего документа будет занимать в памяти значительный объем, поэтому DOM резонно считается моделью, очень требовательной к ресурсам.</p>
     <p>При выборе парсера необходимо хорошо понимать задачи, которые нужно будет решать при обработке документа. Во многих случаях совершенно необязательно целиком представлять документ в памяти. Будет вполне достаточным создать обработчик документа, и затем, при помощи SAX-парсера, произвести обработку без особых затрат ресурсов. Если же, напротив, при обработке важно иметь модель всего документа целиком, лучше использовать готовое решение в виде DOM-парсера.</p>
    </section>
    <section>
     <title>
      <p>Основные классы задач XML</p>
     </title>
     <section>
      <p>В этой главе мы разберем несколько основных типов задач, для решения которых целесообразно применять XML. Естественно, этот список даже близко не претендует на полноту, так же, как нельзя, например, перечислить все программы, которые можно написать на языке Java. Несколько примеров предметных областей, которые будут приведены, иллюстрируют классические проблемы, с успехом решенные XML-технологиями.</p>
     </section>
     <section>
      <title>
       <p>Создание новых языков</p>
      </title>
      <p>Хотя мы и говорим об XML, как о формате описания данных, на самом деле XML — это <emphasis>метаязык</emphasis>, язык, который описывает другие языки. Строго говоря, когда мы создаем XML-документ, мы создаем его не на XML, а в соответствии с XML-синтаксисом. XML — это всего лишь набор синтаксических правил, не более. Настоящим языком в этой ситуации является то, что мы понимаем под логической, семантической схемой создаваемого документа.</p>
      <p>Таким образом, каждый раз, когда мы описываем логическую схему документа, мы создаем новый язык с придуманной нами семантикой и XML-синтаксисом. Достоинством XML в данном случае является стандартность этого синтаксиса, поскольку заботиться о создании модуля для синтаксического разбора (парсера) уже не нужно.</p>
      <p>Что же касается семантики языка, то во многих случаях древовидные XML-структуры очень хорошо подходят для ее описания, будь это язык формата документа или язык программирования.</p>
      <p>Главным недостатком XML является громоздкость синтаксиса. Например, арифметическое выражение <code>2*2</code> может быть выражено в XML приблизительно как:</p>
      <p><code>&lt;mul&gt;</code></p>
      <p><code> &lt;arg&gt;2&lt;/arg&gt;</code></p>
      <p><code> &lt;arg&gt;2&lt;/arg&gt;</code></p>
      <p><code>&lt;/mul&gt;</code></p>
      <p>Очевидно, что с человеческой точки зрения это не самый компактный и элегантный способ.</p>
      <p>На данный момент существует великое множество языков, созданных на основе XML. Мы перечислим несколько наиболее известных из них:</p>
      <p>&#9633; WML (Wireless Markup Language) — язык разметки для беспроводных устройств, основной формат данных для беспроводного протокола WAP;</p>
      <p>&#9633; SVG (Scalable Vector Graphics) — язык описания масштабируемой векторной графики;</p>
      <p>&#9633; XHTML — XML-совместимая версия языка гипертекстовой разметки документов;</p>
      <p>&#9633; SOAP (Simple Object Access Protocol) — XML-протокол для обмена информацией в распределенных системах;</p>
      <p>&#9633; RDF (Resource Description Framework) — система описания ресурсов;</p>
      <p>&#9633; XML/EDI (XML/Electronic Data Interchange) — XML-язык для представления сообщений EDI в системах В2В и электронной коммерции;</p>
      <p>&#9633; OML (Ontology Markup Language) — язык для описания онтологий и тезаурусов;</p>
      <p>&#9633; VoxML (Voice Markup Language) — язык разметки для голосовых приложений;</p>
      <p>&#9633; MathML (Mathematical Markup Language) — язык для описания математических выражений;</p>
      <p>&#9633; CML (Chemical Markup Language) — язык для описания химических формул;</p>
      <p>&#9633; UML exchange Format — XML-выражения языка UML (Unified Modeling Language);</p>
      <p>&#9633; CDF (Channel Description Format) — язык для описания данных для автоматической доставки клиенту (технология push-каналов).</p>
      <p>Несмотря на то, что XML это язык разметки, он вполне подходит для создания языков программирования. Самым лучшим примером является язык XSLT, которому посвящена эта книга. Кроме того, существует множество менее известных языков, например XML-версия функционального языка Lisp, язык HaXML и другие.</p>
     </section>
     <section>
      <title>
       <p>Хранение данных</p>
      </title>
      <p>Практические всегда, когда приложение должно хранить данные во внешних файлах, неизбежны два процесса: парсинг (синтаксический разбор) при считывании данных и сериализация (создание физического выражения состояния объектов) при сохранении (рис. 1.2).</p>
      <image l:href="#img_2.png"/>
      <p><strong>Рис. 1.2</strong>. Стандартная схема хранения данных</p>
      <p>Использование XML в приведенной выше схеме как формата хранения позволяет использовать вместо парсера и сериализатора стандартные XML-инструменты, так что необходимость писать что-то свое отпадает. Кроме того, поскольку сохраняемый в этом случае документ имеет XML-формат, приложение становится совершенно открытым для интеграции с другими системами, ведь обмен данными может быть осуществлен без каких-либо специальных конверторов (рис. 1.3).</p>
      <image l:href="#img_3.png"/>
      <p><strong>Рис. 1.3</strong>. Схема хранения данных в формате XML</p>
      <p>Помимо перечисленных выше достоинств предлагаемого способа следует упомянуть также и следующее:</p>
      <p>&#9633; хранимые в XML данные могут иметь практически любую сложность; она ограничена лишь концептуальной сложностью древовидных структур;</p>
      <p>&#9633; хранимые в XML данные можно снабжать метаинформацией (например, комментариями или инструкциями по обработке);</p>
      <p>&#9633; XML как формат пригоден даже для хранения двоичных данных, если они будут преобразованы в подходящую текстовую кодировку;</p>
      <p>&#9633; SAX и DOM/XPath-интерфейсы обеспечивают эффективный доступ к XML-данным.</p>
      <p>Противопоказаний к использованию XML в качестве формата хранения данных очень мало. Во-первых, разработчик может посчитать нерациональным включение объемных XML-библиотек в приложение размером в 10 Кбайт. Во-вторых, XML-формат это не самый компактный способ хранения данных. В-третьих, открытость внешним приложениям также может быть лишней.</p>
     </section>
     <section>
      <title>
       <p>Обмен данными и проекты интеграции</p>
      </title>
      <p>Большое количество систем, стандартов и технологий, о которых мы говорили ранее, приводит к тому, что эффективно связать разные источники данных в одну систему не получается. Даже такие, казалось бы, однородные источники, как системы управления базами данных, применяют языки запросов и форматы представления выбираемой информации, которые редко полностью совместимы между собой. Как следствие, проекты интеграции в таких условиях требуют больших усилий — требуется вникать в детали различных баз данных, протоколов, операционных систем и так далее.</p>
      <p>В результате интеграция нескольких приложений или систем реализуется по схеме, показанной на рис. 1.4.</p>
      <image l:href="#img_4.png"/>
      <p><strong>Рис. 1.4</strong>. Типичная схема интеграции нескольких приложений</p>
      <p>Несложно оценить трудозатраты подобного рода проекта. Заставить разные системы работать вместе — чрезвычайно трудоемкая задача.</p>
      <p>Идея использования XML в интеграции информационных систем сводится к созданию общего XML-языка, которым могла бы пользоваться каждая из них.</p>
      <p>Такое решение сразу же намного упрощает проект — ведь вместо реализации взаимодействия между каждой парой систем следует всего лишь научить каждую из них "говорить" на созданном XML-языке. Иначе говоря, все сводится к разработке нескольких врапперов (англ. wrapper — упаковщик, программное средство создания системной оболочки для стандартизации внешних обращений и изменения функциональной ориентации действующей системы), которые будут переводить со стандартного XML-языка интегрированной системы на язык, понятный каждой системе в отдельности.</p>
      <p>В принципе, интеграция по XML-схеме (рис. 1.5) не отличается коренным образом от интеграции на основе любого другого общего стандарта. Вместе с тем, она имеет целый ряд весомых преимуществ:</p>
      <p>&#9633; XML-языки не зависят от аппаратных и программных платформ, что позволяет связывать разнородные системы;</p>
      <p>&#9633; выразительная мощность XML достаточно велика для того, чтобы описать данные практически любой сложности;</p>
      <p>&#9633; средства разработки и стандартные библиотеки для XML существуют практически на всех платформах и для большинства популярных языков программирования;</p>
      <p>&#9633; методы работы с XML достаточно стандартны для того, чтобы в разных системах можно было пользоваться одинаковыми приемами;</p>
      <p>&#9633; информация, оформленная в виде XML, может обрабатываться не только машинами, но и человеком (что намного облегчает отладку).</p>
      <image l:href="#img_5.png"/>
      <p><strong>Рис. 1.5</strong>. Интеграция на основе XML</p>
     </section>
    </section>
   </section>
   <section>
    <title>
     <p>Краткая история XML</p>
    </title>
    <p>XML основывается на принципах и соглашениях двух существующих языков разметки, XML и SGML, каждый из которых получил широкое распространение и успешно использовался для решения своего круга задач.</p>
    <p>Несмотря на то, что идеи обобщенной разметки начали появляться еще в 60-х годах, SGML (standard generalized markup language, стандартный язык обобщенной разметки) был ратифицирован Международной Организацией Стандартизации (ISO) только в 1986 году. Возможно, будет показательным тот факт, что SGML не требовал изменений в течение, практически, 10 лет — настолько мощным инструментом он был.</p>
    <p>Вместе с тем, на определенном этапе мощь SGML стала становиться препятствием — этот язык был настолько сложен, что поддержка в приложениях даже основного его подмножества оказалась непростой задачей. Это сказывалось на скорости разработки, стабильности и стоимости приложений, и потому, все больше и больше экспертов высказывались за упрощение этого языка.</p>
    <p>Примерно в то же время произошел квантовый скачок в другой области информационных технологий. Развитие сетевых технологий вывело инфраструктуру обмена информации на качественно новый уровень, произведя на свет глобальную сеть Интернет. Интернет, в свою очередь, стал платформой для обмена гипертекстовыми документами, которые также нуждались в простом стандартном языке разметки для базового форматирования текста, создания таблиц и гиперссылок. Для этих целей был разработан HTML — язык разметки гипертекста (hypertext markup language).</p>
    <p>HTML основывался на синтаксисе SGML, принципы этой технологии были практически проигнорированы. Только намного позже HTML стал SGML- совместимым языком. Ограниченность и нерасширяемость HTML вела к тому, что производители браузеров (программ просмотра) вводили собственные, в большинстве случаев несовместимые, расширения, что в итоге привело к довольно плачевной ситуации в этой области.</p>
    <p>Потребность в улучшении HTML совпала с потребностью в упрощении SGML. В 1996 году Консорциум W3 (World Wide Web Consortium, W3C) поддержал группу Web SGML Activity, задачей которой было создание нового языка разметки, более мощного, чем HTML, но более простого, чем SGML.</p>
    <p>Разработка началась с определения десяти положений, которым должен был соответствовать новый язык. Хотя эти положения и не являются определяющими для уже созданного языка, они все еще включаются в официальную спецификацию XML (п. 1). Думается, будет довольно интересно сравнить первоначальные устремления с тем, что получилось на самом деле. Попытаемся подробнее рассмотреть десять положений XML.</p>
    <p>1. <emphasis>XML должен напрямую использоваться в сети Интернет</emphasis>. Возможно, XML еще долго не будет использоваться в Интернет, как основной язык разметки (сказывается огромная инертность технологий), но, во всяком случае, авторы попытались по максимуму учесть в XML особенности языка HTML.</p>
    <p>2. <emphasis>XML должен поддерживать разнообразные приложения</emphasis>. Как уже было описано выше, XML можно использовать в самых разных областях — тут сказывается мощь абстракции, которую предоставляет древовидные представления данных.</p>
    <p>3. <emphasis>XML должен быть совместим с SGML</emphasis>. XML был разработан, как подмножество языка SGML, и для его обработки можно использовать любые SGML-продукты.</p>
    <p>4. <emphasis>Разработка программ для обработки XML-документов не должна быть сложной задачей</emphasis>. Конструктивный синтаксис XML намного проще, по сравнению с SGML, а значит, XML-инструменты также проще разрабатывать и использовать в своих решениях.</p>
    <p>5. <emphasis>Количество необязательных особенностей XML должно быть как можно меньше, в идеале их не должно быть вовсе</emphasis>. Сложно сказать, насколько это положение было выполнено — ведь большинство особенностей в XML являются необязательными. С другой стороны, в XML, как правило, существует только один способ добиться желаемого эффекта — в этом смысле опций, действительно, немного.</p>
    <p>6. <emphasis>XML-документы должны быть понятны человеку, и при этом достаточно ясны</emphasis>. Как мы уже могли убедиться, XML-документы имеют простую и понятную форму.</p>
    <p>7. <emphasis>XML должен быть разработан быстро</emphasis>. Разработчикам понадобилось два года — с 1996 по 1998, чтобы создать XML — значительный срок для довольно простого языка.</p>
    <p>8. <emphasis>Спецификация XML должна быть формальной и лаконичной</emphasis>. Синтаксис языка XML однозначно определяется EBNF-правилами, а сама спецификация не имеет двояких толкований.</p>
    <p>9. <emphasis>XML-документы должны легко создаваться</emphasis>. Поскольку UTF-8, основная форма кодирования XML-документов, совместима с ASCII, для редактирования XML-документов можно использовать все множество инструментов для работы с обычными текстовыми файлами.</p>
    <p>10. <emphasis>Лаконичность разметки XML-документов не является важной</emphasis>. Язык SGML позволял авторам документов опускать части разметки в случаях, когда из контекста ясно, что там должно быть. Подобный принцип был использован в HTML, где в некоторых случаях можно опускать закрывающие теги, например, <code>&lt;/p&gt;</code>. Для того, чтобы облегчить обработку, XML не позволяет такой вольности.</p>
    <p>Главную роль в создании XML приписывают техническому гуру из фирмы Sun, Йону Босаку (Jon Bosak). Босак и его команда сделали с SGML примерно то же, что когда-то сделала команда, создававшая язык Java с языком С++. Язык был упрощен, сложные и редко использующиеся его особенности были упразднены. Первая спецификация языка, редакторами который были Тим Брэй (Tim Bray) и С.М. Шперберг-МакКвин (С.М. Sperberg-McQueen), в общей сложности насчитывала 26 страниц, что примерно в 20 раз меньше по объему стандарта SGML.</p>
    <p>В октябре 2000 года с небольшими изменениями была принята вторая редакция спецификации языка XML. Судя по всему, язык оказался настолько удачным, что пройдет довольно значительное время прежде, чем он будет изменен.</p>
    <p>Будущее XML практически гарантировано. Несмотря на всю поднятую маркетинговую шумиху, в которой XML — не более чем "buzzword", расхожее словечко, нельзя игнорировать два следующих обстоятельства. Во-первых, без сомнения, существует огромная потребность в простом языке обобщенной разметки, и, во-вторых, у XML просто нет конкурентов. Большие компании уже приняли XML, как стандартное средство, в составе многих своих решений, и вряд ли какая другая технология сможет в скором времени вытеснить этот язык.</p>
    <p>Вместе с тем, было бы ошибкой считать, что XML пришел на замену HTML и SGML. Совсем нет — XML занимает те ниши, которые ранее были недоступны этим двум языкам. В информационном мире всегда будет место для каждого из них, хотя, вполне закономерно ожидать, что XML-технологии получат со временем гораздо более широкое распространение, чем HTML и SGML вместе взятые.</p>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 2</p>
    <p>Введение в XSLT</p>
   </title>
   <section>
    <title>
     <p>Документ = Данные + Структура</p>
    </title>
    <p>В предыдущей главе мы подробно разобрали синтаксис XML, являющийся ключом к пониманию сути XML, которая состоит в том, что простых текстовых меток вполне достаточно, чтобы явно выделить в документе сколь угодно сложную структуру.</p>
    <p>По большому счету, здесь XML заканчивается. Это не язык программирования, не язык операторов и функций, но язык структуры документа. Язык для простого и при этом очень четкого ее описания.</p>
    <p>Важность роли, которую играет структура данных в программировании, сложно переоценить. В классической цитате Н. Вирта "Алгоритмы + Структуры данных = Программы", датированной 1976 годом, спустя четверть века "плюс" следует скорее трактовать, как знак умножения, но принцип остался верен: структура данных имеет ничуть не меньшее значение, чем алгоритм, который ее обрабатывает.</p>
    <p>Успех XML можно, пожалуй, объяснить другим уравнением:</p>
    <subtitle>Документ = Данные + Структура</subtitle>
    <p>В примитивной трактовке это означает, что для того, чтобы получить программу, к документам остается только дописать алгоритмы — данные и структура уже имеются. Если присмотреться более внимательно, можно заметить, что структура данных в равенстве Вирта и структура, которая является одной из составляющих документа, на самом деле могут быть (и, как правило, бывают) очень разными. Положение усугубляется еще и тем, что для одних и тех же данных можно выдумать великое множество типов структур, мало совместимых между собой. Таким образом, для того, чтобы эффективно использовать XML, во многих случаях необходимо уметь преобразовывать структуру XML-документов.</p>
    <p>Как оказалось, традиционные процедурные языки программирования плохо подходят для решения этой задачи: слишком громоздкими были в них программы для преобразования структуры. Объяснить это легко — большинство языков оперировали данными и к арифметике структур документов были мало приспособлены. Проблема требовала более гибкого и мощного решения, и этим решением стал язык XSLT.</p>
    <p>XSLT означает extensible Stylesheet Language for Transformations, что на русский язык традиционно переводится как "расширяемый язык стилей для преобразований". Название это скорее историческое, нежели смысловое — работа над XSLT была инициирована проектом XSL — extensible Stylesheet Language (расширяемым языком стилей).</p>
    <p>Спецификация XSLT гласит, что это язык для преобразования одних XML-документов в другие XML-документы. Вне всякого сомнения, таковой и была изначальная идея XSLT. Очевидно, в процессе разработки язык перерос ее и теперь уместнее согласиться с редактором новой версии языка, Майклом Кеем (Michael Kay) в том, что XSLT — это язык для преобразования структуры документов.</p>
   </section>
   <section>
    <title>
     <p>XSLT как язык</p>
    </title>
    <section>
     <p>По большому счету, любое преобразование можно условно поделить на три составляющие:</p>
     <p>&#9633; обращение к преобразуемому объекту;</p>
     <p>&#9633; создание результата преобразования;</p>
     <p>&#9633; логика, связывающая первые два действия и направляющая процесс преобразования.</p>
     <p>Применительно к преобразованию XML-документов первая подзадача означает получение информации, которую этот документ содержит — в том числе и информации о структуре, которая является неотъемлемой его частью. Обращение в данном случае имеет несколько смыслов, в том числе — опрашивать, делать запросы, вычислять, выбирать; в общем смысле — задавать о документе вопросы и получать на них ответы. Для этой цели в XSLT служит язык, называемый XPath — язык путей в ХМL-документах (от англ. XML Path Language). Как мы увидим, XPath является лаконичным, но при этом чрезвычайно мощным средством обращения к XML-документам (а также к их частям). Роль XPath в XSLT так велика, что их можно было бы считать единым целым, если бы только XPath не использовался также и в других языках, предназначенных для работы с XML.</p>
     <p>Вторая и третья условные части преобразования являются прерогативой самого XSLT. XSLT — это XML-язык в полном смысле этого слова: программы на XSLT (мы будем называть их преобразованиями сообразно их предназначению) являются хорошо оформленными (well-formed) XML-документами. XSLT также использует пространства имен; практически все имена, встречающиеся в XSLT, как-то: имена переменных, шаблонов, форматов и так далее — рассматриваются как расширенные имена, характеризуемые локальной частью вкупе с URI — уникальным идентификатором пространства имен.</p>
     <p>В отличие от традиционных императивных языков программирования, преобразование в XSLT не является последовательностью действий, которую необходимо выполнить для достижения результата. Преобразование — это набор шаблонных правил, каждое из которых определяет процедуру обработки определенной части документа. Иными словами, преобразование в XSLT объявляет, декларирует правила преобразования — правила, применяя которые к входящему документу, XSLT-процессор в конечном итоге генерирует выходящий документ, который и является целью преобразования.</p>
     <p>В качестве первого примера XSLT-преобразования, который будет приведен в этой книге, мы рассмотрим классическую программу <code>"Hello, world!"</code>. Листинг 2.1 показывает XSLT-интерпретацию <code>"Hello, world!"</code>, когда мы преобразуем документ</p>
     <p><code>&lt;msg&gt;Hello, world!&lt;/msg&gt;</code></p>
     <p>в документ вида:</p>
     <p><code>&lt;message&gt;Hello, world!&lt;/message&gt;</code></p>
     <subtitle>Листинг 2.1. Преобразование "Hello, world!"</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="msg"&gt;</code></p>
     <p><code>  &lt;message&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code>  &lt;/message&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Исходный код, представленный выше, является хорошо оформленным XML-документом. Корневым его элементом является элемент <code>xsl:stylesheet</code>, который и обозначает преобразование. Атрибут <code>version</code> указывает на версию языка XSLT, в соответствии с которой был построен этот документ; помимо этого в элементе <code>xsl:stylesheet</code> объявляется пространство имен с префиксом <code>xsl</code>, которому соответствует URI <code>"http://www.w3.org/1999/XSL/Transform"</code>. Все элементы преобразования, принадлежащие пространству имен с этим URI, будут восприняты процессором, как принадлежащие языку XSLT.</p>
     <p>Элемент <code>xsl:stylesheet</code> имеет один-единственный дочерний элемент <code>xsl:template</code>, который и задает правило преобразования. Атрибут <code>match</code> указывает, что это правило должно обрабатывать элемент <code>msg</code>. Содержимое <code>xsl:template</code> является телом шаблона. Оно выполняется тогда, когда сам шаблон применяется к некоторой части документа. В данном случае тело шаблона будет выполнено, когда само правило будет применяться к элементу <code>msg</code>.</p>
     <p>Телом шаблона является элемент <code>message</code>. В терминах XSLT, этот элемент является литеральным элементом результата: он не принадлежит пространству имен XSLT и поэтому при обработке будет просто скопирован в результирующий документ. Содержимое этого элемента будет также обработано и включено в его сгенерированную копию.</p>
     <p>Содержимым элемента <code>message</code> является элемент <code>xsl:value-of</code>, который, в отличие от <code>message</code> принадлежит XSLT. Элемент <code>xsl:value-of</code> вычисляет XPath-выражение, заданное в его атрибуте <code>select</code>, и возвращает результат этого вычисления. XPath-выражение, <code>"."</code>, указанное в <code>select</code>, возвращает ту самую часть узла, которая обрабатывается в данный момент, иначе говоря — элемент <code>msg</code>.</p>
     <p>Переводя на русский язык все вышеперечисленное, можно сказать, что приведенное преобразование содержит единственное правило: если в документе встретится элемент <code>msg</code>, создать в выходящем документе элемент <code>message</code> и включить в него содержимое элемента <code>msg</code>.</p>
     <p>Синтаксис XSLT, являющийся чистым XML, может показаться для языка программирования не совсем обычным, однако, как показывает практика, вряд ли какой другой синтаксис был бы более удобным. В конце концов, XSLT — это, прежде всего преобразование XML-документов, и уж на чем, как не на XML описывать правила этого преобразования. Кроме того, XML- формат самого преобразования позволяет использовать для его представления те же модели данных, что и для преобразуемых документов.</p>
     <p>Совсем иным является язык XPath, который представлен в нашем примере лаконичным выражением <code>"."</code>. XPath не придерживается XML-синтаксиса, напротив, он скорее похож на синтаксис путей в операционных системах — <emphasis>в главе 4</emphasis> мы покажем, насколько верно это сравнение.</p>
     <p>В приведенном преобразовании участвовала и третья синтаксическая конструкция, которая называется в XSLT <emphasis>паттерном</emphasis> (от англ. pattern — образец). Паттерн <code>msg</code>, заданный в атрибуте <code>match</code> элемента <code>xsl:template</code> указывает, какая именно часть XML-документа должна быть обработана этим правилом. Синтаксически паттерны являются XPath-выражениями (но не наоборот), однако смысл их различается. XPath-выражения вычисляются и возвращают результат, паттерны же просто устанавливают соответствие некоторому образцу. В нашем преобразовании паттерн <code>msg</code> указывает, что шаблон должен обрабатывать только элементы <code>msg</code> и никакие другие.</p>
     <p>Каждое из шаблонных правил может вызывать другие шаблонные правила — в этом случае результат выполнения вызванных шаблонов включается в результат выполнения шаблона, который их вызывал. Для того чтобы продемонстрировать этот принцип мы немного перепишем шаблон <code>"Hello, world!"</code> с тем, чтобы он возвращал результат в виде HTML-документа.</p>
     <subtitle>Листинг 2.2. Преобразование "Hello, world!"' с результатом в HTML</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;html&gt;</code></p>
     <p><code>   &lt;head&gt;</code></p>
     <p><code>    &lt;title&gt;Message&lt;/title&gt;</code></p>
     <p><code>   &lt;/head&gt;</code></p>
     <p><code>   &lt;body&gt;</code></p>
     <p><code>    &lt;xsl:apply-templates select="msg"/&gt;</code></p>
     <p><code>   &lt;/body&gt;</code></p>
     <p><code>  &lt;/html&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="msg"&gt;</code></p>
     <p><code>  &lt;b&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code>  &lt;/b&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результат применения этого преобразования к документу</p>
     <p><code>&lt;msg&gt;Hello, world!&lt;/msg&gt;</code></p>
     <p>иллюстрирует листинг 2.3.</p>
     <subtitle>Листинг 2.3. Результат выполнения преобразования</subtitle>
     <p><code>&lt;html&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;title&gt;Message&lt;/title&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code> &lt;body&gt;</code></p>
     <p><code>  &lt;b&gt;Hello, world!&lt;/b&gt;</code></p>
     <p><code> &lt;/body&gt;</code></p>
     <p><code>&lt;/html&gt;</code></p>
     <p>В это преобразование мы добавили еще одно шаблонное правило:</p>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;html&gt;</code></p>
     <p><code>  &lt;head&gt;</code></p>
     <p><code>   &lt;title&gt;Message&lt;/title&gt;</code></p>
     <p><code>  &lt;/head&gt;</code></p>
     <p><code>  &lt;body&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="msg"/&gt;</code></p>
     <p><code>  &lt;/body&gt;</code></p>
     <p><code> &lt;/html&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Это правило определяет обработку корневого узла — в атрибуте <code>match</code> указан паттерн <code>"/"</code>, что соответствует корню документа. Шаблон создает элементы <code>html</code>, <code>head</code>, <code>title</code>, <code>body</code> и в последний включает результат применения шаблонов к элементу <code>msg</code>. Сравнивая тело этого шаблона с результатом выполнения преобразования, можно заметить, что процессор скопировал все элементы, не принадлежащие XSLT, не изменяя их, а элемент <code>xsl:apply-templates</code> выполнил, применив шаблон к элементу <code>msg</code> и включив в <code>body</code> результат (он выделен в листинге полужирным шрифтом).</p>
     <p>Продемонстрированная возможность вызова одних правил из других, а также наличие в XSLT таких управляющих конструкций, как <code>xsl:if</code>, <code>xsl:choose</code> и <code>xsl:for-each</code> позволяет простым набором правил реализовывать очень сложную логику преобразования. В XSLT применяется один из основных принципов эффективной разработки: для того чтобы решить задачу, нужно разбить ее на более мелкие части и решить каждую из них по отдельности. Проблемой в данном случае является преобразование, и вместо того, чтобы описывать его целиком, XSLT позволяет определить простые правила обработки каждой из частей, связав эти правила логикой взаимных вызовов и управляющих конструкций.</p>
    </section>
    <section>
     <title>
      <p>Отсутствие "побочных" эффектов</p>
     </title>
     <p>Одним из краеугольных принципов XSLT, с которым, увы, нелегко смириться разработчику, работавшему только с процедурными языками, — это отсутствие "побочных" эффектов. Под побочными эффектами в данном случае понимаются изменения в окружении преобразования, которые отражаются на дальнейшем его выполнении.</p>
     <p>Концепция отсутствия побочных эффектов берет начало в функциональном программировании, а оно, в свою очередь, в "чистых" математических функциях, не изменяющих своего окружения в процессе вычисления. Например, функция</p>
     <p><emphasis>f</emphasis>(<emphasis>x</emphasis>, <emphasis>у</emphasis>) &gt; <emphasis>вернуть x + у</emphasis>;</p>
     <p>будет чистой функцией. Сколько бы раз мы ее не вызывали, ее результат все равно будет равен сумме аргументов. Кроме того, результат вычисления <emphasis>f</emphasis>(<emphasis>f</emphasis>(<emphasis>x</emphasis><sub>1</sub>, <emphasis>y</emphasis><sub>1</sub>), <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>2</sub>, <emphasis>y</emphasis><sub>2</sub>)) будет равен <emphasis>x</emphasis><sub>1</sub> + <emphasis>y</emphasis><sub>1</sub> + <emphasis>x</emphasis><sub>2</sub> + <emphasis>y</emphasis><sub>2</sub>, в каком бы порядке мы не вычисляли эти функции:</p>
     <p><emphasis>f</emphasis>(<emphasis>f</emphasis>(<emphasis>x</emphasis><sub>1</sub>, <emphasis>y</emphasis><sub>1</sub>), <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>2</sub>, <emphasis>y</emphasis><sub>2</sub>)) = <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>1</sub> + <emphasis>y</emphasis><sub>1</sub>, <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>2</sub>, <emphasis>y</emphasis><sub>2</sub>)) = <emphasis>x</emphasis><sub>1</sub> + <emphasis>y</emphasis><sub>1</sub> + <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>2</sub>, <emphasis>y</emphasis><sub>2</sub>) = <emphasis>x</emphasis><sub>1</sub> + <emphasis>y</emphasis><sub>1</sub> + <emphasis>x</emphasis><sub>2</sub> + <emphasis>y</emphasis><sub>2</sub></p>
     <p><emphasis>f</emphasis>(<emphasis>f</emphasis>(<emphasis>x</emphasis><sub>1</sub>, <emphasis>y</emphasis><sub>1</sub>), <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>2</sub>, <emphasis>y</emphasis><sub>2</sub>)) = <emphasis>f</emphasis>(<emphasis>f</emphasis>(<emphasis>x</emphasis><sub>1</sub>, <emphasis>y</emphasis><sub>1</sub>), <emphasis>x</emphasis><sub>2</sub> + <emphasis>y</emphasis><sub>2</sub>) = <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>1</sub>, <emphasis>y</emphasis><sub>1</sub>) + <emphasis>x</emphasis><sub>2</sub> + <emphasis>y</emphasis><sub>2</sub> = <emphasis>x</emphasis><sub>1</sub> + <emphasis>y</emphasis><sub>1</sub> + <emphasis>x</emphasis><sub>2</sub> + <emphasis>y</emphasis><sub>2</sub></p>
     <p><emphasis>f</emphasis>(<emphasis>f</emphasis>(<emphasis>x</emphasis><sub>1</sub>, <emphasis>y</emphasis><sub>1</sub>), <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>2</sub>, <emphasis>y</emphasis><sub>2</sub>)) = <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>1</sub>, <emphasis>y</emphasis><sub>1</sub>) + <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>2</sub>, <emphasis>y</emphasis><sub>2</sub>) = <emphasis>x</emphasis><sub>1</sub> + <emphasis>y</emphasis><sub>1</sub> + <emphasis>f</emphasis>(<emphasis>x</emphasis><sub>2</sub>, <emphasis>y</emphasis><sub>2</sub>) = <emphasis>x</emphasis><sub>1</sub> + <emphasis>y</emphasis><sub>1</sub> + <emphasis>x</emphasis><sub>2</sub> + <emphasis>y</emphasis><sub>2</sub></p>
     <p>и так далее.</p>
     <p>Представим теперь похожую функцию, обладающую побочным эффектом:</p>
     <p><emphasis>f</emphasis>(<emphasis>x</emphasis>, <emphasis>у</emphasis>) &#8594; <emphasis>z присвоить x</emphasis>; <emphasis>увеличить z на у</emphasis>; <emphasis>вернуть z</emphasis>;</p>
     <p>В данном случае побочный эффект состоит в изменении значения переменной <emphasis>z</emphasis>. В этом случае результат вычисления выражения <emphasis>f</emphasis>(<emphasis>z</emphasis>, <emphasis>f</emphasis>(<emphasis>x</emphasis>, <emphasis>у</emphasis>)) строго зависит от того, в каком порядке будут вычисляться функции — в одних случаях результатом будет <emphasis>x</emphasis> + <emphasis>у</emphasis> + <emphasis>z</emphasis>, в других 2&#8729;<emphasis>x</emphasis> + 2&#8729;<emphasis>у</emphasis>. Для того чтобы результат вычислений с побочными эффектами был детерминирован, требуется строгая определенность в порядке действий. В XSLT же эта строгая определенность отсутствует, преобразование — это набор правил, а не последовательность действий.</p>
     <p>Таковы теоретические посылки отсутствия побочных эффектов. Главным практическим ограничением является то, что преобразования не могут во время выполнения <emphasis>изменять</emphasis> переменные — после того, как переменной присвоено некоторое начальное значение, измениться оно больше не может.</p>
     <p>Сильнее всего это ограничение сказывается на стиле XSLT-программирования. Он становится ближе к функциональному стилю таких языков, как Lisp и Prolog. Научиться соответствовать этому стилю просто, хотя поначалу он и будет казаться неудобным.</p>
    </section>
    <section>
     <title>
      <p>Расширения</p>
     </title>
     <p>Слово extensible (англ. расширяемый) в расшифровке аббревиатуры XSLT исторически происходит из названия языка XSL, но оно вполне применимо и к самому XSLT: спецификация этого языка позволяет разрабатывать собственные функции и элементы и использовать их в преобразованиях.</p>
     <p>Применительно к преобразованиям структуры, XSLT является чрезвычайно мощным языком, но в то же время вычислительная его часть страдает. В языке XPath, на который переложена задача вычислений в XSLT, есть основные арифметические и логические операторы, небольшая базовая библиотека функций для работы с различными типами данных — но не более. XPath мало подходит для действительно сложных вычислительных задач. Что касается самого XSLT, набор элементов этого языка можно назвать вполне достаточным для большинства задач. Но и тут встречаются приложения (и разработчики), которые требуют большего.</p>
     <p>Следуя спецификации, большинство реализаций XSLT предоставляет интерфейсы для разработки собственных функций, немного реже — элементов. Расширения пишутся на обычных языках программирования, таких как Java или С, но используются в XSLT так же, как использовались бы обычные функции и элементы.</p>
     <p>Технология расширений делает XSLT поистине универсальным языком, ведь получается, что в нем можно использовать любые вычисления, которые только могут быть описаны в классических языках программирования.</p>
     <p>К сожалению, вследствие различий в интерфейсах расширений, их использования приводит к потере переносимости между платформами и процессорами. Если преобразования, созданные в соответствии со стандартом языка, будут, как правило, без проблем выполняться различными процессорами, использование расширений в большинстве случаев ограничивает переносимость преобразования.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Преобразования снаружи</p>
    </title>
    <p>В общем случае в преобразовании участвуют три документа:</p>
    <p>&#9633; <emphasis>входящий документ</emphasis>, который подвергается преобразованию;</p>
    <p>&#9633; документ, который описывает само <emphasis>преобразование</emphasis>;</p>
    <p>&#9633; <emphasis>выходящий документ</emphasis>, который является результатом преобразования.</p>
    <p>Само по себе преобразование это всего лишь XML-документ, не более чем описание правил, в соответствии с которыми входящий документ должен трансформироваться в исходящий. Процесс преобразования входящего документа в соответствии с описанными правилами называется <emphasis>применением</emphasis> преобразования к входящему документу или просто <emphasis>выполнением</emphasis> данного преобразования.</p>
    <p>Выполнением преобразований над документами занимаются специальные программы, которые называются XSLT-процессорами. В первом приближении схема преобразования приведена на рис. 2.1.</p>
    <image l:href="#img_6.png"/>
    <p><strong>Рис. 2.1</strong>. Схема XSLT-преобразования</p>
    <p>Процессор получает входящий документ и преобразование, и, применяя правила преобразования, генерирует выходящий документ — такова в общем случае внешняя картина. На самом деле процессор оперирует не самими документами, а древовидными моделями их структур (рис. 2.2.) — именно структурными преобразованиями занимается XSLT, оставляя за кадром синтаксис, который эти структуры выражает.</p>
    <image l:href="#img_7.png"/>
    <p><strong>Рис. 2.2.</strong> Древовидные структуры в XSLT</p>
    <p>Несмотря на то, что для XSLT как для языка совершенно неважно, в каком виде находятся документы изначально (главное — чтобы была структура, которую можно преобразовать), абсолютное большинство процессоров может работать с документами, которые физически записаны в файлах. В этом случае процесс обработки делится на три стадии.</p>
    <p>&#9633; XSLT-процессор разбирает входящий документ и документ преобразования, создавая для них древовидные структуры данных. Этот этап называется этапом <emphasis>парсинга</emphasis> документа (от англ. parse — разбирать).</p>
    <p>&#9633; К дереву входящего документа применяются правила, описанные в преобразовании. В итоге процессор создает дерево выходящего документа. Этот этап называется этапом <emphasis>преобразования</emphasis>.</p>
    <p>&#9633; Для созданного дерева генерируется физическая сущность. Этот этап называется этапом <emphasis>сериализации</emphasis>.</p>
    <p>Хотя практически все процессоры выполняют каждый из этих трех этапов (получают входящие документы и выдают результат их трансформации), рабочей областью XSLT является только второй этап, этап преобразования. XSLT практически не контролирует парсинг входящего документа, как правило, этим занимается встроенный или внешний SAX- или DOM-парсер.</p>
    <p>С сериализацией дела обстоят немного сложнее. С точки зрения преобразования, результирующее дерево — это все, что от него требуется, но вряд ли разработчику будет этого достаточно. Редко когда сгенерированная абстрактная древовидная структура — это то, что нужно. Гораздо чаще результат преобразования требуется получить в определенной физической форме.</p>
    <p>Сериализация как раз и является процессом создания физической интерпретации результирующего дерева, и если и эта задача делегируется XSLT-процессору, то преобразованию под силу контролировать физический вывод генерируемого документа (рис. 2.3).</p>
    <image l:href="#img_8.png"/>
    <p><strong>Рис. 2.3</strong>. Сериализация в XSLT</p>
    <p>Текущая версия языка поддерживает три основных метода сериализации: XML, HTML и текст. Каждый из этих методов учитывает синтаксис целевого физического формата и позволяет получить документ требуемого вида. Кроме того, имплементации XSLT могут добавлять собственные методы сериализации, генерируя документы в других форматах (например, PDF или TeX), не предусмотренных стандартными методами.</p>
    <p>Преобразования могут указывать метод сериализации, который должен использоваться для создания физической интерпретации генерируемой структуры, однако даже в случае стандартных методов непосредственный контроль над синтаксисом физического документа сильно ограничен. Можно сказать, что он практически отсутствует.</p>
    <p>Преобразования отделены от синтаксической обработки совершенно сознательно, ведь их задачей являются структурные трансформации, а не работа с физическим синтаксисом. Благодаря этому разделению многие процессоры позволяют использовать для парсинга и сериализации внешние приложения, что в значительной степени повышает универсальность XSLT: для каждого этапа преобразования можно использовать наиболее подходящий инструмент.</p>
   </section>
   <section>
    <title>
     <p>Области применения XSLT</p>
    </title>
    <section>
     <p>В отличие от языка XML, предметную область XSLT задать очень легко. XSLT следует применять там, где необходимо преобразование одного документа в другой.</p>
     <p>Естественно, XSLT имеет также и некоторые ограничения:</p>
     <p>&#9633; XSLT не подходит для описания преобразований с очень сложной логикой;</p>
     <p>&#9633; XSLT не подходит для преобразований, которые требуют сложных вычислений.</p>
     <p>Первое ограничение связано с тем, что преобразование в XSLT — это всего лишь набор элементарных правил. В подавляющем большинстве случаев этого достаточно для описания преобразования, однако, встречаются также и такие задачи, для которых данного набора правил будет недостаточно. Например, древовидные структуры могут описывать математические выражения, но при этом преобразование для упрощения или вычисления этого дерева выражений может быть чересчур сложным для XSLT.</p>
     <p>Второе ограничение является следствием простоты языка XPath, который используется в XSLT для вычислений. XPath предоставляет только самые простейшие вычислительные конструкции, которых явно недостаточно для сложных задач. Кроме того, функциональный стиль XSLT и отсутствие изменяемых переменных делают очень затруднительными многошаговые и циклические вычисления.</p>
     <cite>
      <subtitle>Замечание</subtitle>
      <p>Оба этих ограничения можно с успехом обойти при помощи механизма расширений, который позволяет комбинировать XSLT с другими языками программирования. Умело используя расширения, можно совместить гибкость XSLT и мощь традиционных языков.</p>
     </cite>
     <p>Ниже мы опишем наиболее классические области применения XSLT: Web-решения, использование в клиент-серверных приложениях и проекты интеграции.</p>
    </section>
    <section>
     <title>
      <p>XSLT в архитектуре клиент-сервер</p>
     </title>
     <section>
      <p>Многие из систем, применяющих XSLT, так или иначе, сводятся к клиент- серверной архитектуре, в которой клиент делает запрос, а сервер в качестве ответа возвращает некоторые данные. XSLT в таких решениях может использоваться для приведения структуры данных из внутреннего формата сервера к некоторому внешнему формату, понятному клиенту. Примером подобной системы может быть Web-сервер, предоставляющий клиентам (фактически, Web-браузерам) информацию, которая динамически генерируется из базы данных.</p>
      <p>Классическим и широко применяемым решением для такого рода задачи являются серверные компоненты, сервлеты и различные скриптовые языки, которые преобразуют запросы клиента в запросы к базе данных, а затем оформляют результаты выполнения в виде HTML и отсылают клиенту.</p>
      <p>Очевидный минус этого решения в том, что оно слишком сильно зависит от презентации данных. Новая презентация (например, версия "для печати" или для мобильного устройства) или сравнительно серьезное исправление старой заставляют, чуть ли не полностью (в зависимости от качества проектирования) переписывать Web-приложение.</p>
      <p>Практика показывает, что в подобных системах весьма и весьма эффективно применяется связка XML+XSLT. Вместо того чтобы генерировать по данным HTML-презентацию, можно создать XML-документ, и, применяя преобразования, возвращать клиенту именно тот результат, которого он ожидает.</p>
      <p>Схема взаимодействия XML и XSLT в архитектуре клиент-сервер представлена на рис. 2.4. На этом рисунке нет четкой границы, которая отделяла бы клиента от сервера. Дело в том, что существует два принципиально различных способа использования XSLT в подобной архитектуре: преобразования могут выполняться как на стороне сервера, так и на стороне клиента. Рассмотрим подробнее оба способа.</p>
      <image l:href="#img_9.png"/>
      <p><strong>Рис. 2.4</strong>. XML и XSLT в архитектуре клиент-сервер</p>
     </section>
     <section>
      <title>
       <p>XSLT на стороне сервера</p>
      </title>
      <p>Применение XSLT на стороне сервера (рис. 2.5) совершенно незаметно для клиента — он, как и раньше, в ответ на свой запрос получает HTML или документ в другом требуемом формате. В данном случае связка XML+XSLT является дополнительным звеном, дополнительным уровнем абстракции, который позволяет отделять данные от презентации, добиваясь простоты и универсальности. Создание преобразований для генерации HTML по имеющимся XML-документам — задача совершенно иного плана, чем написание серверных приложений и программ, которые непосредственно работают с результатами выполнения запросов к базе данных.</p>
      <image l:href="#img_10.png"/>
      <p><strong>Рис. 2.5</strong>. XSLT на стороне сервера</p>
      <p>Главным минусом этого способа является то, что мы все равно возвращаем клиенту <emphasis>представление</emphasis> данных, а не сами данные. Естественно, используя XSLT, множество доступных представлений расширить очень легко, но это множество в любом случае будет ограничено. Вне всякого сомнения, для большинства современных Web-систем этого более чем достаточно, но существующие Web-технологии больше ориентированы на представление данных, чем на сами данные — они стараются предвосхитить вопросы и заранее процедуры ответов. Возможно, в будущем эта ситуация изменится.</p>
     </section>
     <section>
      <title>
       <p>XSLT на стороне клиента</p>
      </title>
      <p>Идея использования XSLT на стороне клиента (рис. 2.6) заключается в том, чтобы отдавать клиенту отдельно нужные ему данные и отдельно преобразование, которое будет создавать для этих данных требуемое представление (например — HTML-страницу). Четкое разделение данных и их представления предоставит клиенту полную свободу распоряжаться полученной информацией. Преобразование в этом случае всего лишь предлагает возможную трактовку этой информации, ни к чему не обязывая.</p>
      <image l:href="#img_11.png"/>
      <p><strong>Рис. 2.6</strong>. XSLT на стороне клиента</p>
      <p>Еще одним (правда, чисто техническим) достоинством выполнения преобразований на стороне клиента является разгрузка сервера, ведь такой подход освобождает его от необходимости выполнять процедуру преобразования.</p>
      <p>Основным ограничением этого способа является предположение, что программное обеспечение на стороне клиента <emphasis>сможет</emphasis> выполнять преобразования. К сожалению, текущая ситуация далека от идеальной, и решение такого вида может применяться только в очень ограниченном числе случаев — когда достоверно известно, что целевой клиент поддерживает XSLT.</p>
     </section>
    </section>
    <section>
     <title>
      <p>XSLT в Web-решениях</p>
     </title>
     <p>Попытаемся теперь взглянуть на приложения архитектуры клиент-сервер под несколько иным углом и в более узкой области Web-решений.</p>
     <p>Примем за основу наиболее реалистичную схему, в которой преобразования выполняются на стороне сервера. Типовой процесс доступа к данным в этом случае может быть описан следующим образом:</p>
     <p>&#9633; клиент запрашивает определенный документ;</p>
     <p>&#9633; сервер находит (или генерирует) этот документ;</p>
     <p>&#9633; сервер находит (или генерирует) преобразование, ассоциированное с этим документом, и применяет его к документу;</p>
     <p>&#9633; результат преобразования возвращается клиенту (например, в виде HTML-файла).</p>
     <p>В подобной системе можно выделить три базовых компонента (рис. 2.7):</p>
     <p>&#9633; генератор — модуль, который создает документ на основе информации, хранящейся в базе данных или просто в файлах на сервере;</p>
     <p>&#9633; процессор преобразований — модуль, который применяет преобразования к сгенерированному документу;</p>
     <p>&#9633; сериализатор — модуль, создающий физическую репрезентацию результата преобразования.</p>
     <image l:href="#img_12.png"/>
     <p><strong>Рис. 2.7</strong>. Декомпозиция системы Web-публикации</p>
     <p>В таком виде XSLT создает сильную конкуренцию серверным скриптовым языкам типа ASP, JSP, PHP, Python и так далее. Web-системы, построенные на XML и XSLT, гораздо гибче и легче в реализации, а их масштабируемость нельзя даже сравнивать. В традиционных системах добавление еще одного представления данных (например, текстовой версии документа или версии "для печати") — это еще одна программа на сервере, в то время как в системах, использующих XSLT, — это всего лишь еще одно преобразование (рис. 2.8).</p>
     <image l:href="#img_13.png"/>
     <p><strong>Рис. 2.8</strong>. Создание множественных представлений с использованием XSLT</p>
     <p>XSLT является одной из основных технологий систем Web-публикации, как Cocoon от Apache XML Project и XSQL от Oracle. Решения на основе. Cocoon и XSQL отличаются мощностью, гибкостью и простотой; ожидается, что системы этого класса займут в скором времени лидирующие позиции.</p>
    </section>
    <section>
     <title>
      <p>XSLT при обмене данными</p>
     </title>
     <p>В предыдущей главе мы обсудили преимущества применения XML в проектах интеграции: определение общего XML-языка снижает трудозатраты по реализации обмена данными между различными системами. При этом экспорт данных в общем формате выполняется врапперами — оболочками для стандартизации внешних обращений.</p>
     <p>Между тем, во многих случаях функции врапперов совершенно стандартны: от них требуется только экспортировать и импортировать данные. Более того, если приложение может производить экспорт и импорт в определенном XML-формате самостоятельно, потребность во врапперах попросту отпадает.</p>
     <p>Действительно, предположим, что наши приложения уже имеют определенный XML-интерфейс (рис. 2.9):</p>
     <image l:href="#img_14.png"/>
     <p><strong>Рис. 2.9</strong>. Приложение с XML-интерфейсом</p>
     <p>Под XML-интерфейсом в данном случае подразумевается возможность экспортировать и импортировать данные в некотором XML-языке (пусть даже своем для каждого из приложений).</p>
     <p>Таким образом, для интеграции этого приложения в общую схему потребуется лишь обеспечить "перевод" данных с XML-языка приложения на общий XML-язык и обратно (рис. 2.10).</p>
     <image l:href="#img_15.png"/>
     <p><strong>Рис. 2.10</strong>. Интеграция приложения с XML-интерфейсом в общую схему</p>
     <p>Упомянутая выше задача перевода, или, по-другому, преобразования, есть очевидная область применения языка XSLT. Общая схема интеграции на основе XML и XSLT показана на рис. 2.11.</p>
     <image l:href="#img_16.png"/>
     <p><strong>Рис. 2.11</strong>. Схема интеграции приложений на основе XML/XSLT</p>
     <p>Здесь XSLT исполняет роль связующего звена между XML-интерфейсами приложений и общим XML-языком. Эта схема легка в реализации (поскольку не требует знания внутреннего устройства приложений), масштабируема (задача добавления новых приложений и систем заключается в создании дополнительной пары преобразований) и концептуально целостна (так как основана только на XML-технологиях).</p>
    </section>
   </section>
   <section>
    <title>
     <p>История XSLT</p>
    </title>
    <p>Одной из главных задач технологии XML было отделение данных от их презентации. XML прекрасно справляется с этой задачей, предоставляя широкие возможности для структурного оформления данных в текстовом виде. Вместе с тем, во многих случаях просто выделить данные было явно недостаточно, поскольку помимо машинной обработки они также должны были быть понятны человеку. В качестве примера, вспомним рекламное объявление, которое мы разметили в первой главе:</p>
    <p><code>&lt;advert&gt;</code></p>
    <p><code> Предлагаем Вашему вниманию новый &lt;room&gt;3&lt;/room&gt;-x камерный</code></p>
    <p><code> &lt;product&gt;Холодильник&lt;/product&gt;</code></p>
    <p><code> &lt;product-title&gt;"Горск"&lt;/product-title&gt;</code></p>
    <p><code> объемом &lt;volume&gt;250 л.&lt;/volume&gt; и стоимостью всего &lt;price&gt;4500&lt;/price&gt;</code></p>
    <p><code> рублей!</code></p>
    <p><code> &lt;!-- И так далее --&gt;</code></p>
    <p><code>&lt;/advert&gt;</code></p>
    <p>Разметив документ, оформив семантически значимые данные при помощи элементов, мы добились явного выделения их структуры, что позволяет программно обрабатывать информацию, содержащуюся в документе (например, производить поиск или анализ данных). Но это только полдела: помимо программной обработки рекламных объявлений, не менее важной задачей является их презентация, ведь в большинстве случаев пользователь хочет увидеть объявление, а не получить соответствующую ему структуру данных.</p>
    <p>Выделение данных, вне всякого сомнения, расширяет возможности презентации, поскольку они более не зависят от конкретного устройства или формата вывода. Единственное требование — это наличие программных средств, которые, принимая на вход структурированную информацию, смогут корректным образом представить ее в целевом формате или носителе. Если вернуться к примеру с рекламным объявлением, то для того, чтобы получить вывод этого объявления в формате HTML, нам потребуется программа, которая поймет формат документа объявления и создаст для него соответствующий гипертекстовый файл.</p>
    <p>При всем многообразии возможных методов презентации данных, наиболее часто используемые из них весьма схожи между собой. Примером этому может служить визуальное представление информации в печатной форме или на экране.</p>
    <p>Приведенные выше причины могут объяснить потребность в стандартной технологии для презентации XML-документов — технологии, подобной DSSSL (Document Style Semantics and Specification Language, язык семантики и спецификации стиля документа), которая существовала для SGML или CSS (Cascading Style Sheets — каскадные таблицы стилей) для HTML. Эта технология получила название XSL (extensible Stylesheet Language — расширяемый язык стилей), и именно ей обязан своим возникновением язык XSLT.</p>
    <p>Первые идеи о создании отдельного языка для презентации документов были представлены на конференции WWW'94, где С.М. Шперберг-МакКвин и Роберт Гольдштейн выступили с докладом об использовании возможностей SGML во всемирной паутине. В этом докладе были сформулированы основные принципы языка стилей. Мы перечислим некоторые из них:</p>
    <p>&#9633; язык стилей должен быть декларативным (а не процедурным);</p>
    <p>&#9633; язык стилей должен уметь оперировать структурой документа;</p>
    <p>&#9633; презентация элемента может изменяться в зависимости от расположения этого элемента в документе;</p>
    <p>&#9633; реализация интерпретатора языка стилей не должна быть сложной даже в процедурном языке программирования;</p>
    <p>&#9633; синтаксис языка должен быть как можно более примитивным, чтобы разбор его грамматических конструкций не составлял труда.</p>
    <p>Спустя три года, когда Консорциум W3 уже всерьез занялся концепцией XML, эти идеи получили дальнейшее развитие: началась разработка XSL, языка для презентации XML-документов.</p>
    <p>Язык XSL виделся тогда более простым и понятным, чем DSSSL и более мощным, чем CSS. Уже тогда разработчики понимали, что язык презентации XML-документов не сможет обойтись без преобразования их структуры, расширений и должен быть основан на множестве правил презентации.</p>
    <p>В мае 1998 года требования к XSL были оформлены в едином документе. Помимо большого числа комментариев, касающихся визуальной презентации XML-документа, этот документ также упоминал необходимость определения вычислительных выражений, операций, типов данных, конструкций, которые позволяли бы обращаться к обрабатываемому документу, стандартных и пользовательских функций. Концептуально язык определялся как декларативный и не имеющий побочных эффектов.</p>
    <p>После того, как требования к XSL были, наконец, сформулированы, разработка языка вылилась в создание целой серии черновых рабочих вариантов (в терминах W3C — working drafts, WD). Эти варианты зачастую сильно различались между собой, однако основные принципы XSL соблюдались в них неукоснительно.</p>
    <p>С первых же рабочих версий XSL стало понятно, что задача презентации XML-документов состоит из двух главных подзадач: преобразование документа и описание внешнего вида результата этого преобразования. Разделение это было настолько четким, что спецификацию XSL более или менее независимо редактировали два человека: Джеймс Кларк (James Clark) и Стивен Дич (Stephen Deach). Кларк отвечал за преобразования (что в первых версиях называлось tree construction — конструирование дерева), Дич редактировал презентационную часть XSL (которую назвали formatting objects — форматирующие объекты).</p>
    <p>Независимость и различия между двумя этими частями были настолько явными, что уже в третьей рабочей версии, которая вышла в свет 21 апреля 1999 года, технологию XSL разделили на два языка: XSL (расширяемый язык стилей) и XSLT (расширяемый язык стилей для преобразований). XSLT отвечал за преобразование входящего документа, XSL — за визуальное отображение результата этого преобразования. В дальнейшем эти два языка стали развиваться достаточно независимо (хотя они и были частями одной технологии).</p>
    <p>Следующим важным моментом в истории XSLT было создание языка XPath (вернее, выделение этого языка, как самостоятельного). Как оказалось, XSLT имеет семантически общую часть с языком XPointer, который разрабатывался другой группой Консорциума W3. Результатом общих усилий был создан язык XPath, который позволял обращаться к частям XML-документов, а также производить выборки и основные вычисления. XPath также обладал базовой библиотекой функций, которую и XSLT и XPointer расширяли для собственных нужд.</p>
    <p>Таким образом, технология XSL разделилась на три составные части: язык преобразований XSLT, язык обращений к XML-документам XPath и язык стилей XSL. На рис. 2.12 в графической форме показано развитие XSL с момента создания первой рабочей версии в августе 1998 года и до настоящего времени. Вершины графа соответствуют опубликованным версиям языков. WD означает working draft (рабочий черновой вариант), CR — candidate recommendation (кандидат в рекомендации), PR — proposed recommendation (предлагаемая рекомендация) и REC — рекомендация. Для тех, кто не знаком с деятельностью Консорциума W3 поясним, что любая технология, которой занимаются рабочие группы W3C, проходит ряд этапов: формирования требований, несколько рабочих версий, кандидат в рекомендации и предлагаемая рекомендация. Если все проходит успешно, технология становится технической рекомендацией Консорциума W3, что имеет статус стандарта де-факто (с тем лишь отличием, что стандарты могут принимать только организации, уполномоченные правительствами).</p>
    <image l:href="#img_17.png"/>
    <p><strong>Рис. 2.12</strong>. История развития языка XSL в виде графа</p>
    <p>Что касается XSLT и XPath, спецификации обоих этих языков стали техническими рекомендациями 16 ноября 1999 года. Сам же язык XSL, который теперь стали называть XSL-FO (аббревиатура FO означает formatting objects — форматирующие объекты), получил статус рекомендации не так быстро. Спустя год, в ноябре 2000, спецификация XSL получила статус кандидата в рекомендации, а еще через 9 месяцев с минимальными исправлениями — статус предлагаемой рекомендации. По всей видимости, к тому моменту, когда эта книга увидит свет, спецификация XSL уже будет официальной рекомендацией W3C.</p>
    <p>Одного года было достаточно, чтобы XSLT стал широко использоваться во многих XSLT-задачах. Повышенное внимание разработчиков позволило выявить некоторые досадные огрехи, которые были допущены в первой версии XSLT, и потому в конце 2000 года была начата работа над версией 1.1. В новой версии рабочая группа XSL постаралась исправить большинство ошибок, допущенных в версии 1.0 и добавить некоторые возможности, которых не хватало в первой версии. Однако через некоторое время стало понятно, что разрабатываемый язык довольно сильно отличается от первой версии. К тому же, с учетом таких разработок, как XML Schema и XQuery возникла необходимость изменить модель данных и выражений XPath. В итоге, работу над версией 1.1 решено было прекратить и переключиться на создание вторых версий языков XSLT и XPath.</p>
    <p>Вместо того чтобы разбирать в этой книге особенности версии 1.1, которая никогда не станет рекомендацией, в последней главе мы опишем то, что, согласно требованиям ко вторым версиям языков XSLT и XPath, ожидается в их спецификациях, и что, согласно XSLT 1.1 там точно будет. Работа над XSLT 2.0 и XPath 2.0 в самом разгаре: к сентябрю 2001 года были уже готовы три внутренних рабочих версии. К сожалению, открывать секреты рабочей группы XSL мы не в праве, хотя можно смело сказать, что процесс работы внушает оптимизм.</p>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 3</p>
    <p>Идея и модель языка XSLT</p>
   </title>
   <section>
    <title>
     <p>Модель XML-документа</p>
    </title>
    <section>
     <p>Описывая основы построения XML-документов, мы отмечали, что иерархическая организация информации в XML лучше всего описывается древовидными структурами. Дерево — это четкая, мощная и простая модель данных и именно она была на концептуальном уровне применена в языках XSLT и XPath. Как пишет Кнут [Кнут 2000], "<emphasis>деревья — это наиболее важные нелинейные структуры, которые встречаются при работе с компьютерными алгоритмами</emphasis>". Добавим, что это без сомнения самая важная структура из тех, которыми оперируют языки XSLT и XPath.</p>
     <p>В этих языках документ моделируется как дерево, состоящее из узлов. Узлы дерева соответствуют структурным единицам XML — элементам, атрибутам, тексту и так далее, а дуги, ветки — отношениям между этими единицами. Простейшим примером является принадлежность одних элементов другим. Документ вида</p>
     <p><code>&lt;а&gt;</code></p>
     <p><code> &lt;b/&gt;</code></p>
     <p><code> &lt;с/&gt;</code></p>
     <p><code>&lt;/а&gt;</code></p>
     <p>может быть представлен деревом (рис. 3.1).</p>
     <image l:href="#img_18.png"/>
     <p><strong>Рис. 3.1</strong>. Представление документа в виде дерева</p>
     <p>Аналогия совершенно очевидна — элемент <code>а</code> содержит элементы <code>b</code> и <code>с</code>, в то время как в дереве вершина <code>а</code> является родительским узлом для вершин <code>b</code> и <code>с</code>.</p>
     <p>Естественно, XML-документы состоят далеко не из одних только элементов и потому для того, чтобы дерево достоверно отражало структуру и содержание документа, в нем выделяются узлы следующих семи типов:</p>
     <p>&#9633; корневой узел;</p>
     <p>&#9633; узлы элементов;</p>
     <p>&#9633; узлы атрибутов;</p>
     <p>&#9633; текстовые узлы;</p>
     <p>&#9633; узлы пространств имен;</p>
     <p>&#9633; узлы инструкций по обработке;</p>
     <p>&#9633; узлы комментариев.</p>
     <p>Каждый узел дерева имеет соответствующее ему строковое значение, которое вычисляется в зависимости от типа. Строковым значением корневого узла и узла элемента является конкатенация (строковое сложение) строковых значений всех их потомков, для остальных типов узлов строковое значение является частью самого узла. Порядок вычисления строковых значений узлов будет более детально определен в описании каждого из типов.</p>
     <p>Мы подробно разберем каждый из типов узлов чуть позже, а пока отметим, что дерево в XSLT и XPath является чисто концептуальной моделью. Процессоры не обязаны внутренне представлять документы именно в этой структуре, концептуальная модель означает лишь то, что все операции преобразования над документами будут определяться в терминах деревьев. Для программиста же это означает, что вовсе необязательно вникать в тонкости реализации преобразований в том или ином процессоре. Все равно они должны работать, так, как будто они работают непосредственно с деревьями.</p>
     <p>Отметим также и то, что на практике некоторые из процессоров вообще не воссоздают внутреннюю модель документа, экономя, таким образом, ресурсы. Документы могут быть слишком объемными, и это препятствует загрузке их в память в виде древовидной структуры.</p>
     <p>Некоторые из процессоров, напротив, используют DOM-модель документа для внутреннего представления обрабатываемой информации. Несмотря на большие требования к ресурсам памяти, такое решение также может иметь свои плюсы, например, универсальность и легкая интеграция в существующие XML-решения на базе DOM.</p>
     <p>Но, так или иначе, с воссозданием древовидной структуры документа в памяти или нет, процессоры все равно оперируют одной и той же концептуальной моделью, которой мы сейчас и займемся.</p>
    </section>
    <section>
     <title>
      <p>Деревья</p>
     </title>
     <p>Прежде, чем мы приступим к рассмотрению типов узлов и отношений между ними, необходимо определиться с самой структурой дерева. Древовидная структура задает для своих элементов отношение ветвления, очень похожее на строение обычного дерева — есть корневой узел (ствол), от которого происходят другие узлы (ветки).</p>
     <p>Формально [Кнут 2000] дерево определяется, как конечное множество T, состоящее из одного или нескольких элементов (узлов), обладающих следующими свойствами:</p>
     <p>&#9633; во множестве T выделяется единственный узел, называемый корневым узлом или корнем;</p>
     <p>&#9633; все остальные узлы разделены на m&#8805;0 непересекающихся множеств T<sub>1</sub>, …, T<sub>m</sub>, каждое из которых в свою очередь также является деревом.</p>
     <p>Деревья T<sub>1</sub>, …, T<sub>m</sub> называются поддеревьями корня дерева T.</p>
     <p>Это определение является рекурсивным, то есть в нем дерево определяется само через себя. Конечно, существуют нерекурсивные определения, но, пожалуй, следует согласиться с тем, что рекурсивное определение лучше всего отражает суть древовидной структуры: ветки дерева также являются деревьями.</p>
     <p>В XSLT и XPath деревья являются упорядоченными, то есть для множеств T<sub>1</sub>, …, T<sub>m</sub> задается порядок следования, который называется порядком просмотра документа. В XSLT деревья упорядочиваются в порядке появления текстового представления их узлов в документах.</p>
     <p>Существует множество способов графического изображения деревьев. Мы будем рисовать их так, что корень дерева будет находиться наверху, а поддеревья будут упорядочены слева направо. Такой способ является довольно стандартным для XML, хотя и здесь существует множество вариантов. Примером изображения дерева может быть следующий рисунок (рис. 3.2):</p>
     <image l:href="#img_19.png"/>
     <p><strong>Рис. 3.2</strong>. Изображение дерева</p>
     <p>Мы часто будем говорить о дочерних узлах, родительских узлах, братских узлах, узлах-предках и узлах-потомках. Дадим определения этим понятиям.</p>
     <p>&#9633; Дочерним узлом текущего узла называется любой из корней его поддеревьев. Например, в дереве на рис. 3.2 дочерними узлами узла <code>а</code> являются узлы b и <code>с</code>, а дочерними узлами узла <code>b</code> — узлы <code>d</code> и <code>e</code>. Узел <code>с</code> не имеет дочерних узлов — такие узлы иначе называются листьями.</p>
     <p>&#9633; Каждый узел называется родительским узлом корней своих поддеревьев. На рис. 3.2 узел <code>а</code> является родителем узлов <code>b</code> и <code>с</code>, а узел <code>b</code> — родителем узлов <code>d</code> и <code>e</code>.</p>
     <p>&#9633; Корни поддеревьев называются братскими узлами или узлами-братьями. На рис. 3.2 братьями являются узлы <code>b</code> и <code>с</code>, а также узлы <code>d </code>и <code>e</code>.</p>
     <p>&#9633; Предками текущего узла являются его родитель, а также родители его родителей и так далее. На рис. 3.2 предками узла <code>d</code> являются узлы <code>b</code> и <code>а</code>.</p>
     <p>&#9633; Потомками текущего узла являются его дочерние узлы, а также дочерние узлы его дочерних узлов и так далее. На рис. 3.2 потомками узла <code>а</code> являются узлы <code>b</code>, <code>c</code>, <code>d</code> и <code>e</code>.</p>
    </section>
    <section>
     <title>
      <p>Узлы дерева XML-документа</p>
     </title>
     <section>
      <title>
       <p>Корневой узел</p>
      </title>
      <p>Корневой узел XML-документа — это узел, который является корнем дерева документа. Не следует путать его с корневым <emphasis>элементом</emphasis> документа, поскольку помимо корневого элемента дочерними узлами корня также являются инструкции по обработке и комментарии, которые находятся вне корневого элемента.</p>
      <p>Мы будем помечать корневой узел документа символом "<code>/</code>" и изображать следующим образом (рис. 3.3):</p>
      <image l:href="#img_20.png"/>
      <p><strong>Рис. 3.3</strong>. Изображение корневого узла</p>
      <p>На рис. 3.4 показано изображение документа,</p>
      <p><code>&lt;!--А--&gt;</code></p>
      <p><code>&lt;В/&gt;</code></p>
      <p><code>&lt;?С?&gt;</code></p>
      <p>корневой узел которого помимо корневого элемента содержит комментарии и инструкции по обработке.</p>
      <image l:href="#img_21.png"/>
      <p><strong>Рис. 3.4</strong>. XML-документ и его изображение</p>
      <p>Корневой элемент не имеет имени. Функция <code>name(/)</code> будет всегда возвращать пустую строку.</p>
      <p>Строковым значением корневого узла является конкатенация строковых значений всех его текстовых потомков в порядке просмотра документа.</p>
     </section>
     <section>
      <title>
       <p>Узлы элементов</p>
      </title>
      <p>Каждому элементу XML-документа соответствует узел элемента. Дочерними узлами узла элемента могут быть узлы его дочерних элементов, а также узлы комментариев, инструкций по обработке и текстовые узлы, которые представляют его непосредственное содержимое. Следует обратить внимание на то, что узлы атрибутов не считаются дочерними узлами своего элемента, они лишь только ассоциируются с ними.</p>
      <p>При изображении деревьев мы будем помечать узлы элементов их именами. Например, элемент <code>A</code> будет изображен следующим образом (рис. 3.5):</p>
      <image l:href="#img_22.png"/>
      <p><strong>Рис. 3.5</strong>. Изображение элемента <code>А</code></p>
      <p>Каждый элемент имеет расширенное имя, которое состоит из локальной части и идентификатора пространства имен. Пространство имен, которому принадлежит элемент, может быть нулевым, если элемент не имеет префикса, и в его предках не было объявлено пространство имен по умолчанию.</p>
      <p>Подобно корневому узлу, строковым значением узла элемента будет конкатенация значений его текстовых потомков в порядке просмотра документа. В силу того, что атрибуты не являются потомками элементов, их текстовые значения учитываться не будут.</p>
     </section>
     <section>
      <title>
       <p>Узлы атрибутов</p>
      </title>
      <p>Атрибутам того или иного элемента соответствуют узлы атрибутов. Считается, что узел элемента является родителем узла своего атрибута, но вместе с тем узел атрибута не является дочерним узлом узла его элемента. Такая ситуация несколько отличает дерево документа в XSLT от классического дерева, как оно было определено ранее — отношение между узлом элемента и узлом атрибута является отношением ассоциации. Говорят, что узел атрибута ассоциируется с узлом элемента.</p>
      <p>Между тем, отношения такого рода не сильно отличаются от отношений между родительскими и дочерними узлами — один атрибут ассоциируется ровно с одним элементом. Поэтому мы будем изображать узлы атрибутов точно так же, как если бы они были дочерними узлами элементов. Для того чтобы отличать узлы атрибутов от остальных узлов, мы будем помечать их именем, которому будет предшествовать символ "<code>@</code>". При необходимости, значение атрибута будет приводиться в нижней части изображения узла.</p>
      <subtitle>Пример</subtitle>
      <p>Рис. 3.6 показывает возможные варианты изображения элемента, определенного как <code>&lt;file name="a.txt"/&gt;</code>.</p>
      <image l:href="#img_23.png"/>
      <p><strong>Рис. 3.6</strong>. Изображение элемента и принадлежащего ему атрибута</p>
      <p>В случаях, когда значение атрибута не является важным, оно может отсутствовать в изображении узла.</p>
      <p>Каждый атрибут имеет расширенное имя, состоящее из локальной части и идентификатора пространства имен. Пространство имен атрибута будет нулевым, если оно не было определено по умолчанию и у имени атрибута нет префикса.</p>
      <p>Строковым значением узла атрибута является значение атрибута, который ему соответствует.</p>
     </section>
     <section>
      <title>
       <p>Текстовые узлы</p>
      </title>
      <p>Символьные данные, содержащиеся в документе, организуются в виде текстовых узлов. Последовательности символов, встречающиеся в документах, в целях экономии никогда не разбиваются на два или более текстовых узла, а текстовые узлы никогда не бывают пустыми. Содержание секций CDATA обрабатываются так, как если бы их содержимое было просто включено в документ с заменой символов "<code>&lt;</code>" и "<code>&amp;</code>", на сущности <code>&amp;lt;</code> и <code>&amp;amp;</code>.</p>
      <p>Текст, содержащийся в значениях атрибутов, а также в комментариях и инструкциях по обработке не оформляется в виде текстовых узлов — эти данные принадлежат соответствующим узлам атрибутов, комментариев и инструкций.</p>
      <p>Мы будем помечать текстовые узлы символьными последовательностями, которые они содержат, заключенными в кавычки. В случаях, когда сам текст не важен, мы будем помечать эти узлы как "<code>...</code>".</p>
      <subtitle>Пример</subtitle>
      <p>Элемент, заданный как <code>&lt;p&gt;Welcome&lt;/p&gt;</code>, может быть изображен следующим образом (рис. 3.7):</p>
      <image l:href="#img_24.png"/>
      <p><strong>Рис. 3.7</strong>. Варианты изображения текстового узла элемента</p>
      <p>Текстовые узлы не имеют имен. Строковым значением текстового узла является последовательность символов, которую он содержит.</p>
     </section>
     <section>
      <title>
       <p>Узлы пространств имен</p>
      </title>
      <p>Каждому пространству имен, которое определено для данного элемента, соответствует узел пространства имен, ассоциируемый с узлом этого элемента. Множество узлов пространств имен, которое ассоциируется с данным элементом, включает в себя следующие узлы.</p>
      <p>&#9633; Узел, который соответствует пространству имен <code>xml</code>. Это пространство неявно определено в любом XML-документе.</p>
      <p>&#9633; Узел, который соответствует пространству имен, заданному по умолчанию, если такое есть.</p>
      <p>&#9633; По одному узлу на каждый префикс пространств имен, доступный в данном элементе.</p>
      <p>Напомним, что пространства имен, доступные в данном элементе, и пространство имен по умолчанию могут быть определены в его предках.</p>
      <p>Подобно узлам атрибутов, узлы пространств имен ассоциируются с узлом элемента. Узел элемента является их родительским узлом, но при этом они сами не являются дочерними узлами узла элемента.</p>
      <p>Расширенные имена узлов пространств имен состоят из локальной части имени, которая равна префиксу, использованному для объявления этого пространства и нулевого идентификатора пространства имен. Локальная часть пространства, определенного по умолчанию, будет пустой.</p>
      <p>Строковым значением узла пространства имен является уникальный идентификатор ресурса (URI), с которым оно связано.</p>
      <p>Мы будем помечать узлы пространств имен метками вида <code>xmlns:<emphasis>префикс</emphasis></code> для обычного пространства и <code>xmlns</code> для пространства имен по умолчанию. Мы не будем показывать в деревьях узлы пространства имен <code>xml</code>, поскольку они ассоциируются со всеми узлами элементов. При необходимости в нижней части изображения узла мы будем приводить URI пространства, которое ему соответствует.</p>
      <subtitle>Пример</subtitle>
      <p>Приведем изображение дерева (рис. 3.8) документа</p>
      <p><code>&lt;а xmlns="urn:a"&gt;&lt;b:b xmlns:b="urn:b"/&gt;&lt;/a&gt;</code></p>
      <image l:href="#img_25.png"/>
      <p><strong>Рис. 3.8</strong>. Изображение дерева документа с узлами пространств имен</p>
     </section>
     <section>
      <title>
       <p>Узлы инструкций по обработке</p>
      </title>
      <p>Каждой инструкции по обработке соответствует свой узел. В дерево не включаются узлы инструкций, которые были приведены в декларации типа документа (DTD). Кроме этого, поскольку декларация XML не является инструкцией по обработке, ей не будет соответствовать никакой узел в дереве документа.</p>
      <p>Локальной частью расширенного имени инструкции по обработке является имя целевого приложения инструкции. Пространство имен инструкции по обработке всегда нулевое.</p>
      <p>Строковым значением инструкции по обработке является ее содержание — последовательность символов, которая начинается после имени приложения и следующего за ним пробела и заканчивается перед символами "<code>?&gt;</code>", которые закрывают инструкцию. Напомним, что символьные данные инструкции по обработке не выделяются в отдельный текстовый узел.</p>
      <p>Узел инструкции по обработке помечается именем целевого приложения, заключенным в символы "<code>&lt;?</code>" и "<code>?&gt;</code>". В нижней части изображения узла пространства имен может быть указано содержимое инструкции.</p>
      <subtitle>Пример</subtitle>
      <p>Узел инструкции по обработке <code>&lt;?xsql quit?&gt;</code> может быть изображен следующим образом (рис. 3.9):</p>
      <image l:href="#img_26.png"/>
      <p><strong>Рис. 3.9</strong>. Изображение узла инструкции по обработке</p>
     </section>
     <section>
      <title>
       <p>Узел комментария</p>
      </title>
      <p>Узел комментария соответствует каждому из комментариев, которые присутствуют в документе кроме тех, которые находятся в декларации типа документа (DTD). Узлы комментариев не имеют имен; их строковым значением является текст комментария — последовательность символов после "<code>&lt;!--</code>" и до "<code>--&gt;</code>". В изображении дерева узлы комментариев будут помечаться символами "<code>&lt;!-- --&gt;</code>". В нижней части при необходимости будет указываться текст комментария.</p>
      <subtitle>Пример</subtitle>
      <p>Узел комментария <code>&lt;!-- To do... --&gt;</code> может быть изображен следующим образом (рис. 3.10):</p>
      <image l:href="#img_27.png"/>
      <p><strong>Рис. 3.10</strong>. Изображение узла комментария</p>
     </section>
     <section>
      <title>
       <p>Сводная таблица характеристик узлов</p>
      </title>
      <p>Для удобства использования мы можем свести в одну таблицу (табл. 3.1) такие характеристики узлов, как строковое значение, локальная часть имени, пространство имен и так далее.</p>
      <empty-line/>
      <p><emphasis><strong>Таблица 3.1</strong>. Характеристики различных типов узлов</emphasis></p>
      <table>
       <tr>
        <th rowspan="3" align="left">Тип узла</th>
        <th colspan="5" align="left">Характеристики</th>
       </tr>
       <tr>
        <th rowspan="2">Строковое значение</th>
        <th colspan="2" align="left">Расширенное имя</th>
        <th rowspan="2" align="left">Дочерние узлы</th>
        <th rowspan="2" align="left">Родительские узлы</th>
       </tr>
       <tr>
        <th>Локальная часть имени</th>
        <th align="left">Пространство имен</th>
       </tr>
       <tr>
        <td align="left">Корневой узел</td>
        <td align="left">Конкатенация текстовых потомков</td>
        <td colspan="2" align="left">Нет</td>
        <td align="left">Узлы элементов, комментариев, инструкций по обработке</td>
        <td align="left">Нет</td>
       </tr>
       <tr>
        <td align="left">Узел элемента</td>
        <td align="left">Конкатенация текстовых потомков</td>
        <td align="left">Имя элемента</td>
        <td align="left">Пространство имен элемента</td>
        <td align="left">Узлы элементов, комментариев, инструкций по обработке, текстовые узлы</td>
        <td align="left">Корневой узел или узел элемента</td>
       </tr>
       <tr>
        <td align="left">Узел атрибута</td>
        <td align="left">Значение атрибута</td>
        <td align="left">Имя атрибута</td>
        <td align="left">Пространство имен атрибута</td>
        <td align="left">Нет</td>
        <td align="left">Узел элемента</td>
       </tr>
       <tr>
        <td align="left">Текстовый узел</td>
        <td align="left">Символьные данные</td>
        <td colspan="2" align="left">Нет</td>
        <td align="left">Нет</td>
        <td align="left">Узел элемента</td>
       </tr>
       <tr>
        <td align="left">Узел пространства имен</td>
        <td align="left">URI пространства имен</td>
        <td align="left">Префикс пространства имен</td>
        <td align="left">Нулевое</td>
        <td align="left">Нет</td>
        <td align="left">Узел элемента</td>
       </tr>
       <tr>
        <td align="left">Узел инструкции по обработке</td>
        <td align="left">Содержимое инструкции</td>
        <td align="left">Имя целевого приложения</td>
        <td align="left">Нулевое</td>
        <td align="left">Нет</td>
        <td align="left">Корневой узел или узел элемента</td>
       </tr>
       <tr>
        <td align="left">Узел комментария</td>
        <td align="left">Текст комментария</td>
        <td colspan="2" align="left">Нет</td>
        <td align="left">Нет</td>
        <td align="left">Корневой узел или узел элемента</td>
       </tr>
      </table>
     </section>
    </section>
    <section>
     <title>
      <p>Ограничения модели XML-документа</p>
     </title>
     <p>Модель XML-документа, описанная выше, является вполне достаточной для того, чтобы манипулировать структурой документа и данными, которые он содержит. Между тем, эта модель имеет определенные ограничения, а именно:</p>
     <p>&#9633; Не учитывается информация, содержащаяся в блоке DTD. Как следствие, в XSLT невозможно манипулировать определениями сущностей, элементов, атрибутов и так далее.</p>
     <p>&#9633; Не учитываются некоторые синтаксические особенности входящего XML-документа. Например: использовались ли в определенном атрибуте одинарные или двойные кавычки; была ли определенная строка задана сущностью или просто текстом, был ли текст заключен в секции CDATA или нет.</p>
     <p>&#9633; Если атрибут элемента был определен в DTD со значением по умолчанию, то в преобразовании нельзя точно сказать, присутствовал ли он физически во входящем документе или нет.</p>
     <p>&#9633; Не учитывается, был ли пустой элемент определен как <code>&lt;b&gt;&lt;/b&gt;</code> или <code>&lt;b/&gt;</code>.</p>
     <p>Одним словом, предложенная выше модель не учитывает информацию, которая не важна с точки зрения структуры документа. На практике помимо структуры бывает также важен и детальный синтаксис документа (например, необходимо вместо <code>&amp;#160;</code> выводить <code>&amp;nbsp;</code>). К сожалению, применение XSLT для таких задач ограничено вследствие ограничений самой модели документа.</p>
    </section>
    <section>
     <title>
      <p>Порядок просмотра документа</p>
     </title>
     <p>Узлы дерева XML-документа находятся в определенном порядке, который называется порядком просмотра документа (англ. document order). Этот порядок важен для вычисления XPath-вырэжений, которые оперируют множествами узлов. Несмотря на то, что эти множества не имеют внутреннего порядка, при вычислении выражений узлы в них будут перебираться в прямом или обратном порядке просмотра документа в зависимости от того, какие оси навигации применяются в выражении.</p>
     <p>Порядок просмотра документа — это порядок, который соответствует появлению в документе первого символа текстовой записи узла. Например, для элементов это будет порядок появления в документе открывающих тегов.</p>
     <p>Более четко порядок просмотра документа определяется следующими правилами:</p>
     <p>&#9633; корневой узел является первым узлом в порядке просмотра документа;</p>
     <p>&#9633; узлы элементов предшествуют своим дочерним узлам, узлам пространств имен и узлам атрибутов;</p>
     <p>&#9633; узлы пространств имен предшествуют узлам атрибутов;</p>
     <p>&#9633; узлы атрибутов предшествуют другим дочерним узлам своего элемента;</p>
     <p>&#9633; остальные узлы упорядочиваются в последовательности их появления в документе.</p>
     <p>Обратным порядком просмотра документа называется порядок, который в точности противоположен обычному порядку просмотра документа. Обычный порядок просмотра документа также называют прямым порядком или порядком документа.</p>
     <subtitle>Пример</subtitle>
     <p>В качестве примера приведем схему дерева и выясним порядок просмотра</p>
     <p>следующего документа:</p>
     <p><code>&lt;!-- Start --&gt;</code></p>
     <p><code>&lt;?арр open?&gt;</code></p>
     <p><code>&lt;а level="0" xmlns:b="urn:b" xmlns="urn:a"&gt;</code></p>
     <p><code> alpha</code></p>
     <p><code> &lt;b:bravo/&gt;&lt;!-- To do... --&gt;&lt;charlie/&gt;</code></p>
     <p><code> delta</code></p>
     <p><code>&lt;/a&gt;</code></p>
     <p><code>&lt;?app close?&gt;</code></p>
     <p>Дерево этого документа показано на рис. 3.11. Порядок просмотра данного документа будет следующим:</p>
     <p>&#9633; корневой узел;</p>
     <p>&#9633; узел комментария <code>&lt;!-- start --&gt;</code>;</p>
     <p>&#9633; узел инструкции по обработке <code>&lt;?app open?&gt;</code>;</p>
     <p>&#9633; узел элемента <code>a</code>;</p>
     <p>&#9633; узел пространства имен <code>"urn:а"</code>;</p>
     <p>&#9633; узел пространства имен <code>"urn:b"</code>;</p>
     <p>&#9633; атрибут <code>level</code>;</p>
     <p>&#9633; текстовый узел "<code>alpha</code>";</p>
     <p>&#9633; узел элемента <code>b:bravo</code>;</p>
     <p>&#9633; узел пространства имен <code>"urn:а"</code>;</p>
     <p>&#9633; узел пространства имен <code>"urn:b</code>";</p>
     <p>&#9633; комментарий с текстом "<code>To do ...</code>";</p>
     <p>&#9633; элемент <code>charlie</code>;</p>
     <p>&#9633; узел пространства имен <code>"urn:а"</code>;</p>
     <p>&#9633; узел пространства имен <code>"urn:b"</code>;</p>
     <p>&#9633; текстовый узел "<code>delta</code>";</p>
     <p>&#9633; узел инструкции по обработке <code>&lt;?арр close?&gt;</code>.</p>
     <image l:href="#img_28.png"/>
     <p><strong>Рис. 3.11</strong>. Схема дерева XML-документа</p>
     <p>Соответственно, обратный порядок просмотра документа будет начинаться с инструкции по обработке <code>&lt;?app close?&gt;</code> и заканчиваться корневым элементом.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Типы данных</p>
    </title>
    <section>
     <p>Многие языки программирования при объявлении переменной требуют указывать, какой тип данных будет ей присваиваться. Например, в языке Java код</p>
     <p><code>int i = 15;</code></p>
     <p>объявит переменную целого типа <code>int</code> с именем <code>i</code> и присвоит ей значение <code>15</code>. В этом случае тип данных ставится в соответствие переменной. XSLT относится к динамически типизируемым языкам, в которых тип данных ассоциируется не с переменными, а со значениями.</p>
     <p>В XSLT выделяется пять типов данных:</p>
     <p>&#9633; булевый тип (boolean);</p>
     <p>&#9633; численный тип (number);</p>
     <p>&#9633; строковый тип (string);</p>
     <p>&#9633; множество узлов (node-set);</p>
     <p>&#9633; результирующий фрагмент дерева (result tree fragment).</p>
     <p>Ниже мы подробно рассмотрим особенности работы со всеми пятью типами данных.</p>
    </section>
    <section>
     <title>
      <p>Булевый тип (boolean)</p>
     </title>
     <p>Булевый тип данных в XSLT может принимать два значения — <code>true</code> ("истина") и <code>false</code> ("ложь"). В XSLT нет констант для выражения тождественной "истины" или "лжи", как во многих других языках программирования, для этих целей следует использовать функции <code>true</code> и <code>false</code>.</p>
     <p>Значение булевого типа могут быть получены путем сравнения других типов данных при помощи операторов сравнения (таких как "<code>=</code>", "<code>&gt;</code>", "<code>&lt;</code>") или как результат вычисления более сложных логических выражений с использованием операторов "<code>and</code>", "<code>or</code>" и функции <code>not</code>.</p>
     <p>Булевый тип может быть неявно преобразован в число (<code>0</code> для <code>false</code> и <code>1</code> для <code>true</code>) или в строку (<code>"false"</code> и <code>"true"</code> соответственно).</p>
     <p>Примеры:</p>
     <p><code>1=2 </code>&#8594;<code> 0 (число)</code></p>
     <p><code>not((2&gt;1) and (2&gt;3)) </code>&#8594;<code> "true" (строка)</code></p>
    </section>
    <section>
     <title>
      <p>Численный тип (number)</p>
     </title>
     <p>Численный тип в XSLT определяется как 64-битное значение с плавающей точкой, двойной точности, соответствующее стандарту IEEE 754-1985. Этот стандарт используется во многих других языках программирования, и потому можно сказать, что арифметика в XSLT работает "как обычно". Вместе с тем, стандарт IEEE 754 имеет свои нюансы, которые обязательно надо учитывать в практике программирования на XSLT.</p>
     <p>Согласно строгому определению, числа в XSLT имеют форму <code>s</code>&#215;<code>m</code>&#215;2<code><sup>x</sup></code>, где <code>s</code> — знак числа, <code>m</code> — его мантисса, а <code>x</code> — экспонента. Эти числа имеют следующие значения:</p>
     <p>&#9633; знак (<code>s</code>) равен <code>+1</code> для положительных чисел и <code>-1</code> для отрицательных;</p>
     <p>&#9633; мантисса (<code>m</code>) — это положительное целое число в интервале от <code>0</code> до <code>2<sup>53</sup>-1</code> включительно;</p>
     <p>&#9633; экспонента (<code>x</code>) — это целое число в интервале от <code>-1075</code> до <code>970</code> включительно.</p>
     <p>Таким образом, числа в XSLT находятся в интервале приблизительно от <code>-10<sup>317</sup></code> до <code>10<sup>317</sup></code>.</p>
     <p>Кроме этого выделяются пять особых значений.</p>
     <p>&#9633; Отрицательная бесконечность. Это значение представляет отрицательные числа, меньшие, чем <code>-10<sup>317</sup></code>; оно соответствует математическому значению -&#8734;. Отрицательная бесконечность может быть результатом таких операций, как деление отрицательного числа на нуль или умножение двух очень больших (в абсолютном значении) чисел разного знака в случае, когда для записи их произведения не хватит 64 бит.</p>
     <p>&#9633; Положительная бесконечность. Это значение представляет очень большие положительные числа, превосходящие <code>10<sup>317</sup></code>; оно соответствует математическому значению &#8734;. Положительная бесконечность может быть результатом таких операций, как деление положительного числа на нуль или умножение двух очень больших (в абсолютном значении) чисел одного знака в случае, когда для записи их произведения не хватит 64 бит.</p>
     <p>&#9633; Отрицательный нуль. Это значение соответствует значению предела <code>-1/x</code> при <code>x</code>, стремящемся к бесконечности. Отрицательный нуль может быть результатом таких операций, как деление отрицательного числа на бесконечность или положительного числа на отрицательную бесконечность. Отрицательный нуль может также быть получен путем деления отрицательного числа на очень большое положительное число, или, наоборот, в случае, когда для записи частного не хватает 64-битной точности.</p>
     <p>&#9633; Положительный нуль (предел <code>1/x </code>при <code>x</code>, стремящемся к бесконечности). Результат таких операций, как вычитание числа из самого себя, деление положительного числа на положительную бесконечность или отрицательного — на отрицательную бесконечность. Положительный нуль может также быть частным деления двух чисел одного знака, если для записи результата не хватает 64-битной точности.</p>
     <p>&#9633; Особое значение <code>NaN</code>, "не-число" (англ. "not-a-number"). Результат преобразования нечислового строкового значения в числовой формат.</p>
     <p>Примеры особых значений:</p>
     <p><code>-1 div 0 </code>&#8594; <code><emphasis>отрицательная бесконечность</emphasis></code></p>
     <p><code>1 div 0 </code>&#8594; <code><emphasis>положительная бесконечность</emphasis></code></p>
     <p><code>1 div (-1 div 0) </code>&#8594; <code><emphasis>отрицательный нуль</emphasis></code></p>
     <p><code>-1 div (1 div 0) </code>&#8594; <code><emphasis>отрицательный нуль</emphasis></code></p>
     <p><code>1 div (1 div 0) </code>&#8594; <code><emphasis>положительный нуль</emphasis></code></p>
     <p><code>-1 div (-1 div 0) </code>&#8594; <code><emphasis>положительный нуль</emphasis></code></p>
     <p><code>1-1 </code>&#8594; <code><emphasis>положительный нуль</emphasis></code></p>
     <p><code>number('one') </code>&#8594;<code> NaN, <emphasis>не-число</emphasis></code></p>
     <p><code>number('NaN') </code>&#8594;<code> NaN, <emphasis>не-число</emphasis></code></p>
     <p>Все числовые значения, кроме <code>NaN</code> являются упорядоченными, иначе говоря, для них определены операции сравнения.</p>
     <p>&#9633; Отрицательная бесконечность является наименьшим численным значением. Две отрицательные бесконечности равны между собой.</p>
     <p>&#9633; Отрицательные конечные числа больше отрицательной бесконечности, но меньше отрицательного нуля.</p>
     <p>&#9633; Отрицательный и положительный нули считаются равными.</p>
     <p>&#9633; Положительные конечные числа больше положительного нуля, но меньше положительной бесконечности.</p>
     <p>&#9633; Положительная бесконечность является наибольшим числом. Две положительные бесконечности находятся в равенстве, все остальные числа всегда будут меньше.</p>
     <subtitle>Примеры</subtitle>
     <p>&#9633; <code>1 div (1 div 0) &lt; 1 div 0 </code>&#8594;<code> true</code></p>
     <p>(положительный нуль меньше положительной бесконечности);</p>
     <p>&#9633; <code>1 div 0 &lt; 2 div 0 </code>&#8594;<code> false</code></p>
     <p>(положительный нуль равен другому положительному нулю);</p>
     <p>&#9633; <code>-2 div 0 &gt; -1 div 0 &gt; false -1 div 0 = -2 div 0 </code>&#8594;<code> true</code></p>
     <p>(отрицательные бесконечности равны между собой);</p>
     <p>&#9633; <code>-1 div 0 &lt; -1 </code>&#8594;<code> true</code></p>
     <p>(отрицательная бесконечность меньше любого отрицательного числа);</p>
     <p>&#9633; <code>-1 &lt; -2 div (1 div 0) </code>&#8594;<code> true</code></p>
     <p>(любое отрицательное число меньше отрицательного нуля);</p>
     <p>&#9633; <code>-2 div (1 div 0) = 1-1 </code>&#8594;<code> true</code></p>
     <p><code>1 div (1 div 0) &gt; -2 div (1 div 0) </code>&#8594;<code> false</code></p>
     <p>(отрицательный нуль равен положительному нулю);</p>
     <p>&#9633; <code>1 &gt; 1 div (1 div 0) </code>&#8594;<code> true</code></p>
     <p>(любое положительное число превосходит положительный нуль).</p>
     <p>Нечисловые значения, <code>NaN</code>, являются неупорядоченными — это означает, что, сравнивая их с другими числами, нельзя установить — больше они, меньше или равны. Результат сравнений операторами "<code>&lt;</code>", "<code>&lt;=</code>", "<code>=</code>", "<code>&gt;</code>", "<code>&gt;=</code>" будет "ложью", если хотя бы одно из сравниваемых значений — <code>NaN</code>. Единственное, что можно с точностью сказать о <code>NaN</code> — это то, что они не равны никакому другому числу, включая, собственно, нечисловые значения. То есть, если хотя бы один из операндов — <code>NaN</code>, результатом сравнения с использованием оператора "<code>!=</code>" будет "истина". Это влечет за собой интересный способ проверки, является ли значение некоторой переменной нечисловым или нет: выражение <code>$x!=$x</code> (буквально значение переменной <code>x</code> не равно значению переменной <code>x</code>) обратится в "истину" в том и только том случае, если значением <code>$x</code> является <code>NaN</code>. В шаблонных правилах эта проверка может быть записана при помощи элемента <code>xsl:if</code>:</p>
     <p><code>&lt;xsl:if test="$x != $x"&gt;</code></p>
     <p><code> &lt;xsl:text&gt;This is not a number (NaN).&lt;/xsl:text&gt;</code></p>
     <p><code>&lt;/xsl:if&gt;</code></p>
     <p>Арифметические операции в XSLT никогда не вызывают ошибки. Деление на нуль, не разрешенное во многих языках программирования, не является для XSLT исключительной ситуацией. Частным такого деления будет положительная или отрицательная бесконечность. Но все же, следует осторожно использовать "опасные" выражения, например, в сравнениях. Несколько необычное поведение операторов сравнения в операциях с NaN может создать в программе курьезные, но трудно обнаруживаемые ошибки — можно легко забыть о том, что некоторые значения могут быть не равны сами себе.</p>
     <p>Числа могут быть неявно преобразованы в булевый тип или в строку. При преобразовании числа в булевый тип, нуль (как положительный, так и отрицательный) и <code>NaN</code> преобразуются в <code>false</code>, все остальные значения (включая бесконечности) — в <code>true</code>.</p>
     <subtitle>Примеры</subtitle>
     <p><code>-1 div (1 div 0) &gt; false 1 div 0 </code>&#8594;<code> true</code></p>
     <p><code>number('NaN') &gt; false number('true') </code>&#8594;<code> false</code></p>
     <p>Результатом неявного преобразования числа в строку является:</p>
     <p>&#9633; для конечных чисел — запись числа в десятичном формате;</p>
     <p>&#9633; для нулей (и положительного, и отрицательного) — "<code>0</code>";</p>
     <p>&#9633; для бесконечностей (отрицательной и положительной) — "<code>-Infinity</code>" и "<code>Infinity</code>" соответственно;</p>
     <p>&#9633; для нечисловых значений — "<code>NaN</code>".</p>
     <subtitle>Примеры</subtitle>
     <p><code>-14 div 3 </code>&#8594;<code> '-4.666666666666667'</code></p>
     <p><code>0010.00050000 </code>&#8594;<code> '10.0005'</code></p>
     <p><code>-1 div (1 div 0) </code>&#8594;<code> '0'</code></p>
     <p><code>1 - 1 </code>&#8594;<code> '0'</code></p>
     <p><code>1 div 0 </code>&#8594;<code> 'Infinity'</code></p>
     <p><code>-2 div 0 </code>&#8594;<code> '-Infinity'</code></p>
     <p><code>number('NaN') </code>&#8594;<code> 'NaN'</code></p>
     <p><code>number('Infinity') </code>&#8594;<code> 'NaN'</code></p>
     <p>Кроме неявного преобразования в строку, XSLT предоставляет широкие возможности для форматирования числовых значений с использованием функции <code>format-number</code>.</p>
    </section>
    <section>
     <title>
      <p>Строковый тип (string)</p>
     </title>
     <p>Строки в XSLT практически не отличаются от строк в других языках программирования. Строка — это последовательность, состоящая из нуля или более символов определенного алфавита или набора символов (англ. character set). XSLT использует в качестве алфавита Unicode, что теоретически позволяет манипулировать любыми символами. Строки, которые не содержат символов, называются пустыми.</p>
     <p>Строки в XSLT записываются в виде последовательностей символов, заключенных в кавычки — одинарные или двойные. Строки часто используются внутри атрибутов элементов, которые также могут быть заключены в двойные и одинарные кавычки и, потому, из соображений удобства, существует следующее негласное соглашение — значения атрибутов заключаются в двойные кавычки, а литералы (строковые значения) — в одинарные.</p>
     <subtitle>Пример</subtitle>
     <p>Результатом выполнения элемента</p>
     <p><code>&lt;xsl:value-of select="'text'"/&gt;</code></p>
     <p>будет строковый узел со значением <code>"text"</code>, в то время как элемент</p>
     <p><code>&lt;xsl:value-of select="text"/&gt;</code></p>
     <p>создаст текстовый узел, значение которого будет равно текстовому значению элемента <code>text</code>. В первом случае выражение <code>"text"</code> являлось строкой, литералом, во втором — путем выборки.</p>
     <p>Определенную сложность создает одновременное использование в литералах двойных и одинарных кавычек — некоторые процессоры будут воспринимать их как окончание значения атрибута. Такие строки проще всего будет задавать при помощи переменных, например:</p>
     <p><code>&lt;xsl:variable name="s"&gt;</code></p>
     <p><code> &lt;xsl:text&gt;'An author of "One Flew Over Cookoo's Nest"'&lt;/xsl:text&gt;</code></p>
     <p><code>&lt;/xsl:variable&gt;</code></p>
     <p><code>&lt;xsl:value-of select="$s"/&gt;</code></p>
     <p>Следует особым образом отметить, что в XSLT, как XML-языке, символы могут быть заменены сущностями. Например, вместо символа "<code>"</code>" (двойные кавычки) можно использовать сущность <code>&amp;quot;</code>, а вместо символа "<code>'</code>" (одинарные кавычки) — <code>&amp;apos;</code>. Это позволяет использовать внутри атрибутов такие конструкции, как</p>
     <p><code>'this is a string&amp;apos;</code></p>
     <p>что эквивалентно</p>
     <p><code>'this is a string'</code></p>
     <p>На практике следует избегать таких приемов — они сильно запутывают текст программы. Сущности следует использовать только тогда, когда это действительно необходимо.</p>
     <p>Строки можно сравнивать при помощи операторов "<code>=</code>" (равно) или "<code>!=</code>" (не равно). При сравнении строки проверяются на посимвольное совпадение. Различные процессоры могут по-разному реализовывать процедуру сравнения, например, рассматривать разные символы с одним начертанием как одинаковые, но в одном можно быть точно уверенными — в случае, если на одних и тех же местах будут стоять символы с одинаковыми Unicode-кодами, строки будут равны.</p>
     <subtitle>Пример</subtitle>
     <p><code>'not' = 'n&amp;#111;&amp;#х74;&amp;apos; </code>&#8594;<code> true</code></p>
     <p>Не следует также забывать, что один символ в строке — это необязательно один байт. Более того, это необязательно некое фиксированное число байт, ведь модель символов Unicode позволяет использовать для записи символа коды переменной длины.</p>
     <p>Строка может быть приведена к булевому и численному типу.</p>
     <p>В булевом представлении пустой строке соответствует <code>false</code>, непустой — <code>true</code>. Содержимое непустой строки при этом никакой роли не играет. Булевое значение строки "<code>false</code>" будет "истиной", равно, как и булевое значение строки "<code>true</code>".</p>
     <subtitle>Примеры</subtitle>
     <p><code>'То be' or 'not to be' </code>&#8594;<code> true</code></p>
     <p><code>'Full' and '' </code>&#8594;<code> false</code></p>
     <p><code>'true' and 'false' </code>&#8594;<code> true</code></p>
     <p>При приведении к численным значениям строки разбираются как числа в десятичном формате. Если строка не является представлением числа, ее численным значением будет <code>NaN</code>. В свою очередь, результатом любых вычислений, в которых участвует <code>NaN</code>, будет также <code>NaN</code>.</p>
     <subtitle>Примеры</subtitle>
     <p><code>'2' * '2' </code>&#8594;<code> 4</code></p>
     <p><code>'one' + 'two' </code>&#8594;<code> NaN</code></p>
     <p><code>'2/3' + '5/6' </code>&#8594;<code> NaN</code></p>
     <p><code>'2' div '3' + '5' div '6' </code>&#8594;<code> 1.5</code></p>
     <p>При работе с численными значениями можно использовать следующие операторы:</p>
     <p>&#9633; <code>-</code>, унарный оператор, который выполняет отрицание своего единственного операнда — эта операция равносильна вычитанию числа из нуля;</p>
     <p>&#9633; <code>+</code>, бинарный оператор сложения, возвращает сумму своих операндов;</p>
     <p>&#9633; <code>-</code>, бинарный оператор вычитания, возвращает разность своих операндов;</p>
     <p>&#9633; <code>*</code>, бинарный оператор умножения, возвращает произведение своих операндов;</p>
     <p>&#9633; <code>div</code>, бинарный оператор деления, возвращает частное от деления первого операнда на второй;</p>
     <p>&#9633; <code>mod</code>, бинарный оператор, возвращающий остаток от деления первого операнда на второй.</p>
     <p>Обратим внимание на то, что оператор <code>div</code> в отличие от его трактовки в языке Pascal, выполняет нецелое деление. Результатом вычисления выражения <code>3 div 2</code> будет <code>1.5</code>, а не <code>1</code>.</p>
     <p>Динамическая типизация в XSLT позволяет использовать в выражениях значения разных типов — например, складывать строки и булевые значения или производить логические операции над числами. В тех случаях, когда тип данных значения отличается от типа данных, который требуется для операции, значения будут неявным образом приведены к требуемому типу, если это, конечно, возможно.</p>
    </section>
    <section>
     <title>
      <p>Множество узлов (node-set)</p>
     </title>
     <p>Несмотря на то, что XSLT оперирует логической моделью XML-документа как деревом с узлами, в XSLT нет типа данных, который соответствовал бы одному узлу. Вместо этого используется гораздо более мощный и гибкий тип данных, называемый <emphasis>множеством узлов</emphasis> (англ. node-set).</p>
     <p>Множество узлов — это чистое математическое множество, состоящее из узлов дерева: оно не содержит повторений и не имеет внутреннего порядка элементов. Множества узлов выбираются особым видом XPath-выражений, которые называются путями выборки (англ. location path).</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 3.1. Документ</subtitle>
     <p><code>&lt;А&gt;</code></p>
     <p><code> &lt;В/&gt;</code></p>
     <p><code> &lt;С&gt;</code></p>
     <p><code>  &lt;D&gt;</code></p>
     <p><code>   &lt;G/&gt;</code></p>
     <p><code>  &lt;/D&gt;</code></p>
     <p><code>  &lt;E/&gt;</code></p>
     <p><code>  &lt;F&gt;</code></p>
     <p><code>   &lt;H/&gt;</code></p>
     <p><code>   &lt;I/&gt;</code></p>
     <p><code>  &lt;/F&gt;</code></p>
     <p><code> &lt;/C&gt;</code></p>
     <p><code>&lt;/A&gt;</code></p>
     <p>Предположим, что в этом документе мы хотим выбрать все узлы, являющиеся потомками элемента <code>C</code>, который находился бы в элементе <code>A</code>, который находится в корне документа. Соответствующее XPath-выражение будет записано в виде <code>/A/C//node()</code>.</p>
     <p>Для наглядности представим наш документ в виде дерева (рис. 3.12) и выделим в нем соответствующее множество узлов.</p>
     <image l:href="#img_29.png"/>
     <p><strong>Рис. 3.12</strong>. Выбор множества узлов</p>
     <p>Выбранное множество состоит из узлов элементов <code>D</code>, <code>G</code>, <code>E</code>, <code>F</code>, <code>H</code>, I (рис. 3.13):</p>
     <image l:href="#img_30.png"/>
     <p><strong>Рис. 3.13</strong>. Выбранное множество</p>
     <p>Выбор множества не означает "клонирования", создания копий узлов, которые в него входят. Это просто выбор из всех узлов входящего документа некоторого набора, удовлетворяющего критериям, заданным путем выборки. С точки зрения программиста, множество узлов может быть представлено, как неупорядоченный список ссылок на узлы. При этом практическая реализация зависит от разработчиков конкретного процессора.</p>
     <p>В общем случае, во множество узлов не входят дети узлов, содержащихся в нем. В нашем примере узлы элементов <code>G</code>, <code>H</code> и <code>I</code> вошли в выбранное множество только потому, что они соответствовали пути выборки <code>/A/C//node()</code>. Если бы путь выборки имел вид <code>/A/C/node()</code> (то есть, выбрать всех детей узла <code>C</code>, содержащегося в узле <code>A</code>, находящемся в корне документа), результат (рис. 3.14) был бы иным.</p>
     <image l:href="#img_31.png"/>
     <p><strong>Рис. 3.14</strong>. Другой путь выборки</p>
     <p>Выбранное множество узлов имело бы вид (рис. 3.15):</p>
     <image l:href="#img_32.png"/>
     <p><strong>Рис. 3.15</strong>. Выбранное множество</p>
     <p>Для представления одного узла дерева в XSLT используется множество, состоящее из единственного узла. В предыдущем примере результатом выборки <code>/A</code> (выбрать узел <code>A</code>, находящийся в корне документа) было бы множество, состоящее из единственного узла (рис. 3.16).</p>
     <image l:href="#img_33.png"/>
     <empty-line/>
     <p><strong>Рис. 3.16</strong>. Множество, состоящее из единственного узла</p>
     <p>Несмотря на то, что множества узлов неупорядочены, во многих случаях обработка узлов множества производится в порядке просмотра документа. Некоторые элементы, обрабатывающие множества (такие, как <code>xsl:apply-templates</code> и <code>xsl:for-each</code>) позволяют предварительно выполнять их сортировку при помощи элемента <code>xsl:sort</code>.</p>
     <p>Множества узлов можно сравнивать при помощи операторов "<code>=</code>" (равно) и "<code>!=</code>" (не равно). В отличие от равенства математических множеств, равенство множеств узлов <code>A</code> и <code>B</code> в XSLT означает то, что найдется узел <code><emphasis>a</emphasis></code>, принадлежащий множеству <code>A</code> и узел <code><emphasis>b</emphasis></code>, принадлежащий множеству <code>B</code> такие, что их строковые значения будут равны. Неравенство множеств означает наличие в них как минимум пары узлов с различными строковыми представлениями. Такие определения делают возможным при сравнении двух множеств одновременное выполнение равенства и неравенства.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 3.2. Входящий документ A</subtitle>
     <p><code>&lt;numbers&gt;</code></p>
     <p><code> &lt;int&gt;1&lt;/int&gt;</code></p>
     <p><code> &lt;byte&gt;2&lt;/byte&gt;</code></p>
     <p><code> &lt;int&gt;2&lt;/int&gt;</code></p>
     <p><code> &lt;byte&gt;3&lt;/byte&gt;</code></p>
     <p><code>&lt;/numbers&gt;</code></p>
     <subtitle>Листинг 3.3. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:output method="text"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="numbers"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="int = byte"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt; and &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="int != byte"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результатом этого преобразования будет строка:</p>
     <p><code>true and true</code></p>
     <p>Этот пример показывает, что множество дочерних элементов <code>int</code> элемента <code>numbers</code> одновременно считает как равным, так и неравным множеству дочерних элементов <code>byte</code>.</p>
     <p>Приведем еще несколько примеров.</p>
     <subtitle>Листинг 3.4. Входящий документ B</subtitle>
     <p><code>&lt;numbers&gt;</code></p>
     <p><code> &lt;int&gt;1&lt;/int&gt;</code></p>
     <p><code> &lt;byte&gt;2&lt;/byte&gt;</code></p>
     <p><code> &lt;int&gt;3&lt;/int&gt;</code></p>
     <p><code> &lt;byte&gt;4&lt;/byte&gt;</code></p>
     <p><code>&lt;/numbers&gt;</code></p>
     <p>Результат:</p>
     <p><code>false and true</code></p>
     <subtitle>Листинг 3.5. Входящий документ C</subtitle>
     <p><code>&lt;numbers&gt;</code></p>
     <p><code> &lt;int&gt;1&lt;/int&gt;</code></p>
     <p><code> &lt;byte&gt;1&lt;/byte&gt;</code></p>
     <p><code> &lt;int&gt;1&lt;/int&gt;</code></p>
     <p><code>&lt;/numbers&gt;</code></p>
     <p>Результат:</p>
     <p><code>true and false</code></p>
     <p>С математической точки зрения операции сравнения множеств определены в XSLT, мягко говоря, странно. Например, единственный случай, когда для двух множеств не будет выполняться неравенство ("<code>!=</code>") — это когда все узлы обоих множеств будут иметь одинаковое строковое представление. Вместе с тем, операции сравнения множеств очень часто используются в качестве условий и потому нужно хорошо понимать различия между ними и математическими операциями сравнения.</p>
     <p>XSLT определяет единственную операцию над множествами — операцию объединения "<code>|</code>". Выражение "<code>$A | $B</code>" возвратит множество узлов, присутствующих либо в <code>$A</code>, либо в <code>$B</code>, либо и там, и там.</p>
     <p>В XSLT нет встроенного оператора, который позволил бы установить принадлежность узла некоторому множеству. Для этой цели используется очень хитроумный прием, основанный на использовании функции <code>count</code>, которая возвращает количество узлов множества. Представим, что множество <code>$node</code> содержит некоторый узел, и мы хотим проверить, входит ли он во множество <code>$nodeset</code>. Сделать это можно при помощи выражения</p>
     <p><code>count($nodeset) = count($node | $nodeset)</code></p>
     <p>которое будет истинным тогда и только тогда, когда <code>$node</code> полностью принадлежит <code>$nodeset</code>.</p>
     <p>Этот метод позволяет реализовать в XSLT другие операции над множествами — пересечение, разность и симметрическую разность. Подробное описание этих операций приводится в <emphasis>главе 11</emphasis>.</p>
     <p>В XSLT также нет оператора, который позволил бы проверить тождественность двух узлов. Например, если каждое из множеств <code>$A </code>и <code>$B</code> содержит по одному узлу, при помощи простого оператора равенства (<code>$A = $B</code>) мы не сможем проверить, один и тот же это узел или два разных узла с одинаковыми текстовыми значениями.</p>
     <p>Для того чтобы корректно выполнить такое сравнение, можно использовать функцию <code>generate-id</code>, которая для каждого из узлов дерева генерирует уникальный строковый идентификатор, присущий только этому узлу и никакому другому, причем для одних и тех же узлов идентификаторы всегда будут генерироваться одинаковыми. Таким образом, для проверки тождественности двух узлов, содержащихся во множествах <code>$A</code> и <code>$B</code>, будет достаточно сравнить их уникальные идентификаторы:</p>
     <p><code>generate-id($А) = generate-id($В)</code></p>
     <p>Множества узлов могут быть преобразованы в булевые значения, числа и строки.</p>
     <p>При преобразовании в булевый тип пустое множество узлов преобразуется в <code>false</code>, а непустое — в <code>true</code>. Например, чтобы проверить, есть ли у текущего узла атрибут <code>value</code>, можно написать:</p>
     <p><code>&lt;xsl:if test="@value"&gt;</code></p>
     <p><code> &lt;xsl:text&gt;Value attribute exists here.&lt;/xsl:text&gt;</code></p>
     <p><code>&lt;/xsl:if&gt;</code></p>
     <p>Выражение <code>@value</code> возвратит непустое множество, состоящее из узла атрибута <code>value</code>, если он есть в текущем элементе, или пустое множество, если такого атрибута нет. В первом случае логическим эквивалентом будет <code>true</code>, во втором — <code>false</code>, то есть текст будет выведен только в случае наличия атрибута <code>value</code>.</p>
     <p>При преобразовании множества узлов в строку, результатом будет строковое значение первого в порядке просмотра узла множества.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 3.6. Входящий документ</subtitle>
     <p><code>&lt;catalog&gt;</code></p>
     <p><code> &lt;item&gt;A&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;B&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;C&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;D&lt;/item&gt;</code></p>
     <p><code>&lt;/catalog&gt;</code></p>
     <subtitle>Листинг 3.7. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:output method="text"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="catalog/item"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результат:</p>
     <p><code>A</code></p>
     <p>При преобразовании множества узлов в число, множество сначала приводится к строке, а затем строка преобразуется в численное значение. Проще говоря, численным значением множества узлов будет численное значение первого узла в порядке просмотра документа.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 3.8. Входящий документ</subtitle>
     <p><code>&lt;numbers&gt;</code></p>
     <p><code> &lt;integer&gt;1&lt;/integer&gt;</code></p>
     <p><code> &lt;real&gt;1.5&lt;/real&gt;</code></p>
     <p><code> &lt;integer&gt;2&lt;/integer&gt;</code></p>
     <p><code> &lt;real&gt;2.6&lt;/real&gt;</code></p>
     <p><code> &lt;integer&gt;3&lt;/integer&gt;</code></p>
     <p><code> &lt;real&gt;3.7&lt;/real&gt;</code></p>
     <p><code>&lt;/numbers&gt;</code></p>
     <subtitle>Листинг 3.9. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:output method="text"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="numbers/real — numbers/integer"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результат:</p>
     <p><code>0.5</code></p>
    </section>
    <section>
     <title>
      <p>Результирующий фрагмент дерева (result tree fragment)</p>
     </title>
     <p>Четыре типа данных, описанных выше, заимствованы языком XSLT из XPath. Вместе с тем, XSLT имеет и свой собственный тип данных, называемый result tree fragment (результирующий фрагмент дерева).</p>
     <p>Для того чтобы понять этот тип данных, обратимся к примеру шаблона:</p>
     <p><code>&lt;xsl:template match="href"&gt;</code></p>
     <p><code> &lt;B&gt;You may visit the &lt;A HREF="{location}"&gt;following link&lt;/A&gt;.&lt;/B&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Если мы применим это правило к части документа</p>
     <p><code>&lt;href&gt;</code></p>
     <p><code> &lt;location&gt;http://www.xsltdev.ru&lt;/location&gt;</code></p>
     <p><code>&lt;/href&gt;</code></p>
     <p>то получим следующий результат:</p>
     <p><code>&lt;B&gt;You may visit the &lt;A HREF="http://www.xsltdev.ru"&gt;following link&lt;/A&gt;.&lt;/B&gt;</code></p>
     <p>В терминах деревьев выполнение этого шаблона показано на рис. 3.17.</p>
     <image l:href="#img_34.png"/>
     <p><strong>Рис. 3.17</strong>. Часть дерева входящего документа и часть дерева сгенерированного документа</p>
     <p>Поскольку XSLT оперирует документами, представленными в виде деревьев, уместнее будет сказать, что на самом деле шаблоны обрабатывают фрагменты входящего дерева и создают фрагменты исходящего. Последним и соответствует тип данных, который в XSLT называют <emphasis>результирующим фрагментом дерева</emphasis>. Попросту говоря, все, что создается шаблонами во время выполнения преобразования, является результирующими фрагментами и, в конечном итоге, дерево выходящего документа есть композиция этих фрагментов.</p>
     <p>Структурно результирующий фрагмент дерева тоже является деревом — это просто отрезанная ветка. Шаблоны генерируют ветки, используя собственные инструкции, а также результаты выполнения шаблонов, которые они вызывают и в итоге множество веток срастается в одно большое дерево, которое и является целью преобразования.</p>
     <p>Между тем, результирующие фрагменты деревьев могут и не попасть в само результирующее дерево, то есть совершенно не факт, что они всегда будут его частями. Например, результирующий фрагмент дерева может быть присвоен переменной как начальное значение. Это предоставляет следующие, очень интересные возможности.</p>
     <p>&#9633; Переменная может содержать дерево, являющееся результатом обработки документа. К сожалению, в чистом XSLT нельзя повторно обрабатывать части документов, однако, это реализуется при помощи механизма расширений.</p>
     <p>&#9633; Дерево может быть определено один раз в виде значения переменной и использовано несколько раз в выходящем документе.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 3.10. Входящий документ</subtitle>
     <p><code>&lt;href&gt;</code></p>
     <p><code> &lt;location&gt;http://www.xsltdev.ru&lt;/location&gt;</code></p>
     <p><code>&lt;/href&gt;</code></p>
     <subtitle>Листинг 3.11. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:variable name="href"&gt;</code></p>
     <p><code>  &lt;body&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="href"/&gt;</code></p>
     <p><code>  &lt;/body&gt;</code></p>
     <p><code> &lt;/xsl:variable&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="href"&gt;</code></p>
     <p><code>  &lt;B&gt;You may visit the &lt;A HREF="{location}"&gt;following link&lt;/A&gt;.&lt;/B&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;result&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;&amp;#xA;Result as string:&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="$href"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;&amp;#xA;Result as tree:&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:copy-of select="$href"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;/result&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 3.12. Выходящий документ</subtitle>
     <p><code>&lt;result&gt;</code></p>
     <p><code> Result as string:</code></p>
     <p><code> You may visit the following link.</code></p>
     <p><code> Result as tree:</code></p>
     <p><code> &lt;body&gt;&lt;B&gt;You may visit the &lt;A HREF="http://www.xsltdev.ru"&gt;following</code></p>
     <p><code>  link&lt;/A&gt;.&lt;/B&gt;</code></p>
     <p><code> &lt;/body&gt;</code></p>
     <p><code>&lt;/result&gt;</code></p>
     <p>Это преобразование легко понять, если обратиться к рис. 3.18.</p>
     <image l:href="#img_35.png"/>
     <p><strong>Рис. 3.18</strong>. Генерация выходящего дерева с использованием переменных</p>
     <p>Переменной <code>href</code> присваивается дерево, содержащее результат обработки элемента <code>href</code>, находящегося в корне входящего документа. Затем переменная <code>href</code> дважды используется в результирующем документе: один раз как строка, принадлежащая текстовому узлу, и один раз как результирующий фрагмент дерева.</p>
     <p>Дерево может быть преобразовано в булевое значение, число или строку. Некоторые процессоры позволяют также преобразовывать дерево во множество узлов, которое содержит единственный элемент — корневой узел этого дерева. Такие возможности бывают весьма полезными, но не являются, к сожалению, стандартными в текущей версии языка.</p>
     <p>При преобразовании результирующего фрагмента дерева в булевое значение результатом всегда будет true, поскольку дерево никогда не бывает "пустым" — в нем всегда присутствует корневой узел.</p>
     <p>При преобразовании дерева в строку результатом является конкатенация (строковое сложение) всех текстовых узлов дерева в порядке просмотра.</p>
     <subtitle>Пример</subtitle>
     <p>Результирующий фрагмент дерева</p>
     <p><code>&lt;body&gt;</code></p>
     <p><code>&lt;B&gt;You may visit the &lt;A HREF="http://www.xsltdev.ru"&gt;following</code></p>
     <p><code>link&lt;/A&gt;.&lt;/B&gt;</code></p>
     <p><code>&lt;/body&gt;</code></p>
     <p>приводится к строке</p>
     <p><code>The result is: You may visit the following link.</code></p>
     <p>При приведении дерева к числу, оно сначала преобразовывается в строку, а затем в число. Это означает, что деревья, в принципе, можно использовать в арифметических операциях, несмотря на то, что они для этого не предназначены.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 3.13. Входящий документ:</subtitle>
     <p><code>&lt;numbers&gt;</code></p>
     <p><code> &lt;integer&gt;1&lt;/integer&gt;</code></p>
     <p><code> &lt;real&gt;1&lt;/real&gt;</code></p>
     <p><code> &lt;integer&gt;2&lt;/integer&gt;</code></p>
     <p><code> &lt;real&gt;2&lt;/real&gt;</code></p>
     <p><code> &lt;integer&gt;3&lt;/integer&gt;</code></p>
     <p><code> &lt;real&gt;3.5&lt;/real&gt;</code></p>
     <p><code>&lt;/numbers&gt;</code></p>
     <subtitle>Листинг 3.14. Преобразование:</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:variable name="integers"&gt;</code></p>
     <p><code>  &lt;integers&gt;&lt;xsl:copy-of select="/numbers/integer"/&gt;&lt;/integers&gt;</code></p>
     <p><code> &lt;/xsl:variable&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:variable name="reals"&gt;</code></p>
     <p><code>  &lt;reals&gt;&lt;xsl:copy-of select="/numbers/real"/&gt;&lt;/reals&gt;</code></p>
     <p><code> &lt;/xsl:variable&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;result&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;&amp;#xA; Integers:&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="$integers"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;&amp;#xA;Reals:&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="$reals"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;&amp;#xA;Reals minus integers:&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="$reals - $integers"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;/result&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 3.15. Результат</subtitle>
     <p><code>&lt;result&gt;</code></p>
     <p><code>Integers:</code></p>
     <p><code>123</code></p>
     <p><code>Reals:</code></p>
     <p><code>123.5</code></p>
     <p><code>Reals minus integers:</code></p>
     <p><code>0.5</code></p>
     <p><code>&lt;/result&gt;</code></p>
    </section>
    <section>
     <title>
      <p>Таблица преобразования типов</p>
     </title>
     <p>Для удобства использования все взаимные преобразования типов сведены в одну таблицу (табл. 3.2).</p>
     <empty-line/>
     <p><emphasis><strong>Таблица 3.2</strong>. Взаимные преобразования типов данных XSLT</emphasis></p>
     <table>
      <tr>
       <th/>
       <th colspan="5">Преобразовываемый тип</th>
      </tr>
      <tr>
       <th align="left">Целевой тип</th>
       <th align="left"><code>boolean</code> (булевое значение)</th>
       <th align="left"><code>number </code>(число)</th>
       <th align="left"><code>string</code> (строка)</th>
       <th align="left"><code>node-set</code> (множество узлов)</th>
       <th align="left"><code>tree</code> (дерево)</th>
      </tr>
      <tr>
       <td align="left"><code>boolean</code> (булевое значение)</td>
       <td/>
       <td align="left"><code>0 </code>&#8594;<code> false NaN </code>&#8594; <code>false</code> другое &#8594; <code>true</code></td>
       <td align="left">пустая &#8594; <code>false</code> непустая &#8594; <code>true</code></td>
       <td align="left">пустое &#8594; <code>false </code>другое &#8594; <code>true</code></td>
       <td align="left">всегда <code>true</code></td>
      </tr>
      <tr>
       <td align="left"><code>number</code> (число)</td>
       <td align="left"><code>false</code> &#8594; <code>0 true</code> &#8594; <code>1</code></td>
       <td/>
       <td align="left">разбирается, как число в десятичном формате</td>
       <td align="left">мн-во &#8594; строка &#8594; число</td>
       <td align="left">дерево &#8594; строка &#8594; число</td>
      </tr>
      <tr>
       <td align="left"><code>string</code> (строка)</td>
       <td align="left"><code>false </code>&#8594; <code>"false" true </code>&#8594; <code>"true"</code></td>
       <td align="left">десятичная запись числа</td>
       <td/>
       <td align="left">строковое значение первого узла в порядке просмотра</td>
       <td align="left">строковое сложение всех текстовых узлов дерева</td>
      </tr>
      <tr>
       <td align="left"><code>node-set</code> (множество узлов)</td>
       <td align="left">нет</td>
       <td align="left">нет</td>
       <td align="left">нет</td>
       <td/>
       <td align="left">нет</td>
      </tr>
      <tr>
       <td align="left"><code>tree</code> (дерево)</td>
       <td align="left">нет</td>
       <td align="left">нет</td>
       <td align="left">нет</td>
       <td align="left">нет</td>
       <td/>
      </tr>
     </table>
    </section>
   </section>
   <section>
    <title>
     <p>Переменные</p>
    </title>
    <p>Несмотря на отсутствие побочных эффектов, которое является одним из основных принципов XSLT, в преобразованиях можно использовать переменные. Переменная определяется как имя, с которым связывается некоторое значение, например:</p>
    <p><code>&lt;xsl:variable name="url" select="'http://www.xsltdev.ru'"/&gt;</code></p>
    <p>создаст переменную с именем <code>url</code> и присвоит ей строковое значение <code>"http://www.xsltdev.ru"</code>. После этого переменную можно использовать в выражениях, например:</p>
    <p><code>&lt;xsl:value-of select="concat('Welcome to ', $url)"/&gt;</code></p>
    <p>Для того чтобы отличать переменные от путей выборки, в выражениях их именам предшествует префикс "<code>$</code>": к значению переменной с именем <code>url</code> мы обращались как к <code>$url</code>.</p>
    <p>Каждая из переменных имеет собственную <emphasis>область видимости</emphasis> (англ. visibility scope) — область документа преобразования, в которой может быть использовано ее значение. В зависимости от этого переменные могут быть глобальными (видимыми во всем преобразовании) и локальными (видимыми только в своем родительском элементе).</p>
    <p>Помимо переменных, в преобразованиях и шаблонных правилах могут также определяться <emphasis>параметры</emphasis>. Принцип их действия полностью совпадает с принципом действия переменных с той лишь разницей, что значения, присваиваемые параметрам, являются значениями по умолчанию и могут быть изменены извне — например, вызывающим шаблонное правило элементом типа <code>xsl:apply-templates</code> или <code>xsl:call-template</code>, или самим процессором, если речь идет о глобальных параметрах.</p>
    <p>Использование переменных и параметров в XSLT отличается от их использования в привычных процедурных языках программирования типа С++, Java или Object Pascal из-за того, что их значения не могут изменяться. После того, как переменной или параметру присвоено некоторое изначальное значение, оно будет оставаться неизменным.</p>
    <p>Это ограничение оказывает значительное влияние на стиль программирования преобразований. В этом смысле XSLT намного ближе к функциональным языкам типа Lisp. Например, в XSLT часто используется рекурсия, которая является одним из основных принципов функционального программирования.</p>
   </section>
   <section>
    <title>
     <p>Выражения</p>
    </title>
    <section>
     <p>Многие из задач, которые, так или иначе, выполняются во время преобразования, связаны с вычислением выражений. Для этих целей в XSLT используется язык XPath, который помимо выбора множеств узлов дерева может также выполнять некоторые основные операции над данными.</p>
     <cite>
      <subtitle>Замечание</subtitle>
      <p>Несмотря на то, что XPath является самостоятельным языком, его роль в XSLT настолько велика, что здесь и далее мы будем рассматривать их как единое целое.</p>
     </cite>
     <p>Можно выделить четыре основные задачи, для которых в преобразованиях используются выражения:</p>
     <p>&#9633; выбор узлов для обработки;</p>
     <p>&#9633; описание условий;</p>
     <p>&#9633; вычисление строковых значений, которые затем будут использованы в выходящем дереве;</p>
     <p>&#9633; вычисление множеств узлов, которые затем будут использованы в выходящем дереве.</p>
     <p>Первая из задач непосредственно относится к самому процессу преобразования. Выражения, содержащиеся в атрибутах <code>select</code> элементов <code>xsl:apply-templates</code> и <code>xsl:for-each</code>, вычисляют множества, к узлам которых нужно применить шаблоны.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 3.16</subtitle>
     <p><code>&lt;xsl:template match="HTML"&gt;</code></p>
     <p><code> &lt;html&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates select="HEAD"/&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates select="BODY"/&gt;</code></p>
     <p><code> &lt;/html&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>В этом шаблонном правиле содержатся два элемента <code>xsl:apply-templates</code>, которые применяют шаблоны к множествам, выбранным выражениями <code>HEAD</code> и <code>BODY</code> соответственно.</p>
     <p>Логические выражения XPath могут использоваться в качестве условий в таких элементах, как <code>xsl:if</code> и <code>xsl:when</code>, обеспечивая условную обработку.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что нам нужно выводить различные сообщения в зависимости от возрастной информации, присутствующей во входящем документе:</p>
     <subtitle>Листинг 3.17. Входящий документ</subtitle>
     <p><code>&lt;person&gt;</code></p>
     <p><code> &lt;name&gt;Johnny&lt;/name&gt;</code></p>
     <p><code> &lt;age&gt;19&lt;/age&gt;</code></p>
     <p><code>&lt;/person&gt;</code></p>
     <subtitle>Листинг 3.18. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="person"&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;xsl:if test="age &amp;gt;= 21"&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;Welcome, &lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="name"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;.&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;/xsl:if&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;xsl:if test="age &amp;lt; 21"&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;Sorry, &lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="name"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;, access denied.&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;/xsl:if&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Выделенные выражения <code>age &gt;= 21</code> и <code>age &lt; 21</code> (сущности <code>&amp;gt;</code> и <code>&amp;lt;</code> обозначают символы "<code>&lt;</code>", и "<code>&gt;</code>") определяют условия: содержимое первого элемента <code>xsl:if</code> будет выполняться, только если значение элемента <code>age</code> было не меньше <code>21</code>; содержимое второго — только если значение <code>age</code> было строго меньше <code>21</code>. Этот же самый шаблон может быть переписан с использованием элементов <code>xsl:choose</code>, <code>xsl:when</code> и <code>xsl:otherwise</code>.</p>
     <subtitle>Листинг 3.19</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="person"&gt;</code></p>
     <p><code>  &lt;xsl:choose&gt;</code></p>
     <p><code>   &lt;xsl:when test="age &amp;gt;= 21"&gt;</code></p>
     <p><code>    &lt;xsl:text&gt;Welcome, &lt;/xsl:text&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="name"/&gt;</code></p>
     <p><code>    &lt;xsl:text&gt;.&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;/xsl:when&gt;</code></p>
     <p><code>   &lt;xsl:otherwise&gt;</code></p>
     <p><code>    &lt;xsl:text&gt;Sorry, &lt;/xsl:text&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="name"/&gt;</code></p>
     <p><code>    &lt;xsl:text&gt;, access denied.&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;/xsl:otherwise&gt;</code></p>
     <p><code>  &lt;/xsl:choose&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результатом этого преобразования будет текст</p>
     <p><code>Sorry, Johnny, access denied.</code></p>
     <p>В этой строке имя <code>johnny</code> было заимствовано из входящего документа. Оно было создано элементом <code>xsl:value-of</code>:</p>
     <p><code>&lt;xsl:value-of select="name"/&gt;</code></p>
     <p>Этот элемент вычислил значение выражения <code>name</code>, которое было указано в его атрибуте <code>select</code>, преобразовал результат вычисления в строку и создал в выходящем документе текстовый узел, содержащий вычисленное значение.</p>
     <p>В данном случае выражение <code>name</code> использовалось для генерации символьных данных. Между тем, выражения вполне пригодны и для того, чтобы создавать в выходящем документе целые фрагменты:</p>
     <subtitle>Листинг 3.20. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="person"&gt;</code></p>
     <p><code>  &lt;xsl:choose&gt;</code></p>
     <p><code>   &lt;xsl:when test="age &amp;gt;= 21"&gt;</code></p>
     <p><code>    &lt;event type="access granted"&gt;</code></p>
     <p><code>     &lt;xsl:copy-of select="name"/&gt;</code></p>
     <p><code>    &lt;/event&gt;</code></p>
     <p><code>   &lt;/xsl:when&gt;</code></p>
     <p><code>   &lt;xsl:otherwise&gt;</code></p>
     <p><code>    &lt;event type="access denied"&gt;</code></p>
     <p><code>     &lt;xsl:copy-of select="name"/&gt;</code></p>
     <p><code>     &lt;reason type="underaged"&gt;</code></p>
     <p><code>      &lt;xsl:copy-of select="age"/&gt;</code></p>
     <p><code>     &lt;/reason&gt;</code></p>
     <p><code>    &lt;/event&gt;</code></p>
     <p><code>   &lt;/xsl:otherwise&gt;</code></p>
     <p><code>  &lt;/xsl:choose&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 3.21. Выходящий документ</subtitle>
     <p><code>&lt;event type="access denied"&gt;</code></p>
     <p><code> &lt;name&gt;John&lt;/name&gt;</code></p>
     <p><code> &lt;reason type="underaged"&gt;</code></p>
     <p><code>  &lt;age&gt;19&lt;/age&gt;</code></p>
     <p><code> &lt;/reason&gt;</code></p>
     <p><code>&lt;/event&gt;</code></p>
     <p>Элемент <code>xsl:copy-of</code>, который использовался в этом преобразовании, делает примерно то же самое, что и <code>xsl:value-of</code> — вычисляет значение выражения и включает его в дерево выходящего документа. Главным отличием <code>xsl:copy-of</code> является то, что при его выполнении вычисленное выражение не преобразуется в строку, что позволяет копировать в выходящее дерево множества узлов и результирующие фрагменты. В приведенном выше примере элементы <code>name</code> и <code>age</code> выходящего документа являются копиями элементов <code>name</code> и <code>age</code> входящего документа.</p>
     <p>В преобразованиях выражения могут использоваться только в атрибутах элементов и никогда — в тексте самого преобразования. Элемент</p>
     <p><code>&lt;reason type="underaged"&gt;</code></p>
     <p><code> age</code></p>
     <p><code>&lt;/reason&gt;</code></p>
     <p>будет скопирован в выходящий документ, содержащий текст "<code>age</code>". Ни о каком вычислении выражения <code>age</code> речь, конечно же, не идет. Для того чтобы в результирующий документ был скопирован результат вычисления выражения, оно должно быть заключено в атрибут одного из вычисляющих элементов, например, <code>xsl:copy-of</code>:</p>
     <p><code>&lt;reason type="underaged"&gt;</code></p>
     <p><code> &lt;xsl:copy-of select="age"/&gt;</code></p>
     <p><code>&lt;/reason&gt;</code></p>
     <p>В этом случае в элемент reason будет включен результат вычисления выражения <code>age</code>.</p>
    </section>
    <section>
     <title>
      <p>Виды выражений</p>
     </title>
     <section>
      <p>Выражения языка XPath можно условно разделить на несколько основных типов:</p>
      <p>&#9633; пути выборки;</p>
      <p>&#9633; выражения фильтрации множеств;</p>
      <p>&#9633; выражения объединения множеств;</p>
      <p>&#9633; сравнения;</p>
      <p>&#9633; логические операции;</p>
      <p>&#9633; вызовы функций.</p>
      <p>Рассмотрим подробно назначение и принципы работы каждого из типов выражений.</p>
     </section>
     <section>
      <title>
       <p>Пути выборки</p>
      </title>
      <p>Путь выборки является самым главным видом выражений, которые применяются в XSLT. Путь выборки в соответствии с некоторыми критериями выбирает множество узлов входящего документа.</p>
      <p>Путь выборки может быть абсолютным (отсчитываться от корневого узла дерева) или относительным (отсчитываться от контекстного узла). Он может состоять из нескольких шагов выборки, каждый из которых относительно предыдущего шага (или начального узла) выбирает некоторое множество узлов. Результатом вычисления пути выборки является множество узлов, выбранное его последним шагом.</p>
      <subtitle>Пример</subtitle>
      <p>Предположим, что нам нужно получить узел элемента <code>title</code>, находящийся в элементе <code>head</code>, который находится в элементе <code>html</code>, находящемся в корне документа. Соответствующий путь выборки будет выглядеть как:</p>
      <p><code>/html/head/title</code></p>
      <p>Означает он примерно следующее:</p>
      <p>&#9633; "<code>/</code>" — ведущая косая черта обозначает абсолютный путь выборки, то есть путь, который отсчитывается от корневого узла;</p>
      <p>&#9633; "<code>html</code>" — шаг выборки элементов <code>html</code>;</p>
      <p>&#9633; "<code>/</code>" — разделитель шагов выборки;</p>
      <p>&#9633; "<code>head</code>" — шаг выборки элементов <code>head</code>;</p>
      <p>&#9633; "<code>/</code>" — разделитель шагов выборки;</p>
      <p>&#9633; "<code>title</code>" — шаг выборки элементов <code>title</code>.</p>
      <p>Поскольку каждый из шагов отсчитывается от результатов предыдущего, шаг "<code>html</code>" будет выбирать элементы <code>html</code>, являющиеся дочерними элементами корневого узла и так далее. Пошаговое вычисление этого пути можно описать следующим образом:</p>
      <p>&#9633; "<code>/</code>" — путь, который выбирает корневой узел;</p>
      <p>&#9633; "<code>/html</code>" — путь, который выбирает дочерние элементы <code>html</code> корневого узла;</p>
      <p>&#9633; "<code>/html/head</code>" — путь, который выбирает дочерние элементы <code>head</code> элементов <code>html</code>, находящихся в корне документа;</p>
      <p>&#9633; "<code>/html/head/title</code>" — путь, выбирающий дочерние элементы <code>title</code> субэлементов <code>head</code> элементов <code>html</code>, которые находятся в корне документа.</p>
      <p>Можно заметить очевидную аналогию с файловыми системами: пути выборки очень похожи на пути в структуре каталогов. Между тем, пути выборки гораздо мощнее:</p>
      <p>&#9633; для каждого из шагов выборки можно указать направление, в котором он будет выбирать узлы в документе — например, дочерние узлы, узлы- потомки или, наоборот, узлы-предки или братские узлы;</p>
      <p>&#9633; выбор узлов может проводиться не только по имени, но также и по типу или принадлежности определенному пространству имен;</p>
      <p>&#9633; выбранное на каждом шаге множество может фильтроваться одним или более предикатом (в отфильтрованном множестве останутся только те из выбранных узлов, которые поочередно удовлетворяют каждому из логических условий-предикатов).</p>
      <p>Пути выборки являются средством получения информации, содержащейся в обрабатываемых документах. Неважно, что они возвращают множества узлов, неявное преобразование типов позволяет спокойно записывать выражения вида:</p>
      <p><code>data/a + data/b</code></p>
      <p>Несмотря на то, что <code>data/a </code>и <code>data/b</code> являются множествами узлов, в арифметическом выражении они будут неявно преобразованы к численному типу. То же самое касается строкового и булевого типа.</p>
     </section>
     <section>
      <title>
       <p>Фильтрующие выражения</p>
      </title>
      <p>Фильтрующие выражения выполняют две основные задачи:</p>
      <p>&#9633; выбор из вычисленного множества узлов некоторого подмножества в соответствии с заданными логическими критериями-предикатами;</p>
      <p>&#9633; вычисление путей выборки относительно узлов фильтрованного множества.</p>
      <subtitle>Примеры</subtitle>
      <p>Предположим, что переменной <code>nodeset</code> присвоено некоторое множество узлов. Задачи типа "выбрать каждый второй узел этого множества" или "выбрать первый узел этого множества" или вообще, любой выбор узлов этого множества в соответствии с некоторыми заданными логическими критериями являются задачами фильтрации. Выражение <code>$nodeset[1]</code> выберет первый в порядке просмотра документа узел множества <code>$nodeset</code>; выражение <code>$nodeset[position() mod 2 = 0]</code> выберет четные узлы множества <code>$nodeset</code>. Здесь "<code>[1]</code>" и "<code>[position() mod 2 = 0]</code>" являются предикатами — логическими выражениями, которые фильтруют множество.</p>
      <p>Фильтрующие выражения также позволяют вычислять пути выборки относительно узлов фильтруемых множеств.</p>
      <subtitle>Пример</subtitle>
      <subtitle>Листинг 3.22. Входящий документ</subtitle>
      <p><code>&lt;data&gt;</code></p>
      <p><code> &lt;string&gt;</code></p>
      <p><code>  &lt;value&gt;a&lt;/value&gt;</code></p>
      <p><code>  &lt;value&gt;b&lt;/value&gt;</code></p>
      <p><code>  &lt;value&gt;c&lt;/value&gt;</code></p>
      <p><code> &lt;/string&gt;</code></p>
      <p><code> &lt;number&gt;</code></p>
      <p><code>  &lt;value&gt;1&lt;/value&gt;</code></p>
      <p><code>  &lt;value&gt;2&lt;/value&gt;</code></p>
      <p><code>  &lt;value&gt;3&lt;/value&gt;</code></p>
      <p><code> &lt;/number&gt;</code></p>
      <p><code>&lt;/data&gt;</code></p>
      <p>Следующее преобразование демонстрирует использование относительных путей выборки в фильтрующих выражениях:</p>
      <subtitle>Листинг 3.23. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Тransform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="data"&gt;</code></p>
      <p><code>  &lt;values&gt;</code></p>
      <p><code>   &lt;xsl:copy-of select="(string | number)/value"/&gt;</code></p>
      <p><code>  &lt;/values&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 3.24. Входящий документ</subtitle>
      <p><code>&lt;values&gt;</code></p>
      <p><code> &lt;value&gt;a&lt;/value&gt;</code></p>
      <p><code> &lt;value&gt;b&lt;/value&gt;</code></p>
      <p><code> &lt;value&gt;c&lt;/value&gt;</code></p>
      <p><code> &lt;value&gt;1&lt;/value&gt;</code></p>
      <p><code> &lt;value&gt;2&lt;/value&gt;</code></p>
      <p><code> &lt;value&gt;3&lt;/value&gt;</code></p>
      <p><code>&lt;/values&gt;</code></p>
      <p>Элемент <code>values</code> выходящего документа содержит множество, являющееся результатом вычисления выражения <code>(string | number)/value</code>. Это будет множество элементов <code>value</code>, принадлежащих элементам <code>string</code> или <code>number</code>.</p>
     </section>
     <section>
      <title>
       <p>Объединение множеств</p>
      </title>
      <p>Единственная операция над множествами, которая определена в XSLT, — это операция объединения. Если <code>$nodeset1</code> и <code>$nodeset2</code> — два множества узлов, то результатом вычисления</p>
      <p><code>$nodeset1 | $nodeset2</code></p>
      <p>будет множество узлов, которые принадлежат хотя бы одному из этих множеств.</p>
      <p>Следует сказать, что, поскольку никакой тип данных не может быть преобразован во множество узлов, операнды объединения сами всегда должны быть множествами. То есть, выражение вида:</p>
      <p><code>'а' | body/a</code></p>
      <p>не добавит текстовый узел "<code>а</code>" к множеству элементов <code>а</code>, принадлежащих элементу <code>body</code> — оно просто будет некорректным.</p>
     </section>
     <section>
      <title>
       <p>Арифметические операции</p>
      </title>
      <p>Четыре основные бинарные операции — "<code>+</code>", "<code>-</code>", "<code>div</code>", "<code>mod</code>" и пятая, унарная операция отрицания "<code>-</code>" обеспечивают в XSLT основные арифметические действия. Поскольку любой из типов данных может быть преобразован в численный тип, в качестве операндов арифметических операций можно использовать что угодно — например, вычитать из строки булевое выражение:</p>
      <p><code>'0.5' - true() </code>&#8594;<code> -0.5</code></p>
      <p>Следует осторожно обращаться со знаком "<code>-</code>". Имена элементов и атрибутов могут включать этот знак и поэтому выражение <code>first-last</code> будет воспринято не как разность значений элементов <code>first</code> и <code>last</code>, а как путь выборки элементов с именами "<code>first-last</code>". Для того чтобы избежать таких казусов, операторы всегда следует выделять пробелами:</p>
      <p><code>first - last</code></p>
     </section>
     <section>
      <title>
       <p>Операции сравнения</p>
      </title>
      <p>В XSLT имеются следующие шесть операторов сравнения:</p>
      <p>&#9633; "<code>=</code>" — равно;</p>
      <p>&#9633; "<code>!=</code>" — не равно;</p>
      <p>&#9633; "<code>&lt;</code>" меньше;</p>
      <p>&#9633; "<code>&gt;</code>" больше;</p>
      <p>&#9633; "<code>&lt;=</code>" меньше или равно (не больше);</p>
      <p>&#9633; "<code>&gt;=</code>" больше или равно (не меньше).</p>
      <p>Результат этих сравнений всегда имеет булевый тип, то есть сравнение может быть либо истинным, либо ложным. Несмотря на внешнюю очевидность функций этих операторов, наличие такого типа данных, как множество узлов, делает четкое определение сравнений довольно сложным. Мы приведем его так, как оно приведено в спецификации, снабдив подробными комментариями и примерами.</p>
      <p>Операции сравнения определяются в спецификации в три этапа:</p>
      <p>&#9633; сначала сравнение, в котором участвуют множества узлов, определяется в терминах сравнения более простых типов данных;</p>
      <p>&#9633; затем для простых типов данных определяются равенство ("<code>=</code>") и неравенство ("<code>!=</code>");</p>
      <p>&#9633; наконец, для простых типов данных определяются сравнения "<code>&lt;</code>", "<code>&lt;=</code>", "<code>&gt;</code>", "<code>&gt;=</code>".</p>
      <p>Сравнение, хотя бы один из операндов которого является множеством узлов, определяется следующим образом:</p>
      <p>&#9633; если один из операндов является множеством узлов, а второй имеет булевый тип, сравнение будет истинным тогда и только тогда, когда истинным будет результат сравнения множества узлов, преобразованного к булевому типу и самого булевого операнда;</p>
      <p>&#9633; если один из операндов является множеством узлов, а второй имеет численный тип, сравнение будет истинным тогда и только тогда, когда во множестве узлов найдется такой узел, что сравнение текстового значения этого узла, преобразованного к числу, и самого численного операнда будет истинным;</p>
      <p>&#9633; если один из операндов является множеством узлов, а второй имеет строковый тип, сравнение будет истинным тогда и только тогда, когда во множестве узлов найдется такой узел, что сравнение его текстового значения и самого строкового операнда будет истинным;</p>
      <p>&#9633; если оба операнда являются множествами узлов, их сравнение будет истинным тогда и только тогда, когда найдется узел в первом множестве и узел во втором множестве, такие, что их сравнение будет истинным.</p>
      <p>Примеры выражений, которые мы будем приводить, будут использовать следующий входящий документ (листинг 3.25).</p>
      <subtitle>Листинг 3.25. Входящий документ</subtitle>
      <p><code>&lt;values&gt;</code></p>
      <p><code> &lt;string&gt;0.5&lt;/string&gt;</code></p>
      <p><code> &lt;string&gt;50%&lt;/string&gt;</code></p>
      <p><code> &lt;string&gt;1/2&lt;/string&gt;</code></p>
      <p><code> &lt;number&gt;0.5&lt;/number&gt;</code></p>
      <p><code> &lt;number&gt;1.0&lt;/number&gt;</code></p>
      <p><code> &lt;number&gt;1.5&lt;/number&gt;</code></p>
      <p><code>&lt;/values&gt;</code></p>
      <p>Примеры сравнений множества узлов с булевым значением:</p>
      <p><code>/values/string = true() </code>&#8594;<code> true</code></p>
      <p>В этом равенстве множество узлов сравнивается с булевым значением "истины". Множество узлов, выбираемое путем <code>/values/string</code>, приводится к булевому типу. Результатом приведения будет "истина", поскольку множество элементов string, принадлежащих элементу <code>values</code>, непусто. Таким образом, сравнение является проверкой на равенство двух "истин" — и результат, естественно, тоже будет "истиной".</p>
      <p><code>/values/string != boolean(/values/boolean) </code>&#8594;<code> false</code></p>
      <p>В этом случае мы проверяем множество узлов <code>/values/string</code> на неравенство булевому значению множества <code>/values/boolean</code>. Второй операнд является "истиной" (поскольку множество элементов <code>boolean</code>, принадлежащих элементу <code>values</code>, не пусто), а значит, все сравнение обратится в "ложь".</p>
      <p><code>/values/string = boolean(/values/booleans) </code>&#8594;<code> false</code></p>
      <p>В данном случае множество <code>/values/string</code> сравнивается с булевым значением множества <code>/values/booleans</code>, которое будет "ложью", поскольку это множество будет пустым. Таким образом, результат сравнения также будет "ложью".</p>
      <p><code>/values/strings = boolean(/values/booleans) </code>&#8594;<code> true</code></p>
      <p>Множества <code>/values/strings</code> и <code>/values/booleans</code> будут пустыми, поэтому, сравнивая первое с булевым значением второго, мы получим "истину", так как "ложь" равна "лжи".</p>
      <p>Примеры сравнения множества узлов с числом:</p>
      <p><code>/values/number &amp;lt; 1 </code>&#8594;<code> true</code></p>
      <p>Множество узлов <code>/values/number</code> может считаться меньше, чем число <code>1</code>, поскольку первый элемент этого множества имеет строковое значение "<code>0.5</code>", при приведении которого к числу мы получаем <code>0.5</code>, что меньше <code>1</code>.</p>
      <p><code>/values/number &amp;gt; 1 </code>&#8594;<code> true</code></p>
      <p>То же самое множество узлов может считаться также и большим <code>1</code>, поскольку последний элемент этого множества имеет строковое значение "<code>1.5</code>", при приведении которого к числу мы получаем <code>1.5</code>, что больше <code>1</code>.</p>
      <p><code>/values/number = 1 </code>&#8594;<code> true</code></p>
      <p>Второй элемент множества <code>/values/number</code> равен <code>1</code>, то есть и это сравнение будет истинным.</p>
      <p>Примеры сравнения множества узлов со строковым значением:</p>
      <p><code>/values/number = '1' </code>&#8594;<code> false</code></p>
      <p>Множество <code>/values/number</code> не будет равно строке "<code>1</code>", поскольку ни один из узлов этого множества не имеет строкового значения "<code>1</code>".</p>
      <p><code>/values/number = '1.0' </code>&#8594;<code> true</code></p>
      <p>Множество <code>/values/number</code> будет считаться равным строке "<code>1.0</code>", поскольку второй узел этого множества имеет текстовое значение "<code>1.0</code>".</p>
      <p><code>/values/number != '1.0' </code>&#8594;<code> true</code></p>
      <p>Множество <code>/values/number</code> может также считаться не равным строке "<code>1.0</code>", поскольку первый узел этого множества имеет текстовое значение "<code>0.5</code>", не равное "<code>1.0</code>".</p>
      <p>Примеры сравнения двух множеств узлов:</p>
      <p><code>/values/number = /values/string </code>&#8594;<code> true</code></p>
      <p>Для двух этих множеств будет выполняться равенство, поскольку оба они имеют по узлу с равными строковыми значениями — первый узел <code>/values/number</code> и первый узел <code>/values/string</code> равны "<code>0.5</code>". </p>
      <p><code>values/number != /values/string </code>&#8594;<code> true</code></p>
      <p>Для этих же множеств будет выполняться неравенство, поскольку в них найдется неравная пара узлов (например, узел с текстовым значением "<code>1.0</code>" в <code>/values/number</code> и узел с текстовым значением "<code>50%</code>" в <code>/values/string</code>).</p>
      <p>Определим теперь равенство и неравенство значений простых типов. При проверке на равенство или неравенство оба операнда приводятся к общему типу и сравниваются. Приведение к общему типу производится следующим образом:</p>
      <p>&#9633; если хотя бы один из операндов имеет булевый тип, второй также приводится к булевому типу;</p>
      <p>&#9633; иначе, если хотя бы один из операндов — число, второй также приводится к численному типу;</p>
      <p>&#9633; иначе, если хотя бы один из операндов — строка, второй также приводится к строковому типу.</p>
      <p>После того, как оба операнда приведены к некоторому общему типу, они проверяются на равенство или неравенства как два значения этого общего типа:</p>
      <p>&#9633; два булевых значения равны тогда и только тогда, когда они оба являются "истиной" или оба являются "ложью";</p>
      <p>&#9633; равенство численных значений понимается в обычном смысле (строгое определение равенства чисел дано в стандарте IEEE 754, но вряд ли оно представляет для нас большой интерес);</p>
      <p>&#9633; две строки равны тогда и только тогда, когда они представлены одинаковыми последовательностями Unicode-символов.</p>
      <p>Два значения простых типов (то есть — булевого, численного или строкового типа) неравны тогда и только тогда, когда для них не выполняется равенство.</p>
      <p>Примеры сравнения значений простых типов:</p>
      <p>&#9633; <code>true() = 1 </code>&#8594;<code> true</code></p>
      <p>При приведении числа <code>1</code> к булевому типу получается "истина", что и подтверждается этим равенством.</p>
      <p>&#9633; <code>true() = 100 </code>&#8594;<code> true</code></p>
      <p>Результатом приведения числа <code>100</code> к булевому типу также является "истина".</p>
      <p>&#9633; <code>false() = 'false' </code>&#8594;<code> false</code></p>
      <p>При приведении непустой строки "false" к булевому типу, получается "истина". Отсюда — неверность равенства.</p>
      <p>&#9633; <code>.5 =0.5 </code>&#8594;<code> true</code></p>
      <p><code>.5</code> и <code>0.5</code> представляют одно и то же число, хоть и они записаны в разной форме.</p>
      <p>&#9633; <code>.5 = '0.5' </code>&#8594;<code> true</code></p>
      <p>Это равенство также будет верным, поскольку результатом преобразования строки "<code>0.5</code>" в число будет также <code>0.5</code>.</p>
      <p>&#9633; <code>1 != 'two' </code>&#8594;<code> true</code></p>
      <p>Результатом преобразования строки "<code>two</code>" в численный тип будет значение <code>NaN</code>, которое не равно <code>1</code>.</p>
      <p>При сравнении с использованием операторов "<code>&lt;</code>", "<code>&lt;=</code>", "<code>&gt;</code>" и "<code>&gt;=</code>", оба операнда всегда приводятся к численному типу и сравниваются как числа.</p>
      <p>Примеры сравнений с использованием операторов "<code>&lt;</code>", "<code>&lt;=</code>", "<code>&gt;</code>" и "<code>&gt;=</code>":</p>
      <p><code>false () &amp;gt; true() </code>&#8594;<code> false</code></p>
      <p>В численном виде <code>true()</code> соответствует <code>1</code>, a <code>false()</code> — <code>0</code>, то есть это сравнение равносильно сравнению <code>0 &gt; 1</code>, результатом которого является "ложь".</p>
      <p><code>'0' &amp;lt;= false() </code>&#8594;<code> true</code></p>
      <p>Это сравнение равносильно сравнению <code>0 &lt;= 0</code>, результатом его будет "истина".</p>
      <p><code>'1' &amp;gt;= '0' </code>&#8594;<code> true</code></p>
      <p>Это сравнение равносильно сравнению <code>1 &gt;= 0</code>, результатом его будет "истина".</p>
      <p>Следует обратить внимание, на то, что символы "<code>&lt;</code>" и "<code>&gt;</code>" заменены сущностями <code>&amp;lt;</code> и <code>&amp;gt;</code> соответственно. В случае символа "<code>&lt;</code>" такая замена необходима, чтобы не нарушать выражениями синтаксис XML-документа. Заменять символ "<code>&gt;</code>" обязательной нужды нет, это делается исключительно из соображений единообразности.</p>
     </section>
     <section>
      <title>
       <p>Логические операции</p>
      </title>
      <p>В XSLT имеются две логические операции — <code>or</code> и <code>and</code>. Эти операции бинарны, то есть каждая из них определена для двух операндов. Если операнды не являются булевыми значениями, они неявным образом приводятся к булевому типу.</p>
      <p>Семантика <code>or</code> и <code>and</code> очевидна — они соответствуют операциям логического сложения и умножения.</p>
      <p>Результатом операции <code>or</code> будет "истина", если хотя бы один из операндов является "истиной". При этом если первый операнд имеет значение <code>true</code>, второй операнд не вычисляется — результат и так будет "истиной".</p>
      <p>Результатом операции <code>and</code> будет "истина", если оба операнда истинны. При этом если первый из операндов — "ложь", то второй операнд не вычисляется — результат и так будет "ложью".</p>
     </section>
     <section>
      <title>
       <p>Функции</p>
      </title>
      <p>Функции значительно расширяют возможности выражений. Они принимают на вход несколько аргументов и возвращают некоторый результат, который иногда является продуктом весьма замысловатого вычисления.</p>
      <p>Функции можно условно разделить на <emphasis>стандартные функции</emphasis>, которые определены в XPath и XSLT и должны поддерживаться (хотя на самом деле поддерживаются далеко не всегда) всеми XSLT-процессорами, и <emphasis>функции расширения</emphasis>, которые могут создаваться разработчиками в дополнение к стандартным функциям.</p>
     </section>
    </section>
    <section>
     <title>
      <p>Контекст вычисления выражений</p>
     </title>
     <p>Выражения всегда вычисляются в некотором контексте — окружении, которое зависит от того, какая часть документа обрабатывается XSLT-процессором в данный момент, и какие объявления присутствовали в самом преобразовании.</p>
     <p>Контекст преобразования состоит из узла, называемого контекстным узлом, двух целых чисел — <emphasis>размера</emphasis> контекста и <emphasis>позиции</emphasis> в контексте, объявлений переменных, объявлений пространств имен и библиотеки функций.</p>
     <p>Контекст самым непосредственным образом влияет на вычисление выражений. Относительные пути выборки отсчитываются от контекстного узла, вычисление многих функций также производится в зависимости от контекста. Кроме того, в выражениях нельзя использовать функции, пространства имен и переменные, не присутствующие в контексте.</p>
     <subtitle>Пример</subtitle>
     <p>Для того чтобы показать, как изменяется контекст во время преобразования, мы напишем шаблон, который заменяет все элементы входящего документа элементами вида:</p>
     <p><code>&lt;element</code></p>
     <p><code> name="имя элемента"</code></p>
     <p><code> context-position="позиция в контексте"</code></p>
     <p><code> context-size="размер контекста"</code></p>
     <p><code> string-value="строковое значение"&gt;</code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/element&gt;</code></p>
     <subtitle>Листинг 3.26. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:output indent="yes"/&gt;</code></p>
     <p><code> &lt;xsl:strip-space elements="*"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="*"&gt;</code></p>
     <p><code>  &lt;element</code></p>
     <p><code>   name="{name()}"</code></p>
     <p><code>   context-position="{position()}"</code></p>
     <p><code>   context-size="size()"</code></p>
     <p><code>   string-value="{.}"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="*"/&gt;</code></p>
     <p><code>  &lt;/element&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 3.27. Входящий документ</subtitle>
     <p><code>&lt;data&gt;</code></p>
     <p><code> &lt;part&gt;</code></p>
     <p><code>  &lt;item&gt;A&lt;/item&gt;</code></p>
     <p><code>  &lt;item&gt;B&lt;/item&gt;</code></p>
     <p><code>  &lt;item&gt;C&lt;/item&gt;</code></p>
     <p><code> &lt;/part&gt;</code></p>
     <p><code> &lt;part&gt;</code></p>
     <p><code>  &lt;value&gt;D&lt;/value&gt;</code></p>
     <p><code>  &lt;value&gt;E&lt;/value&gt;</code></p>
     <p><code>  &lt;value&gt;F&lt;/value&gt;</code></p>
     <p><code> &lt;/part&gt;</code></p>
     <p><code>&lt;/data&gt;</code></p>
     <subtitle>Листинг 3.28. Выходящий документ</subtitle>
     <p><code>&lt;element name="data"</code></p>
     <p><code> context-position="1" context-size="1" string-value="ABCDEF"&gt;</code></p>
     <p><code> &lt;element name="part"</code></p>
     <p><code>  context-position="1" context-size="2" string-value="ABC"&gt;</code></p>
     <p><code> &lt;element name="item"</code></p>
     <p><code>  context-position="1" context-size="3" string-value="A"/&gt;</code></p>
     <p><code> &lt;element name="item"</code></p>
     <p><code>  context-position="2" context-size="3" string-value="B"/&gt;</code></p>
     <p><code> &lt;element name="item"</code></p>
     <p><code>  context-position="3" context-size="3" string-value="C"/&gt; &lt;/element&gt;</code></p>
     <p><code> &lt;element name="part"</code></p>
     <p><code>  context-position="2" context-size="2" string-value="DEF"&gt;</code></p>
     <p><code> &lt;element name="value"</code></p>
     <p><code>  context-position="1" context-size="3" string-value="D"/&gt;</code></p>
     <p><code> &lt;element name="value"</code></p>
     <p><code>  context-position="2" context-size="3" string-value="E"/&gt;</code></p>
     <p><code> &lt;element name="value"</code></p>
     <p><code>  context-position="3" context-size="3" string-value="F"/&gt;</code></p>
     <p><code> &lt;/element&gt;</code></p>
     <p><code>&lt;/element&gt;</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Модель преобразования</p>
    </title>
    <section>
     <p>Во вводной главе мы говорили, что преобразования в XSLT являются наборами шаблонных правил, каждое из которых обрабатывает определенный фрагмент входящего документа с тем, чтобы сгенерировать фрагмент выходящего документа.</p>
    </section>
    <section>
     <title>
      <p>Контекст преобразования</p>
     </title>
     <p>При выполнении преобразования каждая из его инструкций, каждый из элементов обрабатывается в некотором <emphasis>контексте</emphasis>. Контекст преобразования состоит из двух частей: из <emphasis>текущего множества узлов</emphasis> и из <emphasis>текущего узла</emphasis>, которые показывают, что именно обрабатывается в данный момент. XSLT-процессор поочередно обрабатывает каждый из узлов текущего множества (при этом делая этот узел текущим узлом) и объединяет результаты в одно дерево.</p>
     <p>Контекст преобразования тесно связан с контекстом вычисления выражений:</p>
     <p>&#9633; текущий узел контекста преобразования соответствует контекстному узлу вычисления выражений;</p>
     <p>&#9633; позиция текущего узла в текущем обрабатываемом множестве соответствует позиции контекста вычисления выражений;</p>
     <p>&#9633; размер текущего множества узлов соответствует размеру контекста вычисления выражений.</p>
     <p>Контекст преобразования может изменяться только двумя элементами — <code>xsl:apply-templates</code> и <code>xsl:for-each</code>. Каждый из этих элементов вычисляет множество узлов, которое становится текущим и затем обрабатывается. После этого контекст преобразования восстанавливается до того состояния, каким он был перед обработкой.</p>
     <p>Изменения контекста могут быть продемонстрированы на следующем примере.</p>
     <subtitle>Листинг 3.29. Входящий документ</subtitle>
     <p><code>&lt;summer&gt;</code></p>
     <p><code> &lt;month&gt;June&lt;/month&gt;</code></p>
     <p><code> &lt;month&gt;July&lt;/month&gt;</code></p>
     <p><code> &lt;month&gt;August&lt;/month&gt;</code></p>
     <p><code>&lt;/summer&gt;</code></p>
     <p>Этому документу соответствует следующее дерево (рис. 3.19):</p>
     <image l:href="#img_36.png"/>
     <p><strong>Рис. 3.19</strong>. Дерево входящего документа</p>
     <subtitle>Листинг 3.30. Преобразование</subtitle>
     <empty-line/>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;html&gt;</code></p>
     <p><code>   &lt;head&gt;</code></p>
     <p><code>    &lt;title&gt;Summer&lt;/title&gt;</code></p>
     <p><code>   &lt;/head&gt;</code></p>
     <p><code>   &lt;body&gt;</code></p>
     <p><code>    &lt;xsl:apply-templates select="summer"/&gt;</code></p>
     <p><code>   &lt;/body&gt;</code></p>
     <p><code>  &lt;/html&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="summer"&gt;</code></p>
     <p><code>  &lt;table&gt;</code></p>
     <p><code>   &lt;tr&gt;</code></p>
     <p><code>    &lt;xsl:apply-templates select="month"/&gt;</code></p>
     <p><code>   &lt;/tr&gt;</code></p>
     <p><code>  &lt;/table&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="month"&gt;</code></p>
     <p><code>  &lt;td&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code>  &lt;/td&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Забегая вперед скажем, что в изначальном контексте преобразования текущее множество состоит из единственного узла — корневого узла документа. Он становится текущим и обрабатывается соответствующим шаблоном.</p>
     <p>В нашем случае шаблонное правило, обрабатывающее корневой узел, выглядит как:</p>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;html&gt;</code></p>
     <p><code>  &lt;head&gt;</code></p>
     <p><code>   &lt;title&gt;Summer&lt;/title&gt;</code></p>
     <p><code>  &lt;/head&gt;</code></p>
     <p><code>  &lt;body&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="summer"/&gt;</code></p>
     <p><code>  &lt;/body&gt;</code></p>
     <p><code> &lt;/html&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Тело этого шаблона выполняется в том самом изначальном контексте, о котором мы только что упомянули: текущее множество состоит из корневого узла, он же является и текущим узлом. Мы можем показать контекст, выделяя текущее множество, пунктиром, а текущий узел — полужирной линией (рис. 3.20).</p>
     <image l:href="#img_37.png"/>
     <p><strong>Рис. 3.20.</strong> Первоначальный контекст преобразования</p>
     <p>Атрибут <code>select</code> элемента <code>xsl:apply-templates</code> задает выражение, вычисляющее множество узлов, которые должны быть обработаны. Выражение <code>summer</code>, которое содержит этот атрибут, является относительным путем выборки, который возвращает все дочерние элементы <code>summer</code> текущего узла. Поскольку текущим узлом в данном контексте является корневой узел дерева, значением выражения <code>summer</code> будет множество узлов, состоящее из субэлемента summer, корневого узла.</p>
     <p>При выполнении элемента <code>xsl:apply-templates</code> процессор сделает это вычисленное множество узлов текущим множеством и начнет поочередно обрабатывать его узлы, делая их при этом текущими. Иначе говоря, выполнение элемента</p>
     <p><code>&lt;xsl:apply-templates select="summer"/&gt;</code></p>
     <p>сведется к выполнению шаблона, обрабатывающего элемент <code>summer</code>. Этот шаблон выглядит следующим образом:</p>
     <p><code>&lt;xsl:template match="summer"&gt;</code></p>
     <p><code> &lt;table&gt;</code></p>
     <p><code>  &lt;tr&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="month"/&gt;</code></p>
     <p><code>  &lt;/tr&gt;</code></p>
     <p><code> &lt;/table&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Выполняться он будет в следующем контексте (рис. 3.21):</p>
     <image l:href="#img_38.png"/>
     <p><strong>Рис. 3.21</strong>. Контекст шаблона элемента <code>summer</code></p>
     <p>Атрибут <code>select</code> элемента <code>xsl:apply-templates,</code> который присутствует в этом шаблоне, вычисляет новое текущее множество: путь выборки <code>month</code> возвращает все дочерние элементы <code>month</code> текущего узла. Текущим узлом является элемент <code>summer</code>, то есть новое текущее множество будет состоять из трех его дочерних элементов <code>month</code>. Таким образом, процессор будет поочередно выполнять шаблоны в каждом из трех следующих контекстов, показанных на рис. 3.22.</p>
     <image l:href="#img_39.png"/>
     <p><strong>Рис. 3.22</strong>. Изменение контекста при выполнении шаблона элемента <code>month</code></p>
     <p>Шаблон, вычисляемый в каждом из этих контекстов, имеет следующий вид:</p>
     <p><code>&lt;xsl:template match="month"&gt;</code></p>
     <p><code> &lt;td&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code> &lt;/td&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Элемент <code>xsl:value-of</code> этого шаблона создает в элементе <code>td</code> текстовый узел, значение которого равно строковому значению выражения "<code>.</code>", то есть строковому значению текущего узла, и в каждом случае это будет строковое значение соответствующего элемента <code>month</code>.</p>
     <p>Контекст преобразования позволяет более четко определить такие понятия, как "обработка узла", "применение шаблона к узлу" и так далее. Все эти выражения означают одно: выполнение соответствующего шаблона с данным узлом в качестве текущего.</p>
    </section>
    <section>
     <title>
      <p>Выполнение преобразования</p>
     </title>
     <p>Несмотря на полную свободу в порядке выполнения шаблонов, правила изменения контекста и компоновки результирующего дерева, спецификация XSLT оговаривает очень четко — это делает XSLT весьма гибким языком, программы на котором при этом выполняются совершенно детерминированным образом.</p>
     <p>Типовой процесс выполнения преобразования согласно спецификации включает следующие стадии:</p>
     <p>&#9633; дерево выходящего документа создается путем обработки множества, состоящего из единственного узла — текущего узла дерева;</p>
     <p>&#9633; результатом применения шаблонов к обрабатываемому множеству узлов является объединение фрагментов деревьев, которые являются результатами обработки каждого из узлов множества;</p>
     <p>&#9633; каждый из узлов обрабатываемого множества преобразуется следующим образом:</p>
     <p> • из всех шаблонов, определенных в данном преобразовании, выбираются шаблоны, соответствующие данному узлу (соответствие определяется паттерном, указанным в атрибуте <code>match</code> элемента <code>xsl:template</code>);</p>
     <p> • из этих шаблонов выбирается наиболее подходящий;</p>
     <p> • выбранный шаблон выполняется в контексте обрабатываемого множества как <emphasis>текущего множества</emphasis> узлов и обрабатываемого узла как <emphasis>текущего узла</emphasis>;</p>
     <p>&#9633; если шаблон содержит инструкции <code>xsl:apply-templates</code> или <code>xsl:foreach</code>, которые дополнительно выбирают узлы для обработки, процесс рекурсивно продолжается до тех пор, пока обрабатываемое множество будет содержать хотя бы один узел.</p>
     <p>В общих чертах этот процесс был продемонстрирован на примере, приведенном в описании контекста преобразования. Сейчас мы завершим картину, показав, как в каждом из шаблонов будут создаваться результирующие фрагменты деревьев и как они затем будут "сращиваться" в дерево выходящего документа.</p>
     <p>На сей раз, мы начнем с самых "глубоких" шаблонов — шаблонов, обрабатывающих элементы <code>month</code>.</p>
     <p><code>&lt;xsl:template match="month"&gt;</code></p>
     <p><code> &lt;td&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code> &lt;/td&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Каждый из них создает результирующий фрагмент дерева следующего вида (рис. 3.23).</p>
     <image l:href="#img_40.png"/>
     <p><strong>Рис. 3.23</strong>. Результат обработки элемента month</p>
     <p>Шаблоны к элементам <code>month</code> применяются элементом <code>xsl:apply-templates</code> при обработке элемента <code>summer</code> соответствующим шаблоном:</p>
     <p><code>&lt;xsl:template match="summer"&gt;</code></p>
     <p><code> &lt;table&gt;</code></p>
     <p><code>  &lt;tr&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="month"/&gt;</code></p>
     <p><code>  &lt;/tr&gt;</code></p>
     <p><code> &lt;/table&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p>Результатом выполнения <code>xsl:apply-templates</code> будет объединение результирующих фрагментов деревьев, которые получатся при обработке элементов <code>month</code>. Таким образом, результирующий фрагмент этого шаблона будет "собран" в следующем виде (рис. 3.24):</p>
     <image l:href="#img_41.png"/>
     <p><strong>Рис. 3.24</strong>. Результат обработки элемента <code>summer</code></p>
     <p>Пунктиром выделены результирующие фрагменты деревьев, сгенерированные при обработке элементов <code>month</code>; эти фрагменты объединяются и используются при создании фрагмента дерева, являющегося результатом обработки элемента <code>summer</code>.</p>
     <p>Этот результат, в свою очередь, используется в главном шаблоне — шаблоне, который обрабатывает корневой элемент:</p>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;html&gt;</code></p>
     <p><code>  &lt;head&gt;</code></p>
     <p><code>   &lt;title&gt;Summer&lt;/title&gt;</code></p>
     <p><code>  &lt;/head&gt;</code></p>
     <p><code>  &lt;body&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="summer"/&gt;</code></p>
     <p><code>  &lt;/body&gt;</code></p>
     <p><code> &lt;/html&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Сгенерированный при обработке элемента <code>summer</code> результирующий фрагмент дерева включается в корневом шаблоне в элемент <code>body</code> (рис.3.25).</p>
     <image l:href="#img_42.png"/>
     <p><strong>Рис. 3.25</strong>. Результат обработки корневого узла</p>
     <p>Пунктиром выделен результирующий фрагмент дерева, который был получен при обработке элемента <code>summer</code>.</p>
     <p>Результирующий фрагмент дерева, полученный в результате обработки корневого узла, является деревом выходящего документа. В чистом XSLT это и есть результат выполнения преобразования. Для того чтобы получить физическую интерпретацию — в данном случае HTML-документ, дерево <emphasis>сериализуется</emphasis>, обращаясь в следующий выходящий документ.</p>
     <subtitle>Листинг 3.31. Выходящий документ проведённого преобразования</subtitle>
     <p><code>&lt;html&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;title&gt;Summer&lt;/title&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code> &lt;body&gt;</code></p>
     <p><code>  &lt;table&gt;</code></p>
     <p><code>   &lt;tr&gt;</code></p>
     <p><code>    &lt;td&gt;June&lt;/td&gt;</code></p>
     <p><code>    &lt;td&gt;July&lt;/td&gt;</code></p>
     <p><code>    &lt;td&gt;August&lt;/td&gt;</code></p>
     <p><code>   &lt;/tr&gt;</code></p>
     <p><code>  &lt;/table&gt;</code></p>
     <p><code> &lt;/body&gt;</code></p>
     <p><code>&lt;/html&gt;</code></p>
     <p>Надо сказать, что спецификация языка XSLT не оговаривает, в каком именно порядке процессоры должны выполнять шаблонные правила — главное, чтобы результат преобразования совпадал с результатом, полученным при обработке приведенным выше способом. На практике это означает, что разработчикам совершенно необязательно знать, как именно конкретный процессор применяет правила — достаточно понимать принципы шаблонной обработки. В этом одно из главных достоинств XSLT как языка, не имеющего побочных эффектов.</p>
    </section>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 4</p>
    <p>Структура преобразования</p>
   </title>
   <section>
    <title>
     <p>Пространство имен XSLT</p>
    </title>
    <p>Для того чтобы выделить элементы и атрибуты, которые принадлежат логической схеме XSLT, в этом языке применяется механизм пространств имен. Это означает, что в документе преобразования элементы, относящиеся к XSLT, должны принадлежать его пространству имен.</p>
    <p>Уникальный идентификатор ресурса пространства имен XSLT имеет вид</p>
    <p><code>http://www.w3.org/1999/XSL/Transform</code></p>
    <p>Как отмечалось ранее, по адресу, указанному в URI пространства имен, совершенно необязательно будет находиться что-либо осмысленное. Однако в нашем случае по адресу <code>http://www.w3.org/1999/XSL/Transform</code> находится текстовый документ, содержащий единственную строчку:</p>
    <p><code>This is the XSLT namespace.</code></p>
    <p>Символ <code>1999</code> в URI пространства имен XSLT никак не соотносится с версией языка преобразования. Это просто год, который был назначен Консорциумом W3 данной спецификации и не более. Версия использованного языка определяется атрибутом <code>version</code> элемента <code>xsl:stylesheet</code>.</p>
    <p>Общепринятым префиксом пространства имен языка XSLT является префикс <code>xsl</code>. Естественно, он может быть любым другим, но в этой книге мы будем использовать именно такое обозначение. Таким образом, объявление пространства имен XSLT в общем случае будет выглядеть следующим образом: <code>xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
    <subtitle>Пример</subtitle>
    <p>Приведем пример простого преобразования, в котором объявлено пространство имен XSLT.</p>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="/"&gt;</code></p>
    <p><code>  &lt;xsl:element name="root"/&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>В некоторых случаях исходный текст намного упрощается, если пространство имен XSLT объявляется по умолчанию:</p>
    <p><code>&lt;stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;template match="/"&gt;</code></p>
    <p><code>  &lt;element name="root"/&gt;</code></p>
    <p><code> &lt;/template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/stylesheet&gt;</code></p>
    <p>Кроме этого, пространство имен по умолчанию можно снова обнулить:</p>
    <p><code>&lt;stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;template match="root"&gt;</code></p>
    <p><code>  &lt;root xmlns=""/&gt;</code></p>
    <p><code> &lt;/template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/stylesheet&gt;</code></p>
    <p>В последнем случае элемент <code>root</code> будет принадлежать нулевому пространству имен. Результат всех трех преобразований одинаков:</p>
    <p><code>&lt;root/&gt;</code></p>
    <p>Элементы XSLT могут содержать атрибуты, принадлежащие другим, но обязательно ненулевым, пространствам имен. Такие атрибуты могут содержать дополнительную информацию, но поскольку они не относятся к XSLT, обрабатываться процессором в общем случае они не будут.</p>
    <subtitle>Пример</subtitle>
    <p>Если мы определим в преобразовании элемент вида</p>
    <p><code>&lt;xsl:template match="a" xsldoc:text="Processes all a elements"</code></p>
    <p><code> xmlns:xsldoc="http://www.a.com/XSL/doc"&gt;</code></p>
    <p><code> ...</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>то в общем случае атрибут <code>xsldoc:text</code> будет проигнорирован. Однако процессор, которому знакомо пространство имен с URI <code>http://www.a.com/XSL/doc</code> сможет понять, что этот атрибут применен для документирования преобразования и будет использовать его в своих целях.</p>
   </section>
   <section>
    <title>
     <p>Корневые элементы преобразования</p>
    </title>
    <section>
     <p>За исключением случаев упрощенных преобразований, корневым элементом XSLT-документа всегда является элемент <code>xsl:stylesheet</code> или его синоним <code>xsl:transform</code>. Эти элементы полностью идентичны и различаются только именами, поэтому мы будем описывать семантику и пользоваться только элементом <code>xsl:stylesheet</code>.</p>
    </section>
    <section>
     <title>
      <p>Элементы <emphasis>xsl:stylesheet</emphasis> и <emphasis>xsl:transform</emphasis></p>
     </title>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> id="<emphasis>идентификатор</emphasis>"</code></p>
     <p><code> extension-element-prefixes="<emphasis>префиксы</emphasis>"</code></p>
     <p><code> exclude-result-prefixes="<emphasis>префиксы</emphasis>"</code></p>
     <p><code> <strong>version</strong>="<emphasis>число</emphasis>"&gt;</code></p>
     <p><code> &lt;!--</code></p>
     <p><code>  Содержимое: несколько элементов xsl:import, элементы верхнего уровня</code></p>
     <p><code> --&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:transform id="<emphasis>идентификатор</emphasis>"</code></p>
     <p><code> extension-element-prefixes="<emphasis>префиксы</emphasis>"</code></p>
     <p><code> exclude-result-prefixes="<emphasis>префиксы</emphasis>"</code></p>
     <p><code> <strong>version</strong>="<emphasis>число</emphasis>"&gt;</code></p>
     <p><code> &lt;!--</code></p>
     <p><code>  Содержимое: несколько элементов xsl:import, элементы верхнего уровня</code></p>
     <p><code> --&gt;</code></p>
     <p><code>&lt;/xsl:transform&gt;</code></p>
     <p>Элемент <code>xsl:stylesheet</code> имеет обязательный атрибут <code>version</code>, в котором указывается версия языка, использованная при создании этого преобразования. Текущей версией языка является версия 1.0, поэтому все преобразования, которые мы будем приводить в качестве примеров, будут начинаться следующим тегом:</p>
     <p><code>&lt;xsl:stylesheet version="1.0" ... &gt;</code></p>
     <p>Необязательный атрибут <code>id</code> может содержать уникальный идентификатор данного преобразования. Этот атрибут используется в тех случаях, когда преобразование включено в преобразуемый документ для его идентификации внутри этого документа.</p>
     <subtitle>Пример</subtitle>
     <p>Если преобразование, включенное в преобразуемый документ, будет иметь вид</p>
     <p><code>...</code></p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> id="trans"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p><code>...</code></p>
     <p>то ассоциироваться с документом оно будет следующей инструкцией:</p>
     <p><code>&lt;?xml-stylesheet type="text/xsl" href="#trans"?&gt;</code></p>
     <p>Необязательный атрибут <code>extension-element-prefixes</code> перечисляет префиксы пространств имен, которые определяют элементы расширения. Об использовании этого атрибута мы расскажем <emphasis>в главе 10</emphasis>, которая посвящена созданию расширений языка XSLT.</p>
     <p>Необязательный атрибут <code>exclude-result-prefixes</code> перечисляет префиксы пространств имен, определения которых не нужно включать в выходящий документ. Использование этого атрибута подробно описано <emphasis>в главе 8</emphasis>.</p>
     <p>Элемент <code>xsl:stylesheet</code> может включать следующие элементы языка XSLT:</p>
     <p>&#9633; <code>xsl:import</code>;</p>
     <p>&#9633; <code>xsl:include</code>;</p>
     <p>&#9633; <code>xsl:strip-space</code>;</p>
     <p>&#9633; <code>xsl:output</code>;</p>
     <p>&#9633; <code>xsl:key</code>;</p>
     <p>&#9633; <code>xsl:decimal-format</code>;</p>
     <p>&#9633; <code>xsl:namespace-alias</code>;</p>
     <p>&#9633; <code>xsl:attribute-set</code>;</p>
     <p>&#9633; <code>xsl:variable</code>;</p>
     <p>&#9633; <code>xsl:param</code>;</p>
     <p>&#9633; <code>xsl:template</code>. </p>
     <p>Эти элементы называются <emphasis>элементами верхнего уровня</emphasis>, поскольку они могут находиться на самом верхнем (не считая уровня корневого элемента) уровне в иерархии элементов документа. Более того, все перечисленные элементы кроме <code>xsl:variable</code> и <code>xsl:param</code> должны находиться только на верхнем уровне. Элементы <code>xsl:variable</code> и <code>xsl:param</code> могут использоваться в шаблонах, определяя локальные переменные и параметры.</p>
     <p>Если преобразование импортирует внешние модули, первыми дочерними элементами <code>xsl:stylesheet</code> должны быть элементы <code>xsl:import</code>. Иначе говоря, элементам <code>xsl:import</code> внутри <code>xsl:stylesheet</code> должны предшествовать только другие элементы <code>xsl:import</code>. Порядок всех остальных дочерних элементов <code>xsl:stylesheet</code> не имеет значения.</p>
     <p>Помимо элементов верхнего уровня, <code>xsl:stylesheet</code> может содержать элементы других, но обязательно ненулевых пространств имен. Это позволяет включать в преобразования любую сопутствующую информацию, правда спецификация оговаривает, что такого рода элементы не должны изменять поведение элементов и функций самого XSLT.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 4.1. Преобразование с элементом верхнего уровня, не принадлежащим XSLT</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code><strong> &lt;source xmlns="http://www.a.com/XSL/source"&gt;</strong></code></p>
     <p><code><strong>  Simple stylesheet</strong></code></p>
     <p><code><strong> &lt;/source&gt;</strong></code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;root/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Выделенный полужирным шрифтом на листинге 4.1 элемент <code>source</code> принадлежит пространству имен с URI <code>http://www.a.com/XSL/source</code>. Поскольку пространство имен этого элемента ненулевое, такое объявление является корректным.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Упрощенные преобразования</p>
    </title>
    <p>Многие простые преобразования состоят из единственного правила, которое обрабатывает корневой узел входящего документа. Общий вид такого рода преобразований показан в следующем листинге.</p>
    <subtitle>Листинг 4.2. Простое преобразование</subtitle>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="/"&gt;</code></p>
    <p><code>  &lt;result&gt;</code></p>
    <p><code>   &lt;!-- Шаблон --&gt;</code></p>
    <p><code>  &lt;/result&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>XSLT позволяет упрощать запись таких преобразований, опуская элементы <code>xsl:stylesheet</code> и <code>xsl:template</code> и оставляя только шаблон, создающий выходящий документ.</p>
    <p>Корневой элемент упрощенной записи должен содержать атрибут <code>xsl:version</code>, указывающий версию языка XSLT, использованного в шаблоне. Как правило, этот элемент также содержит объявление пространства имен XSLT, хотя оно может быть определено и в другом месте.</p>
    <subtitle>Пример</subtitle>
    <p>Преобразование, приведенное в листинге 4.2, можно переписать в упрощенном виде следующим образом.</p>
    <subtitle>Листинг 4.3. Упрощённая запись преобразования</subtitle>
    <p><code>&lt;result</code></p>
    <p><code> xsl:version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
    <p><code> &lt;!-- Шаблон --&gt;</code></p>
    <p><code>&lt;/result &gt;</code></p>
    <p>Приведем еще один простой пример упрощенной записи преобразования, генерирующего простейшую HTML-страницу.</p>
    <subtitle>Листинг 4.4. Упрощённая запись преобразования XML-документа в HTML</subtitle>
    <p><code>&lt;html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
    <p><code> &lt;head&gt;</code></p>
    <p><code>  &lt;title&gt;</code></p>
    <p><code>   &lt;xsl:value-of select="page/name"/&gt;</code></p>
    <p><code>  &lt;/title&gt;</code></p>
    <p><code> &lt;/head&gt;</code></p>
    <p><code> &lt;body&gt;</code></p>
    <p><code>  &lt;xsl:value-of select="page/content"/&gt;</code></p>
    <p><code> &lt;/body&gt;</code></p>
    <p><code>&lt;/html&gt;</code></p>
    <p>Следующий листинг приводит полную версию этого же преобразования.</p>
    <subtitle>Листинг 4.5. Полная запись преобразования XML-документа в HTML</subtitle>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="/"&gt;</code></p>
    <p><code>  &lt;html&gt;</code></p>
    <p><code>   &lt;head&gt;</code></p>
    <p><code>    &lt;title&gt;</code></p>
    <p><code>     &lt;xsl:value-of select="page/name"/&gt;</code></p>
    <p><code>    &lt;/title&gt;</code></p>
    <p><code>   &lt;/head&gt;</code></p>
    <p><code>   &lt;body&gt;</code></p>
    <p><code>    &lt;xsl:value-of select="page/content"/&gt;</code></p>
    <p><code>   &lt;/body&gt;</code></p>
    <p><code>  &lt;/html&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
   </section>
   <section>
    <title>
     <p>Модульная организация преобразования</p>
    </title>
    <section>
     <p>Как и любой, достаточно развитый язык программирования, XSLT обладает средствами для организации модульной структуры преобразований. Существуют два основных способа использования в преобразованиях внешних модулей — включение и импорт. Кроме того, поскольку преобразования в XSLT также являются XML-документами, для разбиения их на модули можно применять сущности.</p>
    </section>
    <section>
     <title>
      <p>Включение преобразований</p>
     </title>
     <p>Подобно тому, как мы бы использовали в языке С директиву <code>#include</code> для включения внешних файлов, преобразования в XSLT могут использовать для той же самой цели элемент <code>xsl:include</code>. Правда, в отличие от языка С, условное включение в XSLT невозможно.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:include</emphasis></p>
     </title>
     <p><code>&lt;xsl:include</code></p>
     <p><code> <strong>href</strong> = "<emphasis>URI</emphasis>"/&gt;</code></p>
     <p>Обязательный атрибут <code>href</code> элемента <code>xsl:include</code> содержит URI внешнего модуля, который должен быть включен в текущее преобразование. Внешний модуль обязан быть корректным XSLT-преобразованием.</p>
     <p>Включение внешнего преобразования является включением в прямом смысле этого слова: преобразование, включающее внешний модуль, ведет себя так, как если бы на месте элемента <code>xsl:include</code> было содержимое этого внешнего модуля.</p>
     <subtitle>Пример</subtitle>
     <p>Рассмотрим простое преобразование <code>a.xsl</code>, которое определяет значение переменной <code>date</code>.</p>
     <subtitle>Листинг 4.6. Преобразование a.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
     <p><code> &lt;xsl:variable name="date" select="'16.07.2001'"/&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Включим <code>a.xsl</code> в преобразование <code>b.xsl</code>.</p>
     <subtitle>Листинг 4.7. Преобразование b.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
     <p><code> &lt;xsl:include href="a.xsl"/&gt;</code></p>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;content&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;Today is &lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="$date"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;.&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;/content&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Включение в преобразование <code>b.xsl</code> преобразования <code>a.xsl</code> эквивалентно замене в <code>b.xsl</code> соответствующего элемента <code>xsl:include</code> на содержимое преобразования <code>a.xsl</code>. В нашем случае будет включено только определение переменной <code>date</code>. Преобразование <code>b.xsl</code> можно переписать в следующем виде: .</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
     <p><code> &lt;xsl:variable name="date" select="'16.07.2001'"/&gt;</code></p>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;content&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;Today is &lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="$date"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;.&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;/content&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>При включении внешних преобразований при помощи <code>xsl:include</code> следует учитывать некоторые особенности использования этого элемента.</p>
     <p>Все ссылки и относительные идентификаторы ресурсов (URI), используемые во включаемом преобразовании, вычисляются относительно его базового адреса.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что URI нашего преобразования имеет вид:</p>
     <p><code>http://www.xsltdev.ru/examples/a.xsl</code></p>
     <p>В этом случае элемент</p>
     <p><code>&lt;xsl:include href="b.xsl"/&gt;</code></p>
     <p>будет включать преобразование с URI</p>
     <p><code>http://www.xsltdev.ru/examples/b.xsl</code></p>
     <p>Нет никаких проблем и с включением преобразований по абсолютным идентификаторам. Например, если преобразование <code>identity.xsl</code> находится по адресу</p>
     <p><code>http://www.xsltdev.ru/stylesheets/identity.xsl</code></p>
     <p>то включить его можно элементом</p>
     <p><code>&lt;xsl:include href=" http://www.xsltdev.ru/stylesheets/identity.xsl"/&gt;</code></p>
     <p>Естественно, включаемые модули должны быть доступны процессору во время выполнения преобразования, поэтому если они находятся на других серверах, то всегда будет существовать возможность невыполнения преобразования.</p>
     <p>В XSLT элементы <code>xsl:import</code> <emphasis>всегда</emphasis> должны быть первыми дочерними элементами головного элемента <code>xsl:stylesheet</code>. Поэтому элементы <code>xsl:import</code> внешнего преобразования включаются сразу после элементов <code>xsl:import</code> основного преобразования. Если в основном преобразовании элементов <code>xsl:import</code> нет, то включаемые элементы <code>xsl:import</code> становятся первыми дочерними элементами <code>xsl:stylesheet</code> основного преобразования.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что в основное преобразование мы импортируем файл <code>a.xsl</code> и включаем файл <code>b.xsl</code>.</p>
     <subtitle>Листинг 4.8. Основное преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
     <p><code> &lt;xsl:import href="a.xsl"/&gt;</code></p>
     <p><code> &lt;xsl:variable name="a"/&gt;</code></p>
     <p><code> &lt;xsl:include href="b.xsl"/&gt;</code></p>
     <p><code> &lt;!-- Содержимое основного преобразования --&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 4.9. Преобразование b.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
     <p><code> &lt;xsl:import href="c.xsl"/&gt;</code></p>
     <p><code> &lt;!-- Содержимое преобразования b.xsl --&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Тогда основное преобразование может быть переписано следующим образом.</p>
     <subtitle>Листинг 4.10. Основное преобразование после включения b.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"&gt; &lt;xsl:import href="a.xsl"/&gt;</code></p>
     <p><code> &lt;xsl: import href=f"c.xsl"/&gt;</code></p>
     <p><code> &lt;xsl:variable name="a"/&gt;</code></p>
     <p><code> &lt;!-- Содержимое преобразования b.xsl --&gt;</code></p>
     <p><code> &lt;!-- Содержимое основного преобразования --&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Элемент <code>xsl:include</code> можно использовать и для включения преобразований с упрощенным синтаксисом. Преобразования такого рода будут включаться как эквивалентные им преобразования стандартного синтаксиса — то есть с корневым элементом <code>xsl:stylesheet</code> и единственным шаблоном, соответствующим корневому узлу.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что мы используем преобразование упрощенного синтаксиса <code>simple.xsl</code>.</p>
     <subtitle>Листинг 4.11. Преобразование simple.xsl</subtitle>
     <p><code>&lt;html xsl:version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>&lt;/html&gt;</code></p>
     <p>Включим <code>simple.xsl</code> в основное преобразование.</p>
     <subtitle>Листинг 4.12. Основное преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:include href="simple.xsl"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="a"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Тогда основное преобразование может быть переписано в следующем виде.</p>
     <subtitle>Листинг 4.13. Основное преобразование после включения simple.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code><strong> &lt;xsl:template match="/"&gt;</strong></code></p>
     <p><code><strong>  &lt;html&gt;</strong></code></p>
     <p><code><strong>   &lt;xsl:apply-templates/&gt;</strong></code></p>
     <p><code><strong>  &lt;/html&gt;</strong></code></p>
     <p><code><strong> &lt;/xsl:template&gt;</strong></code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="a"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Полужирным шрифтом на листинге 4.13 выделен шаблон, который соответствует преобразованию <code>simple.xsl</code>.</p>
     <p>Следует отметить, что разные процессоры по-разному обрабатывают включение упрощенных преобразований. К сожалению, большинство из них не поддерживают эту особенность, хотя она четко определена в спецификации, поэтому, если требуется высокая надежность и переносимость, таких включений лучше избегать.</p>
     <p>Включаемые модули являются полноценными и самостоятельными преобразованиями. К примеру, они также могут включать другие преобразования при помощи тех же элементов <code>xsl:include</code>. При этом преобразование не должно прямо или косвенно включать само себя — такая ситуация породит бесконечный цикл включений.</p>
    </section>
    <section>
     <title>
      <p>Импорт преобразований</p>
     </title>
     <p>Другим способом использования внешних модулей в XSLT является импорт преобразований, который обеспечивается элементом <code>xsl:import</code>. Импорт преобразований более сложен, чем их простое включение — последовательность импорта модулей может влиять на то, как будет выполняться преобразование. Равно как и в случае с <code>xsl:include</code>, условное импортирование преобразований не разрешено.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:import</emphasis></p>
     </title>
     <section>
      <p><code>&lt;xsl:import</code></p>
      <p><code> <strong>href</strong> =" <emphasis>URI</emphasis>"/&gt;</code></p>
      <p>Синтаксис импорта преобразования практически полностью аналогичен включению: обязательный атрибут <code>href</code> содержит URI внешнего модуля, который должен быть импортирован в текущее преобразование. Так же, как и в случае с <code>xsl:include</code>, элемент <code>xsl:import</code> логически заменяется содержимым внешнего модуля, и относительные идентификаторы ресурсов (URI), используемые во внешнем преобразовании, отсчитываются от его базового адреса. Преобразование не может прямо или косвенно импортировать само себя.</p>
      <cite>
       <subtitle>Совет</subtitle>
       <p>Не следует импортировать или включать в преобразование больше кода, чем необходимо. Если в одном импортируемом модуле находится много разнородных шаблонов, определений и так далее, лучше разбить этот модуль на несколько более мелких. Половина модуля загружается быстрее, чем модуль целиком. При этом целый модуль загружается быстрее, чем две его половины по отдельности.</p>
      </cite>
      <p>Главным отличием импорта преобразований является то, что последовательность импортирования внешних модулей, называемая <emphasis>порядком импорта</emphasis> оказывает влияние на приоритет исполнения шаблонов, определения и многое другое.</p>
     </section>
     <section>
      <title>
       <p>Порядок импорта</p>
      </title>
      <p>Как уже было сказано выше, элементы <code>xsl:import</code> должны всегда быть первыми дочерними элементами <code>xsl:stylesheet</code>. Порядок, в котором они находятся в преобразовании, определяет порядок импорта внешних модулей следующим образом.</p>
      <p>&#9633; Порядок импорта основного преобразования всегда старше порядка импорта внешнего преобразования.</p>
      <p>&#9633; В случае, если преобразование импортирует несколько внешних модулей, порядок импорта преобразований, которые импортируются раньше, младше порядка импорта последующих модулей.</p>
      <p>&#9633; Порядок импорта преобразования, включенного в основное при помощи элемента <code>xsl:include</code>, равен порядку импорта основного преобразования.</p>
      <p>Эти правила могут быть проиллюстрированы следующими примерами.</p>
      <p>Рассмотрим преобразование <code>alpha.xsl</code>, которое импортирует преобразования <code>bravo.xsl</code> и <code>сharlie.xsl</code> и включает преобразование <code>delta.xsl</code>.</p>
      <subtitle>Листинг 4.14. Фрагмент преобразования alpha.xsl</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
      <p><code> &lt;xsl:import href="bravo.xsl"/&gt;</code></p>
      <p><code> &lt;xsl:import href="charlie.xsl"/&gt;</code></p>
      <p><code> &lt;xsl:import href="delta.xsl"/&gt;</code></p>
      <p><code> &lt;!-- ... --&gt;</code></p>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <p>В соответствии с первым правилом, порядок импорта основного преобразования старше порядка импорта внешних модулей, значит <code>alpha.xsl</code> старше <code>bravo.xsl</code> и <code>charlie.xsl</code>. Далее, согласно второму правилу порядок импорта преобразования <code>bravo.xsl</code> младше порядка <code>charlie.xsl</code>, поскольку оно импортируется первым. Преобразование <code>delta.xsl</code> будет иметь порядок импорта такой же, как и у основного преобразования <code>alpha.xsl</code>. Таким образом, порядок импорта в этом примере будет иметь следующий вид:</p>
      <p><code>bravo.xsl</code></p>
      <p><code>charlie.xsl</code></p>
      <p><code>alpha.xsl delta.xsl</code></p>
      <p>Преобразование <code>bravo.xsl</code> будет самым младшим, а преобразования <code>alpha.xsl</code> и <code>delta.xsl</code> — самыми старшими.</p>
      <p>Заметим, что импортируемые преобразования могут и сами импортировать другие модули. В этих случаях вычисление порядка импорта несколько усложняется.</p>
      <p>Техническая рекомендация XSLT предлагает решать эту проблему построением логического дерева импорта.</p>
      <subtitle>Пример</subtitle>
      <p>Рассмотрим следующую схему включений и импорта (табл 4.1).</p>
      <empty-line/>
      <p><emphasis><strong>Таблица 4.1</strong>. Включение и импорт преобразований</emphasis></p>
      <table>
       <tr>
        <th align="left">Преобразование</th>
        <th align="left">Импортирует</th>
        <th align="left">Включает</th>
       </tr>
       <tr>
        <td align="left"><code>alpha.xsl</code></td>
        <td align="left"><code>bravo.xsl charlie.xsl</code></td>
        <td/>
       </tr>
       <tr>
        <td align="left"><code>bravo.xsl</code></td>
        <td align="left"><code>delta.xsl echo.xsl</code></td>
        <td align="left"><code>foxtrot.xsl</code></td>
       </tr>
       <tr>
        <td align="left"><code>charlie.xsl</code></td>
        <td align="left"><code>golf.xsl hotel.xsl</code></td>
        <td/>
       </tr>
       <tr>
        <td align="left"><code>hotel.xsl</code></td>
        <td/>
        <td align="left"><code>india.xsl</code></td>
       </tr>
      </table>
      <p>Этой схеме будет соответствовать логическое дерево импорта на рис. 4.1.</p>
      <image l:href="#img_43.png"/>
      <p><strong>Рис. 4.1</strong>. Обход дерева импорта преобразований</p>
      <p>В соответствии с правилами, левые ветки дерева будут младше правых, вершины, находящиеся ближе к корню, будут старше тех, которые дальше от него, включенные преобразования имеют тот же приоритет, что и у родителей.</p>
      <p>Таким образом, порядок импорта преобразований от младших к старшим будет выглядеть следующим образом:</p>
      <p><code>delta.xsl</code></p>
      <p><code>echo.xsl</code></p>
      <p><code>bravo.xsl foxtrot.xsl</code></p>
      <p><code>golf.xsl</code></p>
      <p><code>hotel.xsl india.xsl</code></p>
      <p><code>charlie.xsl</code></p>
      <p><code>alpha.xsl</code></p>
      <p>Порядок, в котором импортируются модули, непосредственным образом влияет на различные аспекты преобразования. Эффект, который оказывает порядок импорта на те или иные элементы, будет подробно описан при их рассмотрении — сейчас же мы их просто коротко перечислим.</p>
      <p>&#9633; <code>xsl:attribute-set</code> — порядок импорта используется для определения главенства элементов <code>xsl:attribute</code>, включенных в разные именованные списки атрибутов, но создающих атрибуты с одинаковыми именами.</p>
      <p>&#9633; <code>xsl:namespace-alias</code> — в случае, если в преобразовании определяются несколько псевдонимов префиксов пространств имен, процессор использует самый старший в порядке импорта псевдоним.</p>
      <p>&#9633; <code>xsl:output</code> — эти элементы объединяются процессором. В случае конфликтов, например, когда в разных элементах <code>xsl:output</code> атрибуты определены по-разному, процессор должен использовать старшее в порядке импорта определение.</p>
      <p>&#9633; <code>xsl:strip-space</code> и <code>xsl:preserve-space</code> — в этих элементах порядок импорта также используется для разрешения конфликтов: выигрывают определения со старшим порядком импорта.</p>
      <p>&#9633; <code>xsl:template</code> — порядок импорта используется для разрешения конфликтов, которые возникают в случаях, когда один узел может быть обработан несколькими шаблонами. Шаблон, содержащийся в преобразовании с младшим порядком импорта, будет просто исключен из рассмотрения.</p>
      <p>&#9633; <code>xsl:variable</code> и <code>xsl:param</code> — порядок импорта используется при обращении к глобальным переменным в случае, если в разных преобразованиях существуют разные определения переменной с одним именем. В подобной ситуации будет использована переменная со старшим порядком импорта.</p>
     </section>
    </section>
    <section>
     <title>
      <p>Использование сущностей для разбивки на модули</p>
     </title>
     <p>Поскольку XSLT-преобразования являются XML-документами, мы можем воспользоваться средствами XML для модульной организации данных. Части преобразований можно просто вынести во внешние документы и включать в документ в виде сущности.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 4.15. Входящий документ:</subtitle>
     <p><code>&lt;root&gt;</code></p>
     <p><code> &lt;a/&gt;</code></p>
     <p><code> &lt;b/&gt;</code></p>
     <p><code>&lt;/root&gt;</code></p>
     <subtitle>Листинг 4.16. Основное преобразование</subtitle>
     <p><code>&lt;!DOCTYPE xsl:stylesheet [</code></p>
     <p><code> &lt;!ENTITY ab SYSTEM "ab.xsl"&gt;</code></p>
     <p><code>]&gt;</code></p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="root"&gt;</code></p>
     <p><code>  &lt;ROOT&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/ROOT&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &amp;ab;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 4.17. Файл ab.xsl</subtitle>
     <p><code>&lt;xsl:template match="a"&gt;</code></p>
     <p><code> &lt;A/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:template match="b"&gt;</code></p>
     <p><code> &lt;B/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <subtitle>Листинг 4.18. Результат преобразования</subtitle>
     <p><code>&lt;ROOT&gt;</code></p>
     <p><code> &lt;A/&gt;</code></p>
     <p><code> &lt;B/&gt;</code></p>
     <p><code>&lt;/ROOT&gt;</code></p>
     <p>В этом примере в DTD-блоке мы определяем сущность с именем <code>ab</code>, которая содержит два шаблонных правила для обработки элементов <code>a</code> и <code>b</code>. Файл <code>ab.xsl</code>, в котором содержится текст внешней сущности, заменяет в документе ссылку <code>&amp;ab;</code>. После раскрытия процессором сущности (замены ссылки на ее содержимое) наше преобразование будет выглядеть следующим образом.</p>
     <subtitle>Листинг 4.19. Основное преобразование после раскрытия сущности &amp;ab;</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="root"&gt;</code></p>
     <p><code>  &lt;ROOT&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/ROOT&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="a"&gt;</code></p>
     <p><code>  &lt;A/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="b"&gt;</code></p>
     <p><code>  &lt;B/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Совместное использование преобразований и XML-документов</p>
    </title>
    <section>
     <title>
      <p>Ассоциация преобразования с XML-документом</p>
     </title>
     <p>Тем, кому приходилось работать со стилями в HTML-документах, пожалуй будет знакома конструкция вида <code>&lt;LINK REL="stylesheet"&gt;</code>, которая закрепляет за документом определенный стиль. Включив такую конструкцию, автор явным образом указывает, как следует отображать данный документ.</p>
     <p>Подобные задачи возникают и при работе с XSLT. Например, если для обработки XML-документа всегда будет использоваться одно и то же преобразование, логично будет закрепить это преобразование за документом.</p>
     <p>Для того чтобы закрепить XSLT-преобразование за XML-документом, в последнем должна быть использована инструкция по обработке <code>xml-stylesheet</code>, которая имеет следующий вид:</p>
     <p><code>&lt;?xml-stylesheet</code></p>
     <p><code> <strong>href</strong>="<emphasis>URI</emphasis>"</code></p>
     <p><code> <strong>type</strong>="<emphasis>тип</emphasis>"</code></p>
     <p><code> title="<emphasis>название</emphasis>"</code></p>
     <p><code> media="<emphasis>тип носителя</emphasis>"</code></p>
     <p><code> charset="<emphasis>кодировка</emphasis>"</code></p>
     <p><code> alternate="yes" | "no"?&gt;</code></p>
     <p>Заметим, что <code>xml-stylesheet</code> может закреплять за XML-документами не только преобразования. Основным назначением инструкции <code>xml-stylesheet</code> является ассоциация с документом фиксированного стиля (англ. <code>stylesheet</code> — стиль, стилевая таблица). С этой точки зрения преобразования являются не более, чем частным случаем стилевых таблиц.</p>
     <p>Инструкция <code>xml-stylesheet</code> содержит шесть псевдоатрибутов (приставка псевдо- поясняет, что на самом деле инструкции по обработке не имеют атрибутов), два из которых, <code>href</code> и <code>type</code>, являются обязательными. Использование псевдоатрибутов <code>xml-stylesheet</code> поясняет табл. 4.2.</p>
     <empty-line/>
     <p><emphasis><strong>Таблица 4.2</strong>. Псевдоатрибуты инструкции по обработке </emphasis><code><emphasis>xml-stylesheet</emphasis></code></p>
     <table>
      <tr>
       <th align="left">Псевдоатрибут</th>
       <th align="left">Описание</th>
      </tr>
      <tr>
       <td align="left"><code>href</code></td>
       <td align="left">Указывает местоположение стиля, закрепляемого за документом. В случае преобразований, <code>href</code> указывает местоположение преобразования, которое нужно применять к этому документу. В псевдоатрибуте <code>href</code> может быть также указан уникальный идентификатор преобразования, если оно включено в сам документ (<emphasis>см. раздел "Включение преобразования в документ"</emphasis>).</td>
      </tr>
      <tr>
       <td align="left"><code>type</code></td>
       <td align="left">Указывает тип стиля, закрепляемого за документом. В нашем случае, поскольку мы ассоциируем с документом XSLT-преобразование, псевдоатрибут <code>type</code> должен иметь значение "<code>text/xsl</code>"</td>
      </tr>
      <tr>
       <td align="left"><code>title</code></td>
       <td align="left">Задает название закрепляемого стиля. Название не имеет особого значения при обработке — оно просто поясняет назначение стиля</td>
      </tr>
      <tr>
       <td align="left"><code>media</code></td>
       <td align="left">Указывает тип носителя или устройства, для которого предназначен результирующий документ</td>
      </tr>
      <tr>
       <td align="left"><code>charset</code></td>
       <td align="left">Определяет кодировку, в которой создан стиль. Если стиль является XSLT-преобразованием, значение псевдоатрибута <code>charset</code> в расчет не принимается, поскольку кодировка преобразований явно или неявно определена в них самих</td>
      </tr>
      <tr>
       <td align="left"><code>alternate</code></td>
       <td align="left">Указывает, является ли данный стиль основным ("<code>no</code>") или альтернативным ("<code>yes</code>"). Значением этого атрибута по умолчанию является "<code>no</code>"</td>
      </tr>
     </table>
     <cite>
      <subtitle>Примечание</subtitle>
      <p>Что касается псевдоатрибута <code>type</code>, то на самом деле нет стандарта, который заставлял бы использовать значение "<code>text/xsl</code>". Рабочая группа XSL Консорциума W3 до сих пор обсуждает, какой именно тип должен быть присвоен XSLT. Поскольку XSLT есть XML-язык, формально следовало бы использовать "<code>application/xml</code>", однако с легкой подачи Microsoft все используют "<code>text/xsl</code>".</p>
     </cite>
     <p>Инструкция <code>xml-stylesheet</code> может быть включена только в пролог документа, то есть она должна предшествовать корневому элементу. Не рекомендуется включать эту инструкцию в блоки <code>DOCTYPE</code>, поскольку некоторые парсеры и процессоры будут ее в этом случае игнорировать.</p>
     <subtitle>Примеры</subtitle>
     <p>Стандартный механизм использования <code>xml-stylesheet</code> может быть продемонстрирован следующим документом:</p>
     <p><code>&lt;?xml version="1.0"?&gt;</code></p>
     <p><code>&lt;?xml-stylesheet type="text/xsl" href="mytransform.xsl"?&gt;</code></p>
     <p><code>&lt;body&gt;</code></p>
     <p><code> &lt;!-- ... --&gt;</code></p>
     <p><code>&lt;/body&gt;</code></p>
     <p>В этом документе инструкция <code>xml-stylesheet</code> указывает на то, что этот документ должен быть обработан XSLT-преобразованием <code>mytransform.xsl</code>.</p>
     <p>Псевдоатрибут <code>title</code> может содержать краткое описание применяемого преобразования:</p>
     <p><code>&lt;?xml-stylesheet</code></p>
     <p><code> title="Generate menu"</code></p>
     <p><code> type="text/xsl"</code></p>
     <p><code> href="menu.xsl"?&gt;</code></p>
     <p>Псевдоатрибуты <code>media</code> и <code>alternate</code> могут использоваться совместно для того, чтобы описать альтернативное представление документа, к примеру, на небольших мобильных устройствах:</p>
     <p><code>&lt;?xml-stylesheet</code></p>
     <p><code> type="text/xsl"</code></p>
     <p><code> href="pda.xsl"</code></p>
     <p><code> alternate="yes"</code></p>
     <p><code> media="handheld"?&gt;</code></p>
     <p>Теоретически, если документ с такой инструкцией будет показываться на мобильном устройстве (например, на Palm Pilot), он должен быть преобразован при помощи <code>pda.xsl</code>. На практике не следует полагаться на подобные возможности, поскольку они сильно зависят от поддержки серверов и процессоров, которая в этом отношении все еще сильно ограничена.</p>
     <p>В заключение описания инструкции <code>xml-stylesheet</code> приведем правила, которые определяют ее синтаксис.</p>
     <p><code>[XMS1] StyleSheetPI    ::= '&lt;?xml-stylesheet' (S PseudoAtt)* S? '?&gt;'</code></p>
     <p><code>[XMS2] PseudoAtt       ::= Name S? '=' S? PseudoAttValue</code></p>
     <p><code>[XMS3] PseudoAttValue  ::= ( '"' ([^"&lt;&amp;]|CharRef|PredefEntityRef)* '"'</code></p>
     <p><code>                           | "'" ([^'&lt;&amp;]|CharRef|PredefEntityRef)* "'")</code></p>
     <p><code>                           - (Char* '?&gt;' Char*)</code></p>
     <p><code>[XMS4] PredefEntityRef ::= '&amp;quot;' | '&amp;lt;'</code></p>
     <p><code>                           | '&amp;gt;' | '&amp;amp;' | '&amp;apos;'</code></p>
    </section>
    <section>
     <title>
      <p>Объединение документа и преобразования</p>
     </title>
     <section>
      <p>XSLT-преобразование является, как правило, самостоятельным XML-документом, корневым элементом которого является <code>xsl:stylesheet</code> или <code>xsl:transform</code>. Вместе с тем, иногда бывает необходимо объединять преобразуемый документ и само преобразование так, чтобы они находились в одном файле.</p>
      <p>Мы опишем два способа объединения документов и преобразований. Первый основывается на использовании инструкции <code>xml-stylesheet</code> для того, чтобы закрепить за документом преобразование, находящееся внутри него самого. Во втором способе обрабатываемый документ включается в преобразование как пользовательский элемент верхнего уровня и обрабатывается при помощи функции <code>document('')</code> с пустым строковым параметром.</p>
     </section>
     <section>
      <title>
       <p>Включение преобразования в документ</p>
      </title>
      <p>Корневой элемент преобразования <code>xsl:stylesheet</code> может быть включен в преобразуемый документ со всеми дочерними элементами верхнего уровня и так далее. Для того чтобы использовать это преобразование, псевдоатрибут <code>href</code> инструкции по обработке <code>xml-stylesheet</code> должен указывать на идентификатор элемента <code>xsl:stylesheet</code>, определенный в его атрибуте <code>id</code>.</p>
      <subtitle>Пример</subtitle>
      <subtitle>Листинг 4.20. Входящий документ</subtitle>
      <p><code>&lt;?xml version="1.0"?&gt;</code></p>
      <p><code>&lt;?xml-stylesheet type="text/xml" href="#transform"?&gt;</code></p>
      <p><code>&lt;page&gt;</code></p>
      <p><code> &lt;title&gt;Main page&lt;/title&gt;</code></p>
      <p><code> &lt;content&gt;Main content&lt;/content&gt;</code></p>
      <p><code> &lt;xsl:stylesheet</code></p>
      <p><code>  id="transform"</code></p>
      <p><code>  version="1.0"</code></p>
      <p><code>  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
      <p><code>  &lt;xsl:template match="/"&gt;</code></p>
      <p><code>   &lt;body title="{page/title}"&gt;</code></p>
      <p><code>    &lt;xsl:text&gt;&lt;xsl:value-of select="page/content"/&gt;&lt;/xsl:text&gt;</code></p>
      <p><code>   &lt;/body&gt;</code></p>
      <p><code>  &lt;/xsl:template&gt;</code></p>
      <p><code>  &lt;xsl:template match="xsl:stylesheet"/&gt;</code></p>
      <p><code> &lt;/xsl:stylesheet&gt;</code></p>
      <p><code>&lt;/page&gt;</code></p>
      <subtitle>Листинг 4.21. Выходящий документ</subtitle>
      <p><code>&lt;body title="Main page"&gt;</code></p>
      <p><code> Main content</code></p>
      <p><code>&lt;/body&gt;</code></p>
      <p>Поскольку элемент <code>xsl:stylesheet</code> включен в преобразуемый документ, он также подвергнется преобразованию. Для того чтобы избежать этого, в преобразование включается шаблонное правило, которое указывает, что элементы <code>xsl:stylesheet</code> следует игнорировать:</p>
      <p><code>&lt;xsl:template match="xsl:stylesheet"/&gt;</code></p>
      <p>К сожалению, приходится констатировать тот факт, что описанную возможность (хотя она и включена в спецификацию языка XSLT) поддерживают очень немногие процессоры и поэтому пока что на нее не следует полагаться.</p>
     </section>
     <section>
      <title>
       <p>Включение документа в преобразование</p>
      </title>
      <p>Другой возможностью объединения документов и преобразований является включение элемента документа в преобразование в виде элемента верхнего уровня.</p>
      <p>Поскольку преобразование также является XML-документом, доступ к данным, которые оно содержит можно получить при помощи функции <code>document</code>, так же, как если бы документ преобразования был внешним документом. Функция <code>document</code>, которой в качестве параметра была передана пустая строка, возвращает множество, состоящее из корневого узла самого преобразования. То есть, если документ был включен в преобразование в качестве элемента верхнего уровня с именем, к примеру, <code>user:input</code>, получить доступ к нему можно при помощи выражения</p>
      <p><code>document('')/xsl:stylesheet/user:input</code></p>
      <subtitle>Пример</subtitle>
      <subtitle>Листинг 4.22. Входящий документ</subtitle>
      <p><code>&lt;whatever/&gt;</code></p>
      <subtitle>Листинг 4.23. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:user="urn:user"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform" </code></p>
      <p><code> exclude-result-prefixes="user"&gt;</code></p>
      <p><code><strong> &lt;input xmlns="urn:user"&gt;</strong></code></p>
      <p><code><strong>  &lt;a/&gt;</strong></code></p>
      <p><code><strong>  &lt;b/&gt;</strong></code></p>
      <p><code><strong> &lt;/input&gt;</strong></code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="/"&gt;</code></p>
      <p><code>  &lt;xsl:apply-templates</code></p>
      <p><code>   select="document('')/xsl:stylesheet/user:input"/&gt;</code></p>
      <p><code>  &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="user:a"&gt;</code></p>
      <p><code>  &lt;A/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="user:b"&gt;</code></p>
      <p><code>  &lt;B/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="user:input"&gt;</code></p>
      <p><code>  &lt;output&gt;</code></p>
      <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
      <p><code>  &lt;/output&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 4.24. Выходящий документ</subtitle>
      <p><code>&lt;output&gt;</code></p>
      <p><code> &lt;A/&gt;</code></p>
      <p><code> &lt;B/&gt;</code></p>
      <p><code>&lt;/output&gt;</code></p>
      <p>Следует обратить внимание на следующие особенности этого примера.</p>
      <p>&#9633; Элементы верхнего уровня в обязательном порядке должны иметь ненулевое пространство имен. Поэтому мы включили элемент <code>input</code> и все его дочерние узлы в пространство имен <code>urn:user</code>. В листинге 4.23 эти элементы выделены полужирным шрифтом.</p>
      <p>&#9633; В шаблонах, которые обрабатывают элементы включенного документа, должны указываться паттерны, соответствующие расширенным именам этих элементов, то есть не <code>input</code>, a <code>user:input</code>.</p>
      <p>&#9633; Чтобы не выводить объявления пространств имен в выходящем документе, мы включили префикс <code>user</code> в атрибут <code>exclude-result-prefixes</code> элемента <code>xsl:stylesheet</code>.</p>
      <p>Как можно видеть, включение элемента <code>input</code> как элемента верхнего уровня породило определенные проблемы. Для того чтобы избежать их, можно воспользоваться маленьким фокусом — включать документ не <emphasis>как</emphasis> элемент верхнего уровня, а <emphasis>в</emphasis> элемент верхнего уровня.</p>
      <subtitle>Пример</subtitle>
      <p>Результат следующего преобразования в точности совпадает с результатом преобразования в предыдущем примере.</p>
      <subtitle>Листинг 4.25. Пользовательские данные в элементе верхнего уровня</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template name="input"&gt;</code></p>
      <p><code>  &lt;input&gt;</code></p>
      <p><code>   &lt;a/&gt;</code></p>
      <p><code>   &lt;b/&gt;</code></p>
      <p><code>  &lt;/input&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="/"&gt;</code></p>
      <p><code>  &lt;xsl:apply-templates</code></p>
      <p><code>   select="document('')/</code></p>
      <p><code>   xsl:stylesheet/xsl:template[@name='input']/input"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="a"&gt;</code></p>
      <p><code>  &lt;A/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="b"&gt;</code></p>
      <p><code>  &lt;B/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="input"&gt;</code></p>
      <p><code>  &lt;output&gt;</code></p>
      <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
      <p><code>  &lt;/output&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <p>Хитрость заключается в том, что мы обрабатываем содержимое именованного шаблона, которое вполне может принадлежать нулевому пространству имен. Единственное, что следует иметь в виду — это то, что этот шаблон не должен конфликтовать с другими шаблонами.</p>
      <p>В отличие от предыдущего варианта с преобразованием, включенным в документ, этот способ является гораздо более работоспособным. Минусом его является только то, что на вход все равно должен подаваться какой-нибудь XML-документ, даже если его содержимое и не обрабатывается.</p>
     </section>
    </section>
   </section>
   <section>
    <title>
     <p>Литеральные элементы результата</p>
    </title>
    <section>
     <p>Как мы уже видели из множества примеров, преобразования состоят не только из элементов языка XSLT. Например, в шаблоне</p>
     <p><code>&lt;xsl:template match="b"&gt;</code></p>
     <p><code> &lt;В/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>элемент <code>B</code> не принадлежит пространству имен XSLT и, следовательно, не считается XSLT-элементом. Такие элементы называются <emphasis>литеральными элементами результата</emphasis> (англ. literal result elements).</p>
     <p>Когда процессор выполняет шаблон, содержащий литеральные результирующие элементы, для них в результирующем документе создаются элементы с тем же расширенным именем и атрибутами, содержимым которых является результат выполнения содержимого литерального элемента в преобразовании.</p>
     <p>Попросту говоря, литеральные элементы выводятся в результирующий документ без изменений; но их содержимое при этом все же выполняется.</p>
     <subtitle>Пример</subtitle>
     <p>В предыдущем случае шаблон содержал пустой литеральный элемент <code>B</code>. При выполнении этого правила процессор просто создаст в результирующем документе элемент с тем же расширенным именем и пустым содержимым — то есть это будет его точная копия.</p>
     <p>Теперь обратимся к случаю, когда один литеральный элемент будет включать другой:</p>
     <p><code>&lt;xsl:template match="a"&gt;</code></p>
     <p><code> &lt;A&gt;</code></p>
     <p><code>  &lt;B/&gt;</code></p>
     <p><code> &lt;/A&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>При выполнении этого шаблона процессор создаст элемент <code>A</code> и включит в него обработанное содержимое — то есть элемент <code>B</code>. Результатом этого шаблона будет XML-фрагмент:</p>
     <p><code>&lt;А&gt;</code></p>
     <p><code> &lt;В/&gt;</code></p>
     <p><code>&lt;/А&gt;</code></p>
     <p>Теперь попробуем включить в содержимое элемента инструкцию XSLT:</p>
     <p><code>&lt;xsl:template match="a"&gt;</code></p>
     <p><code> &lt;А&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="." /&gt;</code></p>
     <p><code> &lt;/A&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>При выполнении этого шаблона процессор создаст результирующий элемент а и включит в него результат выполнения его содержимого, то есть элемента <code>xsl:value-of</code>. Этот элемент создаст текстовый узел ей строковым значением текущего узла контекста преобразования. Например, если бы мы обрабатывали этим шаблоном элемент <code>а</code> вида</p>
     <p><code>&lt;a href="http://www.xsltdev.ru"&gt;Visit our site!&lt;/a&gt;</code></p>
     <p>результатом выполнения был бы следующий элемент:</p>
     <p><code>&lt;A&gt;Visit out site!&lt;/A&gt;</code></p>
     <p>При воссоздании литеральных элементов в результирующем документе, процессор копирует также все атрибуты и узлы пространств имен, которые ассоциируются с данным элементом. Например, результатом выполнения следующего шаблона:</p>
     <p><code>&lt;xsl:template match="a"&gt;</code></p>
     <p><code> &lt;A HREF="http://www.xsltdev.ru"</code></p>
     <p><code>  xmlns:xhtml="http://www.w3.org/1999/xhtml"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="." /&gt;</code></p>
     <p><code> &lt;/A&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>будет элемент вида:</p>
     <p><code>&lt;A HREF="http://www.xsltdev.ru"</code></p>
     <p><code> xmlns:xhtml="http://www.w3.org/1999/xhtml"&gt; </code></p>
     <p><code> Visit out site!</code></p>
     <p><code>&lt;/A&gt;</code></p>
     <p>Как можно заметить, процессор воссоздал не только сам элемент, но также его атрибуты и объявления пространств имен. В этом и есть смысл литеральных элементов — они копируются в выходящее дерево без изменений, хотя и здесь есть несколько исключений.</p>
     <p>&#9633; Процессор не будет копировать атрибуты, принадлежащие пространству имен XSLT.</p>
     <p>&#9633; Процессор не будет создавать узел пространства имен, соответствующий URI <code>http://www.w3.org/1999/XSL/Transform</code>, то есть URI пространства имен XSLT.</p>
     <p>&#9633; Процессор не будет создавать узлы пространств имен, префиксы которых исключаются атрибутами <code>exclude-result-prefixes</code> самого литерального элемента или элемента <code>xsl:stylesheet</code>.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 4.26</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:xhtml="http://www.w3.org/1999/XHTML"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;p</code></p>
     <p><code>   xmlns:xslt="http://www.w3.org/1999/XSL/Transform" </code></p>
     <p><code>   xslt:exclude-result-prefixes="xhtml"&gt;</code></p>
     <p><code>   &lt;xslt:value-of select="2 * 2"/&gt;</code></p>
     <p><code>  &lt;/p&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Обратим внимание на следующие особенности этого преобразования.</p>
     <p>&#9633; В нем объявлено пространство имен с префиксом <code>xhtml</code>.</p>
     <p>&#9633; Литеральный элемент <code>p</code> содержит объявление пространства имен с префиксом <code>xslt</code> и URI <code>http://www.w3.org/1999/XSL/Transform</code>.</p>
     <p>&#9633; Литеральный элемент <code>p</code> содержит атрибут, <code>xslt:exclude-result-prefixes</code>, принадлежащий пространству имен XSLT.</p>
     <p>Как ни странно, ни одно из этих объявлений не проникнет в выходящий документ, который будет иметь вид</p>
     <p><code>&lt;p&gt;4&lt;/p&gt;</code></p>
     <p>Попробуем объяснить такой результат. Атрибут <code>xslt:exclude-result-prefixes</code> не был включен в результирующий элемент <code>p</code>, поскольку принадлежал пространству имен XSLT (отметим еще раз, что принадлежность эта определяется не префиксом, а значением <code>URI</code>). Далее, объявление пространства имен</p>
     <p><code>xmlns:xslt="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p>которое содержалось в литеральном элементе <code>p</code>, не вошло в результат, потому что URI этого объявления совпадало с URI пространства имен XSLT. И, наконец, объявление пространства имен <code>xhtml</code> было исключено атрибутом <code>exclude-result-prefixes</code>.</p>
    </section>
    <section>
     <title>
      <p>Атрибуты языка XSLT в литеральных элементах</p>
     </title>
     <p>Мы упомянули о том, что литеральные элементы могут содержать атрибуты, принадлежащие пространству имен XSLT. В табл. 4.3 они перечислены вместе с краткими описаниями назначения.</p>
     <empty-line/>
     <p><emphasis><strong>Таблица 4.3</strong>. XSLT-атрибуты литеральных элементов</emphasis></p>
     <table>
      <tr>
       <th align="left">Атрибут</th>
       <th align="left">Назначение</th>
      </tr>
      <tr>
       <td align="left"><code>xsl:version</code></td>
       <td align="left">Указывает версию языка в случае использования упрощенного синтаксиса записи преобразований</td>
      </tr>
      <tr>
       <td align="left"><code>xsl:exclude-result-prefixes</code></td>
       <td align="left">Перечисляет префиксы пространств имен, которые должны быть исключены в данном элементе</td>
      </tr>
      <tr>
       <td align="left"><code>xsl:extension-element-prefixes</code></td>
       <td align="left">Перечисляет префиксы пространств имен, которые используются в элементах расширения</td>
      </tr>
      <tr>
       <td align="left"><code>xsl:use-attribute-sets</code></td>
       <td align="left">Перечисляет названия именованных наборов атрибутов, которые следует включить в данный элемент на выходе</td>
      </tr>
     </table>
    </section>
   </section>
   <section>
    <title>
     <p>Шаблоны значений атрибутов</p>
    </title>
    <p>Во многих элементах XSLT в качестве значений атрибутов могут быть указаны специальные шаблоны, называемые <emphasis>шаблонами значений атрибутов</emphasis> (attribute value templates). Замечательное свойство этих шаблонов заключается в том, что вместо простых строковых значений в атрибутах можно использовать результаты вычисления выражений. Выражения в шаблонах значений атрибутов должны быть заключены в фигурные скобки ("<code>{}</code>"). Если процессор встретит внутри значения атрибута выражение в таких скобках, он должен будет вычислить это выражение и заменить его в атрибуте вместе с фигурными скобками на результат вычисления в строковом виде.</p>
    <subtitle>Пример</subtitle>
    <p>Довольно часто в практике программирования на XSLT встречается потребность создавать элементы с именами, которые заранее не известны, но могут быть вычислены в ходе выполнения преобразования. Представим себе документ</p>
    <p><code>&lt;mark-up type="b"&gt;This text should be marked bold.&lt;/mark-up&gt;</code></p>
    <p>в котором атрибут <code>type</code> элемента <code>mark-up</code> указывает на тип элемента разметки, который должен быть использован для данного текстового фрагмента. Для того чтобы получить элемент вида</p>
    <p><code>&lt;b&gt;This text should be marked bold.&lt;/b&gt;</code></p>
    <p>можно использовать следующий шаблон:</p>
    <p><code>&lt;xsl:template match="mark-up"&gt;</code></p>
    <p><code> &lt;xsl:element name="{@type}"&gt;</code></p>
    <p><code>  &lt;xsl:value-of select="."/&gt;</code></p>
    <p><code> &lt;/xsl:element&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Таким образом, в качестве имени нового элемента, содержащего текст элемента <code>mark-up</code>, будет использовано значение атрибута <code>type</code>.</p>
    <p>В одном атрибуте можно использовать несколько выражений — каждое из них должно быть заключено в фигурные скобки.</p>
    <subtitle>Пример</subtitle>
    <p>Предположим, что мы хотим вывести ссылки на графические изображения в виде иконок. Мы задаем список файлов в виде XML-документа:</p>
    <p><code>&lt;images dir="/images"&gt;</code></p>
    <p><code> &lt;image filename="rose.jpg"/&gt;</code></p>
    <p><code> &lt;image filename="orchide.gif"/&gt;</code></p>
    <p><code> &lt;image filename="primul.gif"/&gt;</code></p>
    <p><code>&lt;/images&gt;</code></p>
    <p>Файлы хранятся в каталоге, указанном в атрибуте <code>dir</code> элемента <code>images</code>, а иконки имеют те же имена файлов, что и большие изображения, но с префиксом "<code>th_</code>". Для получения ссылок на изображения мы можем воспользоваться следующим преобразованием:</p>
    <p><code>&lt;xsl:template match="images/image"&gt;</code></p>
    <p><code> &lt;а href="{../@dir}/{@filename}"&gt;</code></p>
    <p><code>  &lt;img src="{../@dir}/th_{@filename}"/&gt; </code></p>
    <p><code> &lt;/a&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Результат будет получен в виде:</p>
    <p><code>&lt;а href="/images/rose.jpg"&gt;&lt;img src="/images/th_rose.jpg"/&gt;&lt;/a&gt;</code></p>
    <p><code>&lt;a href="/images/orchide.gif"&gt;&lt;img src="/images/th_orchide.gif"/&gt;&lt;/a&gt;</code></p>
    <p><code>&lt;a href="/images/primul. gif"&gt;&lt;img src="/images/th_primul.gif"/&gt;&lt;/a&gt;</code></p>
    <p>Для того чтобы использовать в значении атрибута левые и правые фигурные скобки в качестве простых символов, нужно удваивать их количество, то есть указывать "<code>{{</code>" вместо каждой левой и "<code>}}</code>" вместо каждой правой фигурной скобки соответственно.</p>
    <subtitle>Пример</subtitle>
    <p>Элемент, определенный как</p>
    <p><code>&lt;input name="login" type="text"</code></p>
    <p><code> value="{{{{{{Enter your login here}}}}}}"/&gt;</code></p>
    <p>будет преобразован в выходящем документе к виду</p>
    <p><code>&lt;input name="login" type="text" value="{{{Enter your login here}}}"/&gt;</code></p>
    <p>Фигурные скобки нельзя использовать рекурсивно для вычисления внутри выражений. К примеру, в качестве значения атрибута <code>name</code>, определенного как</p>
    <p><code>&lt;story name="{/h{1 + 2}/p}"/&gt;</code></p>
    <p>не будет использовано вычисленное значение выражения <code>/h3/p</code>. Вместо этого процессор выдаст ошибку.</p>
    <p>Фигурные скобки могут быть спокойно использованы внутри выражения в литералах — в этом случае они не будут задавать значений атрибутов.</p>
    <subtitle>Пример</subtitle>
    <p>Элемент, определенный как</p>
    <p><code>&lt;page numbers="{concat ('{', ' 1,2,3', '}') }"/&gt;</code></p>
    <p>будет преобразован к виду</p>
    <p><code>&lt;page numbers="{1,2,3}"/&gt;</code></p>
    <p>Шаблоны значений могут быть использованы далеко не везде. К примеру, не могут содержать шаблонов следующие типы атрибутов.</p>
    <p>&#9633; Атрибуты, значениями которых являются выражения.</p>
    <p>&#9633; Атрибуты, значениями которых являются паттерны.</p>
    <p>&#9633; Атрибуты элементов верхнего уровня.</p>
    <p>&#9633; Атрибуты пространств имен (<code>xmlns</code>).</p>
    <p>Шаблоны значений могут содержаться в любых атрибутах литеральных элементов, что уже несколько раз было продемонстрировано выше. Например, в литеральном элементе</p>
    <p><code>&lt;img src="{../@dir}/th_{@filename}"/&gt;</code></p>
    <p>атрибут <code>src</code> содержит ни что иное, как два шаблона значений.</p>
    <p>Что же касается атрибутов элементов XSLT, то как очевидно из табл. 4.4, лишь малая их часть может содержать шаблоны значений.</p>
    <empty-line/>
    <p><emphasis><strong>Таблица 4.4</strong>. Атрибуты элементов XSLT, которые могут содержать шаблоны значений</emphasis></p>
    <table>
     <tr>
      <th align="left">Элемент</th>
      <th align="left">Атрибуты</th>
      <th align="left">Описание</th>
     </tr>
     <tr>
      <td rowspan="2" align="left"><code>xsl:element</code></td>
      <td align="left"><code>name</code></td>
      <td align="left">Имя создаваемого элемента</td>
     </tr>
     <tr>
      <td align="left"><code>namespace</code></td>
      <td align="left">Пространство имен создаваемого элемента</td>
     </tr>
     <tr>
      <td rowspan="2" align="left"><code>xsl:attribute</code></td>
      <td align="left"><code>name</code></td>
      <td align="left">Имя создаваемого атрибута</td>
     </tr>
     <tr>
      <td align="left"><code>namespace</code></td>
      <td align="left">Пространство имен создаваемого атрибута</td>
     </tr>
     <tr>
      <td align="left"><code>xsl:processing-instruction</code></td>
      <td align="left"><code>name</code></td>
      <td align="left">Имя целевого приложения инструкции по обработке</td>
     </tr>
     <tr>
      <td rowspan="5" align="left"><code>xsl:number</code></td>
      <td align="left"><code>format</code></td>
      <td align="left">Формат номера</td>
     </tr>
     <tr>
      <td align="left"><code>lang</code></td>
      <td align="left">Языковой контекст номера</td>
     </tr>
     <tr>
      <td align="left"><code>letter-value</code></td>
      <td align="left">Традиционная или алфавитная буквенная нумерация</td>
     </tr>
     <tr>
      <td align="left"><code>grouping-separator</code></td>
      <td align="left">Символ-разделитель групп цифр номера</td>
     </tr>
     <tr>
      <td align="left"><code>grouping-size</code></td>
      <td align="left">Размер группы цифр номера</td>
     </tr>
     <tr>
      <td rowspan="4" align="left"><code>xsl:sort</code></td>
      <td align="left"><code>lang</code></td>
      <td align="left">Языковой контекст сортировки</td>
     </tr>
     <tr>
      <td align="left"><code>data-type</code></td>
      <td align="left">Тип данных сортировки</td>
     </tr>
     <tr>
      <td align="left"><code>order</code></td>
      <td align="left">Порядок сортировки</td>
     </tr>
     <tr>
      <td align="left"><code>case-order</code></td>
      <td align="left">Старшинство прописных и строчных символов при сортировке</td>
     </tr>
    </table>
    <p>Таким образом, перечень параметров, которые могут изменяться динамически (иными словами — вычисляться непосредственно во время выполнения шаблона) не так велик. В частности, стандартными способами в XSLT невозможно выполнить следующее.</p>
    <p>&#9633; Вызвать именованный шаблон динамически: атрибут name элемента <code>xsl:call-template</code> должен быть задан заранее и не может содержать шаблон значения.</p>
    <p>&#9633; Динамически изменить режим применения шаблонов (атрибут <code>mode</code> элемента <code>xsl:apply-templates</code>).</p>
    <p>&#9633; Вычислить элементами <code>xsl:copy-of</code> и <code>xsl:value-of</code> выражение заранее неизвестного вида.</p>
    <p>&#9633; Давать переменным и параметрам имена, вычисляемые во время выполнения преобразования.</p>
    <p>Список ограничений подобного рода можно продолжать еще долго, однако общим свойством этих ограничений является то, что шаблоны значений атрибутов могут использоваться при формировании выходящего элемента, но они не оказывают никакого влияния на сам ход выполнения преобразования.</p>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 5</p>
    <p>Шаблонные правила</p>
   </title>
   <section>
    <title>
     <p>Преобразование как набор правил</p>
    </title>
    <p>В предыдущих главах мы уже упомянули о том, что преобразование в XSLT состоит не из последовательности действий, а из набора шаблонных правил, каждое из которых обрабатывает свою часть XML-документа. Эта глава целиком посвящена вопросам создания и использования шаблонных правил, однако, прежде чем мы приступим к их рассмотрению, хотелось бы пояснить, почему же все-таки правила, а не действия.</p>
    <p>Дело в том, что структуры XML-документов (даже принадлежащих одной логической схеме) могут быть настолько разнообразны, что создание императивной программы, которая выполняла бы их преобразование, является очень сложной задачей. Возможность включения или исключения тех или иных элементов, наличие или отсутствие атрибутов, да и неопределенность самой структуры документа в конечном итоге приводят к экспоненциальному увеличению количества операторов ветвления, циклов и так далее. Программа становится большой, сложной и малопонятной.</p>
    <p>В то же время само преобразование может быть очень простым. Не понимая, что нужно сделать, чтобы преобразовать документ <emphasis>целиком</emphasis>, тем не менее, можно хорошо понимать, как следует обработать каждую из его частей.</p>
    <p>Вследствие этого, язык XSLT был создан декларативным: вместо того, чтобы определять последовательность действий, программа в XSLT <emphasis>декларирует</emphasis> правила преобразования. Каждое из этих правил может в свою очередь вызывать другие правила, таким образом обеспечивая обработку документов сколь угодно сложной структуры.</p>
   </section>
   <section>
    <title>
     <p>Определение шаблонного правила</p>
    </title>
    <section>
     <title>
      <p>Элемент<emphasis> xsl:template</emphasis></p>
     </title>
     <p>Синтаксис этого элемента приведен ниже:</p>
     <p><code>&lt;xsl:template</code></p>
     <p><code> match="<emphasis>пaттерн</emphasis>"</code></p>
     <p><code> name="<emphasis>имя</emphasis>"</code></p>
     <p><code> priority="<emphasis>число</emphasis>"</code></p>
     <p><code> mode="<emphasis>имя</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: несколько элементов xsl:param, тело шаблона --&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Элемент верхнего уровня <code>xsl:template</code> определяет в преобразовании <emphasis>шаблонное правило</emphasis>, или просто <emphasis>шаблон</emphasis>. Элемент <code>xsl:template</code> имеет всего четыре атрибута, смысл которых мы кратко опишем ниже.</p>
     <p>Атрибут <code>match</code> задает паттерн — образец узлов дерева, для преобразования которых следует применять этот шаблон.</p>
     <subtitle>Пример</subtitle>
     <p><code>&lt;xsl:template match="bold"&gt;</code></p>
     <p><code> &lt;b&gt;&lt;xsl:value-of select="."/&gt;&lt;/b&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>В этом правиле атрибут <code>match</code> говорит о том, что оно должно использоваться для обработки элементов <code>bold</code> — в данном случае они будут заменяться на элементы <code>b</code>. Шаблоны, в которых определен атрибут <code>match</code>, вызываются при помощи инструкции <code>xsl:apply-templates</code>.</p>
     <p>Шаблон также может иметь имя, определяемое атрибутом <code>name</code>. Шаблон, в котором задано имя, называется <emphasis>именованным</emphasis> шаблоном. Именованные шаблоны могут вызываться вне зависимости от текущего контекста, и даже вести себя как функции — принимать на вход параметры и возвращать некоторые значения.</p>
     <subtitle>Пример</subtitle>
     <p><code>&lt;xsl:template name="bold"&gt;</code></p>
     <p><code> &lt;b&gt;&lt;xsl:value-of select="."/&gt;&lt;/b&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>В отличие от предыдущего примера, это правило не будет обрабатывать какие-либо определенные узлы. Вызвать его можно будет только по имени посредством элемента <code>xsl:call-template</code>.</p>
     <p>При определении шаблона нужно обязательно указать хотя бы один из атрибутов <code>match</code> или <code>name</code>, причем эти атрибуты могут присутствовать в <code>xsl:template</code> одновременно.</p>
     <p>Атрибут <code>mode</code> определяет <emphasis>режим</emphasis> данного шаблонного правила. Режимы позволяют задавать различные преобразования для одних и тех же частей документа (о них мы поговорим позже).</p>
     <p>Атрибут <code>priority</code> используется для определения значения, которое называется <emphasis>приоритетом</emphasis> шаблонного правила. Это значение используется для разрешения конфликтов шаблонов в случае, когда один узел может быть обработан различными правилами.</p>
     <p>Атрибуты шаблонного правила не влияют на выполнение его содержимого. Они используются элементами <code>xsl:apply-templates</code> и <code>xsl:call-template</code> при выборе шаблонов. Правила, которые были импортированы в преобразование, вызываются элементом <code>xsl:apply-imports</code>.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Вызов шаблонных правил</p>
    </title>
    <section>
     <p>Рассмотрим следующий простой пример.</p>
     <subtitle>Листинг 5.1. Входящий документ</subtitle>
     <p><code>&lt;para&gt;&lt;bold&gt;text&lt;/bold&gt;&lt;/para&gt;</code></p>
     <p>Попробуем написать пару шаблонов, которые будут изменять имена элементов <code>para</code> и <code>bold</code> на <code>p </code>и <code>b</code> соответственно. Сначала напишем преобразование для <code>bold</code>:</p>
     <p><code>&lt;xsl:template match="bold"&gt;</code></p>
     <p><code>&lt;b&gt;&lt;xsl:value-of select="."/&gt;&lt;/b&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>В этом правиле создается элемент <code>b</code>, в который включается текстовое значение текущего узла (то есть, обрабатываемого элемента <code>bold</code>). Применив это преобразование к входящему документу, мы получим следующий результат:</p>
     <p><code>&lt;b&gt;text&lt;/b&gt;</code></p>
     <p>Как говорят математики, что и требовалось. Попробуем проделать тот же трюк с элементом <code>para</code> и создадим преобразование, включающее оба правила.</p>
     <subtitle>Листинг 5.2. Преобразование с para и bold — версия 1</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="bold"&gt;</code></p>
     <p><code>  &lt;b&gt;&lt;xsl: value-of select="."/&gt;&lt;/b&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="para"&gt;</code></p>
     <p><code>  &lt;p&gt;&lt;xsl:value-of select="."/&gt;&lt;/p&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>На этот раз вместо ожидаемого результата вида <code>&lt;p&gt;&lt;b&gt;text&lt;/b&gt;&lt;/p&gt;</code> мы получим</p>
     <p><code>&lt;p&gt;</code></p>
     <p><code> text</code></p>
     <p><code>&lt;/p&gt;</code></p>
     <p>Попробуем ответить на три вопроса: кто виноват, что делать и куда делся элемент <code>b</code>.</p>
     <p>Для ответа на вопрос, куда делся элемент <code>b</code>, пожалуй, необходимо будет пояснить, что же именно происходит при преобразовании этого документа. Последовательно рассмотрим стадии этого процесса.</p>
     <p>&#9633; Процессор начинает обработку с корневого узла дерева. Он выбирает шаблон, соответствующий этому узлу. В нашем преобразовании такого шаблона нет, значит, процессор применит к корню шаблонное правило, <emphasis>определенное по умолчанию</emphasis> (<emphasis>см. раздел "Встроенные шаблоны" данной главы</emphasis>).</p>
     <p>&#9633; По умолчанию шаблонное правило корневого узла обрабатывает все дочерние узлы. В нашем документе единственным дочерним узлом корня будет элемент <code>para</code>.</p>
     <p>&#9633; Для элемента <code>para</code> в нашем преобразовании задан шаблон, который и будет применен к этому элементу.</p>
     <p>&#9633; В соответствии с этим шаблоном, процессор создаст элемент <code>p</code> и включит в него текстовое значение выражения "<code>.</code>". Как мы знаем, выражение "<code>.</code>" является сокращенной формой выражения "<code>self::node()</code>", которое возвратит текущий узел. Таким образом, элемент <code>&lt;xsl:value-of select="."/&gt;</code> вычислит и возвратит строковое значение текущего узла, то есть узла <code>para</code>. Строковым значением элемента является конкатенация всех его текстовых потомков. Единственным текстовым потомком нашего para является текстовый узел со значением "<code>text</code>" и вот он-то и выводится между открывающим и закрывающим тегами созданного элемента <code>p</code>.</p>
     <p>Таким образом, элемент <code>b</code> "потерялся" потому, что шаблон для <code>bold</code> просто не вызывался. Виноваты, естественно, мы сами, поскольку не включили его вызов. Осталось только разобраться, как можно вызвать шаблон для обработки элемента <code>bold</code>.</p>
     <p>Ответ на этот вопрос предельно прост — для вызова неименованных шаблонных правил В XSLT используется элемент <code>xsl:apply-templates</code>.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:apply-templates</emphasis></p>
     </title>
     <p>Синтаксис этого элемента выглядит следующим образом:</p>
     <p><code>&lt;xsl:apply-templates</code></p>
     <p><code> select="<emphasis>выражение</emphasis>"</code></p>
     <p><code> mode="<emphasis>режим</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: несколько элементов xsl:sort или xsl:with-param --&gt;</code></p>
     <p><code>&lt;/xsl:apply-templates&gt;</code></p>
     <p>Элемент <code>xsl:apply-templates</code> применяет шаблонные правила к узлам, которые возвращаются выражением, указанным в атрибуте <code>select</code>. Если атрибут <code>select</code> опущен, то <code>xsl:apply-templates</code> применяет шаблонные правила ко всем дочерним узлам текущего узла, то есть</p>
     <p><code>&lt;xsl:apply-templates/&gt;</code></p>
     <p>равносильно</p>
     <p><code>&lt;xsl:apply-templates select="child::node()"/&gt;</code></p>
     <p>Атрибут <code>mode</code> используется для указания режима, в котором должны применяться шаблоны — мы поговорим о различных режимах чуть позже.</p>
     <p>Прежде чем двигаться дальше, опишем более подробно, что означает "применить шаблон" (англ. apply — применить, template — шаблон). Применение шаблонов — это составная часть обработки документа, которая может быть описана следующим порядком действий.</p>
     <p>&#9633; На первом шаге процессор вычисляет выражение, указанное в атрибуте <code>select</code>. Его значением должно быть множество узлов. Полученное множество узлов упорядочивается и становится текущим списком узлов контекста преобразования.</p>
     <p>&#9633; Для каждого из узлов этого списка процессор находит наиболее подходящий шаблон для обработки. Процессор делает этот узел текущим и затем выполняет в измененном контексте выбранное шаблонное правило.</p>
     <p>&#9633; Дерево, которое является результатом выполнения шаблона, добавляется в выходящее дерево.</p>
     <p>Применительно к нашему примеру с <code>para</code> и <code>bold</code>, мы можем изменить преобразование так, что в создаваемый элемент p будет включаться не текстовое значение элемента para, а результат обработки его дочерних узлов.</p>
     <subtitle>Листинг 5.3. Преобразование с para и bold — версия 2</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="bold"&gt;</code></p>
     <p><code>  &lt;b&gt;&lt;xsl:value-of select="."/&gt;&lt;/b&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="para"&gt;</code></p>
     <p><code>  &lt;p&gt;&lt;xsl:apply-templates&lt;/p&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Проследим за процессом выполнения этого преобразования.</p>
     <p>&#9633; Обработка начинается с корневого узла дерева. Для него нет заданных шаблонных правил, значит, применено будет правило по умолчанию — обработать все дочерние узлы. Множество дочерних узлов корня содержит единственный элемент <code>para</code>, значит, текущий список узлов контекста будет состоять из одного узла. Для него в преобразовании определен шаблон, который и будет выполнен процессором.</p>
     <p>&#9633; Шаблон, соответствующий элементу <code>para</code>, создает элемент <code>p</code>, содержимым которого будет результат выполнения инструкции <code>xsl:apply-templates</code>, то есть результат применения шаблонов к дочерним узлам текущего узла — элемента <code>para</code>.</p>
     <p>&#9633; Единственным дочерним узлом элемента <code>para</code> является элемент <code>bold</code>. Процессор изменит контекст так, что текущий список узлов будет содержать только элемент <code>bold</code> и выполнит соответствующее шаблонное правило, которое создаст элемент <code>b</code> и включит в него узел, вычисленный инструкцией <code>&lt;xsl:value-of select="."/&gt;</code>, то есть текстовый узел со строковым значением текущего узла, элемента <code>bold</code>.</p>
     <p>Три шага этого преобразования продемонстрированы на рис. 5.1.</p>
     <image l:href="#img_44.png"/>
     <p><strong>Рис. 5.1</strong>. Процесс преобразования</p>
     <p>Здесь слева показан текущий список узлов, посередине — дерево документа с выделенным пунктиром текущим узлом, справа — генерируемое выходящее дерево.</p>
     <p>Результатом этого преобразования будет документ:</p>
     <p><code>&lt;p&gt;&lt;b&gt;text&lt;/b&gt;&lt;/p&gt;</code></p>
     <p>Рассмотрим чуть более сложное преобразование документа:</p>
     <p><code>&lt;para&gt;</code></p>
     <p><code> &lt;bold&gt;text1&lt;/bold&gt;</code></p>
     <p><code> &lt;para&gt;</code></p>
     <p><code>  &lt;bold&gt;text2&lt;/bold&gt;</code></p>
     <p><code> &lt;/para&gt;</code></p>
     <p><code>&lt;/para&gt;</code></p>
     <p>Порядок действий в этом случае будет приблизительно следующим.</p>
     <p>&#9633; Первым обрабатывается корневой узел. Процессор применяет шаблоны к дочерним узлам (вернее к одному дочернему узлу — элементу <code>para</code>).</p>
     <p>&#9633; Шаблон, обрабатывающий элемент para, создает в выходящем документе элемент p и применяет шаблоны к своим дочерним узлам — на этот раз их два, <code>bold</code> и <code>para</code>.</p>
     <p>&#9633; Шаблон, обрабатывающий элемент <code>bold</code>, создает в выходящем документе элемент <code>b</code> и текстовый узел со значением "<code>text1</code>".</p>
     <p>&#9633; Шаблон, обрабатывающий элемент <code>para</code>, создает в выходящем дереве узел <code>p</code> и применяет шаблоны к дочерним узлам.</p>
     <p>&#9633; Единственным дочерним узлом элемента <code>para</code> является элемент <code>bold</code>.</p>
     <p>&#9633; Шаблон, обрабатывающий этот элемент <code>bold</code>, создает в выходящем документе элемент <code>b</code> и текстовый узел со значением "<code>text2</code>".</p>
     <p>Процесс преобразования показан на рис. 5.2.</p>
     <image l:href="#img_45.png"/>
     <p><strong>Рис. 5.2</strong>. Процесс преобразования</p>
     <p>Результатом этого преобразования будет документ:</p>
     <p><code>&lt;p&gt;</code></p>
     <p><code> &lt;b&gt;text1&lt;/b&gt;</code></p>
     <p><code> &lt;p&gt;</code></p>
     <p><code>  &lt;b&gt;text2&lt;/b&gt;</code></p>
     <p><code> &lt;/p&gt;</code></p>
     <p><code>&lt;/p&gt;</code></p>
     <p>Атрибут <code>select</code> элемента <code>xsl:apply-templates</code> позволяет выбирать, к каким именно узлам будет применяться этот шаблон. Значение <code>select</code> — это XPath-выражение, которое должно возвращать множество узлов. В случае, если атрибут <code>select</code> указан, шаблоны будут поочередно применяться к каждому из узлов выбранного множества.</p>
     <subtitle>Пример</subtitle>
     <p>Если при обработке элементов para мы хотим обрабатывать только дочерние элементы <code>bold</code> и никакие другие, шаблон обработки элементов <code>para</code> будет записан следующим образом:</p>
     <p><code>&lt;xsl:template match="para"&gt;</code></p>
     <p><code> &lt;p&gt;&lt;xsl:apply-templates select="bold"/&gt;&lt;/p&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Результатом обработки документа</p>
     <p><code>&lt;para&gt;</code></p>
     <p><code> &lt;bold&gt;text1&lt;/bold&gt;</code></p>
     <p><code> &lt;para&gt;</code></p>
     <p><code>  &lt;bold&gt;text2&lt;/bold&gt;</code></p>
     <p><code> &lt;/para&gt;</code></p>
     <p><code>&lt;/para&gt;</code></p>
     <p>будет теперь</p>
     <p><code>&lt;p&gt;</code></p>
     <p><code> &lt;b&gt;text1&lt;/b&gt;</code></p>
     <p><code>&lt;/p&gt;</code></p>
     <p>Элемент <code>para</code>, который во входящем документе включен в другой элемент <code>para</code>, не будет обработан по той простой причине, что он не вошел во множество, выбранное XPath-выражением "<code>bold</code>". В то же время, если мы запишем</p>
     <p><code>&lt;xsl:template match="para"&gt;</code></p>
     <p><code> &lt;p&gt;&lt;xsl:apply-templates select="bold|para"/&gt;&lt;/p&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>то результат будет таким же, как и прежде:</p>
     <p><code>&lt;p&gt;</code></p>
     <p><code> &lt;b&gt;text1&lt;/b&gt;</code></p>
     <p><code> &lt;p&gt;</code></p>
     <p><code>  &lt;b&gt;text2&lt;/b&gt;</code></p>
     <p><code> &lt;/p&gt;</code></p>
     <p><code>&lt;/p&gt;</code></p>
     <p>Следует хорошо понимать разницу между атрибутом <code>select</code> элемента <code>xsl:apply-templates</code> и атрибутом <code>match</code> элемента <code>xsl:template</code>. Атрибут <code>match</code> содержит не XPath-выражение, а паттерн XSLT; в отличие от атрибута select в <code>xsl:apply-templates</code> он не выбирает никакого множества узлов, он используется только для того, чтобы проверить, может ли данный узел обрабатываться этим шаблоном или нет.</p>
     <p>Атрибут <code>select</code> элемента <code>xsl:apply-templates</code> наоборот, содержит не паттерн, а выражение, единственным требованием к которому является то, что оно должно возвращать множество узлов. Например, некорректным будет определение вида</p>
     <p><code>&lt;xsl:apply-templates select="para+1"/&gt;</code></p>
     <p>поскольку выражение <code>para+1</code> не может возвратить множество узлов.</p>
     <p>Кроме этого требования, никаких других ограничений на выражения в этом атрибуте нет. В нем можно использовать переменные, содержащие множества узлов, функции, возвращающие множества узлов (например, такие, как <code>id</code> или <code>key</code>), выражения с операциями над множествами (именно таким выражением — выражением объединения было выражение <code>bold|para</code>), пути выборки, фильтрующие выражения, в общем, любые выражения, которые только могут возвращать множества. Например, для того, чтобы обработать содержимое произвольного внешнего XML-документа, в атрибуте <code>select</code> элемента <code>xsl:apply-template</code> следует использовать функцию <code>document</code>.</p>
     <subtitle>Пример</subtitle>
     <p>Объявление вида</p>
     <p><code>&lt;xsl:apply-templates select="document('a.xml')//para"/&gt;</code></p>
     <p>применит шаблоны ко всем элементам <code>para</code> документа <code>a.xml</code>.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Режимы</p>
    </title>
    <p>Очень часто в преобразованиях требуется обрабатывать одни и те же узлы, но <emphasis>разными способами</emphasis>. Типичным примером такого рода задачи является генерация оглавления документа вместе с преобразованием его содержимого. Очевидно, что просто шаблонами здесь не обойтись, и чтобы не получить другой результат, нужно каким-то образом указывать, что по-другому должна вестись и обработка.</p>
    <p>Эта проблема решается в XSLT просто и элегантно. Атрибут <code>mode</code> элемента xsl:template задает <emphasis>режим</emphasis> этого шаблона. Точно такой же атрибут есть у элемента <code>xsl:apply-templates</code>: в этом элементе он устанавливает <emphasis>режим обработки</emphasis>. При выполнении <code>xsl:apply-templates</code> процессор будет применять только те шаблоны преобразования, режим которых совпадает с выбранным режимом обработки.</p>
    <subtitle>Пример</subtitle>
    <p>В качестве примера приведем преобразование, которое добавляет в XHTML-файл перечень текстовых ссылок, обнаруженных в этом документе. Грубо говоря, XHTML — это XML-версия языка HTML, а значит XSLT вполне подходит для обработки XHTML-документов.</p>
    <p>URI пространства имен языка XHTML — <code>"http://www.w3.org/1999/xhtml"</code>; этому языку мы назначим префикс "<code>xhtml</code>" и, кроме того, сделаем это пространство пространством имен по умолчанию:</p>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
    <p><code> xmlns:xhtml="http://www.w3.org/1999/xhtml"</code></p>
    <p><code> xmlns="http://www.w3.org/1999/xhtml"&gt;</code></p>
    <p><code> ...</code></p>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>Начнем с шаблона, который будет выводить каждую из ссылок. В каждой ссылке мы будем выводить только ее атрибут <code>href</code> и текст, который она содержит. Для удобочитаемости мы также добавим элемент <code>br</code> и символ переноса строки <code>&amp;#xA;</code>.</p>
    <p><code>&lt;xsl:template match="xhtml:a"&gt;</code></p>
    <p><code> &lt;xsl:copy&gt;</code></p>
    <p><code>  &lt;xsl:copy-of select="@href|text()"/&gt;</code></p>
    <p><code> &lt;/xsl:copy&gt;</code></p>
    <p><code> &lt;br/&gt;</code></p>
    <p><code> &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Мы чуть позже познакомимся с элементами <code>xsl:copy</code>, <code>xsl:copy-of</code> и <code>xsl:text</code>, пока же скажем, что</p>
    <p><code>&lt;xsl:copy&gt;</code></p>
    <p><code> &lt;xsl:copy-of select="@href|text()"/&gt;</code></p>
    <p><code>&lt;/xsl:copy&gt;</code></p>
    <p>копирует в выходящий документ текущий узел, его атрибут <code>href</code> (<code>@href</code>) и дочерние текстовые узлы (<code>text()</code>).</p>
    <p>Элемент <code>&lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code> выводит символ переноса строки. Элемент <code>&lt;br/&gt;</code> является литеральным элементом результата — он никак не обрабатывается, а просто выводится в результирующий документ.</p>
    <p>Следующее преобразование называется идентичным преобразованием — оно просто копирует все узлы один в один:</p>
    <p><code>&lt;xsl:template match="@*|node()"&gt;</code></p>
    <p><code> &lt;xsl:copy&gt;</code></p>
    <p><code>  &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
    <p><code> &lt;/xsl:copy&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>И, наконец, нам понадобится преобразование для элемента <code>body</code> — в него мы включим копию содержимого, а также ссылки, отсортированные в алфавитном порядке:</p>
    <p><code>&lt;xsl:template match="xhtml:body"&gt;</code></p>
    <p><code> &lt;xsl:copy&gt;</code></p>
    <p><code>  &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
    <p><code>  &lt;h1&gt;Links found on this page:&lt;h1&gt;</code></p>
    <p><code>  &lt;xsl:apply-templates</code></p>
    <p><code>   select=".//xhtml:a[@href and not(xhtml:*)]"&gt;</code></p>
    <p><code>  &lt;xsl:sort select="."/&gt;</code></p>
    <p><code> &lt;/xsl:apply-templates&gt;</code></p>
    <p><code> &lt;/xsl:copy&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Если мы попытаемся выполнить преобразование, состоящее из этих шаблонов, мы обнаружим, что в тексте самого документа ссылки испортились — там <emphasis>тоже</emphasis> добавились элементы <code>br</code> и переносы строк. Это произошло потому, что шаблон для обработки ссылок имеет больший приоритет, чем шаблон, копирующий содержимое документа.</p>
    <p>Для исправления этой ошибки мы выделим шаблон обработки ссылок в отдельный режим <code>links</code>:</p>
    <p><code>&lt;xsl:template match="xhtml:a" mode="links"&gt;</code></p>
    <p><code> ...</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Теперь это правило не будет применяться к ссылкам во время копирования содержимого документа, потому что при выполнении инструкции</p>
    <p><code>&lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
    <p>режим будет пустым, значит шаблон для <code>xhtml:а</code> вызываться не будет. Для того чтобы применить его при помощи <code>xsl:apply-templates</code>, мы добавим в этот элемент атрибут <code>mode</code>:</p>
    <p><code>&lt;xsl:apply-templates</code></p>
    <p><code> select=".//xhtml:a[@href and not(xhtml:*)]"</code></p>
    <p><code><strong> mode="links"</strong>&gt;</code></p>
    <p><code> &lt;xsl:sort select="."/&gt;</code></p>
    <p><code>&lt;/xsl:apply-templates&gt;</code></p>
    <p>Разберем более подробно это определение. Данная инструкция будет применять шаблоны с режимом <code>links</code> к узлам, возвращаемым выражением <code>".//xhtml:a[@href and not (xhtml:*)]"</code>, отсортированным в алфавитном порядке своих строковых значений. Выражение <code>".//xhtml:a[@href and not(xhtml:*)]"</code> возвращает всех потомков текущего узла (путь выборки "<code>.//</code>"), которые принадлежат пространству имен <code>xhtml</code>, являются элементами с именами <code>а</code>, (тест имени "<code>xhtml:a</code>"), при этом имеют атрибут <code>href</code> и не включают в себя другие элементы (предикат "<code>[@href and not (xhtml:*)]</code>").</p>
    <p>Преобразование целиком будет иметь следующий вид.</p>
    <subtitle>Листинг 5.4. Преобразование, добавляющее перечень ссылок</subtitle>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
    <p><code> xmlns:xhtml="http://www.w3.org/1999/xhtml"</code></p>
    <p><code> xmlns="http://www.w3.org/1999/xhtml"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="xhtml:body"&gt;</code></p>
    <p><code>  &lt;xsl:copy&gt;</code></p>
    <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
    <p><code>   &lt;h1&gt;Links found on this page:&lt;/h1&gt;</code></p>
    <p><code>   &lt;xsl:apply-templates select=".//xhtml:a[@href and not (xhtml:*)]"&gt;</code></p>
    <p><code>    &lt;xsl:sort select="."/&gt;</code></p>
    <p><code>   &lt;/xsl:apply-templates&gt;</code></p>
    <p><code>  &lt;/xsl:copy&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="@*|node()"&gt;</code></p>
    <p><code>  &lt;xsl:copy&gt;</code></p>
    <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
    <p><code>  &lt;/xsl:copy&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="xhtml:a"&gt;</code></p>
    <p><code>  &lt;xsl:copy&gt;</code></p>
    <p><code>   &lt;xsl:copy-of select="@href|text()"/&gt;</code></p>
    <p><code>  &lt;/xsl:copy&gt;</code></p>
    <p><code>  &lt;br/&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>Применив это преобразование, например, к главной странице Консорциума W3 (<strong>http://www.w3.org</strong>), мы получим ее точный дубликат, в конце которого будет приведен перечень всех найденных текстовых ссылок. Выходящий документ будет заканчиваться фрагментом вида:</p>
    <p><code>&lt;h1&gt;Links found on this page:&lt;/h1&gt;</code></p>
    <p><code>&lt;a href="Consortium/"&gt;About W3C&lt;/a&gt;&lt;br/&gt;</code></p>
    <p><code>&lt;a href="WAI/"&gt;Accessibility&lt;/a&gt;&lt;br/&gt;</code></p>
    <p><code>&lt;a href="Consortium/Activities"&gt;Activities&lt;/a&gt;&lt;br/&gt;</code></p>
    <p>и так далее.</p>
    <p>Заметим, что того же эффекта можно было добиться другими способами, например, при помощи именованных шаблонов или элемента <code>xsl:for-each</code>, однако применение режимов, пожалуй, является наиболее гибкой техникой.</p>
    <p>Досадным ограничением режимов является то, что режим нельзя выбирать динамически. Атрибут <code>mode</code> обязан иметь фиксированное значение, то есть вызов вида:</p>
    <p><code>&lt;xsl:apply-templates mode="{$mode}"/&gt;</code></p>
    <p>будет некорректным. Особо серьезных практических противопоказаний для динамических режимов нет, будем надеяться, что в следующих версиях XSLT они появятся.</p>
   </section>
   <section>
    <title>
     <p>Именованные шаблоны</p>
    </title>
    <section>
     <p>Вместо того чтобы при помощи атрибута <code>match</code> указывать, какая часть входящего документа должна преобразовываться данным шаблоном, ему можно присвоить имя и вызывать в любой момент вне зависимости от контекста преобразования. Такие шаблоны очень схожи по принципу с процедурами в императивных языках программирования — они позволяют выносить часто используемые части преобразований, передавать им параметры и вызывать вне зависимости от того, что именно обрабатывается в данный момент.</p>
     <p>Имя шаблонному правилу присваивается атрибутом name элемента <code>xsl:template</code>. После этого шаблону более необязательно иметь атрибут <code>match</code>, теперь он может быть вызван просто по имени. Два шаблона с одним порядком импорта не могут иметь одинаковых имен. Если же одинаковые имена имеют шаблоны различного порядка импорта, шаблоны старшего порядка переопределяют младшие шаблоны</p>
     <subtitle>Пример</subtitle>
     <p>При генерации HTML-страниц часто встречающейся задачей является создание элемента <code>head</code>. Элемент <code>head</code>, как правило, содержит несколько элементов <code>meta</code>, предоставляющих метаинформацию, элемент <code>title</code>, который определяет название страницы и элемент <code>link</code>, который связывает данную страницу с другими документами, например, с каскадными таблицами стилей (CSS).</p>
     <p>Для того чтобы упростить процедуру генерации <code>head</code>, мы можем вынести ее в отдельный именованный шаблон.</p>
     <subtitle>Листинг 5.5. Именованный шаблон для генерации элемента head</subtitle>
     <p><code>&lt;xsl:template name="head"&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;meta name="keywords" content="XSLT, XPath, XML"/&gt;</code></p>
     <p><code>  &lt;meta name="description"</code></p>
     <p><code>   content="This site is dedicated to XSLT and Xpath."/&gt;</code></p>
     <p><code>  &lt;title&gt;XSLTdev.ru - XSLT developer resource&lt;/title&gt;</code></p>
     <p><code>  &lt;link rel="stylesheet" type="text/css" href="style/main.css"/&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Думается, этот шаблон не требует пояснений — он просто создает в входящем документе несколько элементов. Непонятным пока остается другое — как вызывать именованные шаблоны? Элемент <code>xsl:apply-templates</code> явно не подходит, поскольку именованные шаблоны не обязаны иметь атрибут <code>match</code>. Их выполнение производится элементом <code>xsl:call-template</code>.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:call-template</emphasis></p>
     </title>
     <p>Приведем синтаксис этого элемента:</p>
     <p><code>&lt;xsl:call-template</code></p>
     <p><code> <strong>name</strong>="<emphasis>имя</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: несколько элементов xsl:with-param --&gt;</code></p>
     <p><code>&lt;/xsl:call-template&gt;</code></p>
     <p>Обязательный атрибут name указывает имя шаблона, который вызывается этой инструкцией. Например, шаблон с именем "<code>head</code>", приведенный выше, может быть вызван следующим образом:</p>
     <p><code>&lt;xsl:call-template name="head"/&gt;</code></p>
     <p>Атрибут <code>name</code> при вызове обязан иметь фиксированное значение — точно так же, как и в случае с <code>mode</code> и <code>xsl:apply-templates</code>, динамика здесь не разрешена.</p>
     <p>При вызове <code>xsl:call-template</code> не изменяет контекста преобразования. Фактически, вызов именованного шаблона эквивалентен замене в тексте преобразования элемента <code>xsl:call-template</code> на тело вызываемого шаблона.</p>
     <p>Приведем пример.</p>
     <subtitle>Листинг 5.6. Входящий документ</subtitle>
     <p><code>&lt;content&gt;</code></p>
     <p><code> Just a few words...</code></p>
     <p><code>&lt;/content&gt;</code></p>
     <subtitle>Листинг 5.7. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;html&gt;</code></p>
     <p><code>  &lt;xsl:call-template name="head"/&gt;</code></p>
     <p><code>  &lt;body&gt;&lt;xsl:copy-of select="content/node()"/&gt;&lt;/body&gt;</code></p>
     <p><code> &lt;/html&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:template name="head"&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;meta name="keywords" content="XSLT, XPath, XML"/&gt;</code></p>
     <p><code>  &lt;meta name="description"</code></p>
     <p><code>   content="This site is dedicated to XSLT and Xpath."/&gt;</code></p>
     <p><code>  &lt;title&gt;XSLTdev.ru - XSLT developer resource&lt;/title&gt;</code></p>
     <p><code>  &lt;link rel="stylesheet" type="text/css" href="style/main.css"/&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 5.8. Выходящий документ</subtitle>
     <p><code>&lt;html&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;meta name="keywords" content="XSLT, XPath, XML"&gt;</code></p>
     <p><code>  &lt;meta name="description"</code></p>
     <p><code>   content="This site is dedicated to XSLT and Xpath."&gt;</code></p>
     <p><code>  &lt;title&gt;XSLTdev.ru - XSLT developer resource&lt;/title&gt;</code></p>
     <p><code>  &lt;link rel="stylesheet" type="text/css" href="style/main.css"&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code> &lt;body&gt;Just a few words...&lt;/body&gt;</code></p>
     <p><code>&lt;/html&gt;</code></p>
     <cite>
      <subtitle>Примечание</subtitle>
      <p>Несколько более эффективным способом использования в документе статических частей (как содержимое элемента <code>head</code> в приведенном примере) является хранение этих частей во внешних документах и вставка их в выходящий документ при помощи элемента <code>xsl:copy-of</code> и функции <code>document</code>.</p>
     </cite>
     <p>В этом примере шаблон, обрабатывающий корневой элемент, фактически эквивалентен шаблону вида:</p>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;html&gt;</code></p>
     <p><code>  &lt;head&gt;</code></p>
     <p><code>   &lt;meta name="keywords" content="XSLT, XPath, XML"/&gt;</code></p>
     <p><code>   &lt;meta name="description"</code></p>
     <p><code>    content="This site is dedicated to XSLT and Xpath."/&gt;</code></p>
     <p><code>   &lt;title&gt;XSLTdev.ru - XSLT developer resource&lt;/title&gt;</code></p>
     <p><code>   &lt;link rel="stylesheet" type="text/css" href="style/main.css"/&gt;</code></p>
     <p><code>  &lt;/head&gt;</code></p>
     <p><code>  &lt;body&gt;&lt;xsl:value-of select="content"/&gt;&lt;/body&gt;</code></p>
     <p><code> &lt;/html&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>В принципе именованные шаблоны не обязаны иметь атрибут <code>match</code>, но он все же может быть определен. В этом случае шаблон можно будет применять как для обработки частей документов элементом <code>xsl:apply-templates</code>, так и вызывая его по имени элементом <code>xsl:call-template</code>.</p>
     <subtitle>Пример</subtitle>
     <p>Изменим объявление нашего шаблона head следующим образом:</p>
     <p><code>&lt;xsl:template name="head" match="head"&gt;</code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Теперь, если входящий документ будет иметь вид</p>
     <p><code>&lt;page&gt;</code></p>
     <p><code> &lt;head/&gt;</code></p>
     <p><code> &lt;content&gt;Just a few words...&lt;/content&gt;</code></p>
     <p><code>&lt;/page&gt;</code></p>
     <p>то результат выполнения следующих двух шаблонов будет одинаков.</p>
     <subtitle>Листинг 5.9. Шаблон для page — версия 1</subtitle>
     <p><code>&lt;xsl:template match="page"&gt;</code></p>
     <p><code> &lt;html&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates select="head"/&gt;</code></p>
     <p><code>  &lt;body&gt;&lt;xsl:copy-of select="content/node()/&gt;&lt;/body&gt;</code></p>
     <p><code> &lt;/html&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <subtitle>Листинг 5.10. Шаблон для page — версия 2</subtitle>
     <p><code>&lt;xsl:template match="page"&gt;</code></p>
     <p><code> &lt;html&gt;</code></p>
     <p><code>  &lt;xsl:call-template name="head"/&gt;</code></p>
     <p><code>  &lt;body&gt;&lt;xsl:copy-of select="content/node()/&gt;&lt;/body&gt;</code></p>
     <p><code> &lt;/html&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>В чем же состоит разница вызова шаблона элементами <code>xsl:apply-templates</code> и <code>xsl:call-template</code>? Перечислим несколько отличий.</p>
     <p>&#9633; Элемент <code>xsl:apply-templates</code> применяет подходящие шаблоны к узлам определенного множества; <code>xsl:call-template</code> просто выполняет тело фиксированного именованного шаблона.</p>
     <p>&#9633; При вызове шаблона инструкцией <code>xsl:apply-templates</code> происходит изменение контекста — обрабатываемое множество узлов становится текущим списком узлов преобразования, а обрабатываемый узел — текущим узлом; <code>xsl:call-template</code> не изменяет контекст преобразования.</p>
     <p>&#9633; Инструкция <code>xsl:apply-templates</code> позволяет использовать различные режимы — применяются только те шаблоны, значение атрибута <code>mode</code> которых равно значению этого атрибута у вызывающей инструкции; <code>xsl:call-template</code> выполняет шаблон с заданным именем вне зависимости от того, в каком режиме происходит обработка и каково значение атрибута <code>mode</code> этого шаблона.</p>
     <p>&#9633; Если для обработки определенного узла подходит несколько шаблонов, то при выполнении <code>xsl:apply-templates</code> процессор будет выбирать наиболее подходящий из них; <code>xsl:call-template</code> всегда будет выполнять тот единственный шаблон преобразования, который имеет указанное имя.</p>
     <p>&#9633; Если в преобразовании не определен шаблон для обработки некоторого узла, но к нему элементом <code>xsl:apply-templates</code> все же применяются шаблоны, процессор будет использовать шаблон обработки по умолчанию; если элемент <code>xsl:call-template</code> вызывает отсутствующий шаблон, процессор выдаст сообщение об ошибке, потому что не сможет найти шаблон с заданным именем.</p>
     <p>&#9633; При использовании <code>xsl:apply-templates</code> процессор игнорирует значения атрибутов <code>name</code> элементов <code>xsl:template</code>; точно так же <code>xsl:call-template</code> принимает во внимание только значение атрибута <code>name</code>, игнорируя атрибуты <code>match</code>, <code>mode</code> и <code>priority</code>.</p>
     <p>При желании можно найти еще с десяток отличий, но и этих положений вполне достаточно для того, чтобы понять разницу. Главным выводом из этого сравнения является то, что <code>xsl:apply-templates</code> демонстрирует декларативный, а <code>xsl:call-template</code> процедурный стиль программирования В первом случае мы используем объявленные (или задекларированные) правила преобразования, во втором — используем шаблон просто как процедуру.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Встроенные шаблоны</p>
    </title>
    <p>Для того чтобы обеспечить рекурсивную обработку документа при преобразовании, в XSLT существуют так называемые встроенные шаблоны. Несмотря на то, что они не описываются в преобразованиях явным образом, встроенные шаблоны применяются процессорами по умолчанию в случаях, когда более подходящих шаблонов нет.</p>
    <p>Существуют пять основных шаблонных правил, которые применяются процессорами по умолчанию.</p>
    <p>Первое из них обеспечивает рекурсивную обработку дочерних элементов документа, которые находятся как в корне, так и в других элементах. Это правило эквивалентно следующему шаблону:</p>
    <p><code>&lt;xsl:template match="*|/"&gt;</code></p>
    <p><code> &lt;xsl:apply-templates/&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Второе встроенное правило преобразования аналогично первому, с той лишь особенностью, что для каждого режима преобразования рекурсивная обработка происходит в том же самом режиме. В XSLT это правило выглядело бы следующим образом:</p>
    <p><code>&lt;xsl:template match="*|/" mode="режим"&gt;</code></p>
    <p><code> &lt;xsl:apply-templates mode="режим"/&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>В XSLT также определяется встроенное правило для обработки текстовых узлов и атрибутов — это правило просто выводит их текстовые значения. Шаблон такого преобразования может быть записан в виде:</p>
    <p><code>&lt;xsl:template match="text()|@*"&gt;</code></p>
    <p><code> &lt;xsl:value-of select="."/&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Четвертое правило касается обработки инструкций по обработке и комментариев. Это правило не делает ничего, то есть инструкции и комментарии просто опускаются в выходящем документе. Шаблон такого преобразования будет иметь вид</p>
    <p><code>&lt;xsl:template match="processing-instruction()|comment()"/&gt;</code></p>
    <p>Последнее, пятое правило определяет обработку узлов пространств имен. Аналогично инструкциям и комментариям, с ними по умолчанию не следует делать ничего, то есть узлы пространств имен просто удаляются.</p>
    <p>Встроенные шаблоны имеют наименьший приоритет импорта, а значит, будут использоваться лишь тогда, когда в преобразовании нет другого, более подходящего правила. Иными словами, любой шаблон, определенный в преобразовании, будет иметь больший приоритет, чем у встроенных правил.</p>
    <p>Такое положение вещей позволяет переопределять преобразования, применяемые к узлам документа по умолчанию. Например, во многих случаях бывает весьма полезным идентичное преобразование, которое копирует узлы как есть. Мы уже встречались с ним, когда создавали шаблон для генерации таблицы ссылок XHTML-документа; теперь мы чуть более подробно разберем его работу.</p>
   </section>
   <section>
    <title>
     <p>Идентичное преобразование</p>
    </title>
    <p>Наличие в XSLT шаблонов, выполняемых по умолчанию, иногда приводит к тому, что процессоры ведут себя не совсем логично с человеческой точки зрения. Например, в простейшем случае может понадобиться переименовать все элементы с именами <code>bold</code> в элементы с именами <code>b</code>. Однако результатом обработки документа</p>
    <p><code>&lt;а&gt;</code></p>
    <p><code> text a</code></p>
    <p><code> &lt;bold&gt;</code></p>
    <p><code>  text b</code></p>
    <p><code>  &lt;bold/&gt;</code></p>
    <p><code> &lt;/bold&gt;</code></p>
    <p><code> &lt;c&gt;</code></p>
    <p><code>  text c </code></p>
    <p><code> &lt;/c&gt;</code></p>
    <p><code>&lt;/a&gt;</code></p>
    <p>преобразованием</p>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="bold"&gt;</code></p>
    <p><code>  &lt;b&gt;&lt;xsl:apply-templates/&gt;&lt;/b&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>будет документ вида</p>
    <p><code>text a</code></p>
    <p><code>&lt;b&gt;</code></p>
    <p><code> text b</code></p>
    <p><code> &lt;b/&gt;</code></p>
    <p><code>&lt;/b&gt;</code></p>
    <p><code>text c</code></p>
    <p>Как можно заметить, в выходящем документе элементы <code>а</code> и <code>с</code> "пропали", но при этом их содержимое осталось нетронутым. Все дело во встроенных шаблонах, которые по умолчанию рекурсивно обрабатывают содержимое элементов и копируют текстовые узлы, если иного не определено.</p>
    <p>Для того чтобы избежать подобного рода казусов, можно использовать идентичное преобразование, которое в случае отсутствия шаблонов для обработки тех или иных узлов копирует их в выходящий документ как есть. Идентичное преобразование записывается в следующем виде.</p>
    <subtitle>Листинг 5.11. Идентичное преобразование</subtitle>
    <p><code>&lt;xsl:stylesheet version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="@*|node()"&gt;</code></p>
    <p><code>  &lt;xsl:copy&gt;</code></p>
    <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
    <p><code>  &lt;/xsl:copy&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>Единственный шаблон этого преобразования при помощи элемента <code>xsl:copy</code> рекурсивно создает в выходящем документе копии узлов и атрибутов. На практике идентичное преобразование используется очень часто, и потому мы настоятельно рекомендуем сохранить его в отдельном файле и импортировать при потребности.</p>
    <p>Поясним, что это преобразование выполняет не просто копирование документа (для этого было бы достаточно элемента <code>xsl:copy-of</code>). Идентичное преобразование переопределяет встроенные шаблоны; теперь, если для обработки какого-либо узла в преобразовании не определено подходящего шаблона, он вместе со всеми своими потомками будет скопирован в выходящий документ без изменений.</p>
    <p>Идентичное преобразование очень полезно в тех случаях, когда требуется изменить только некоторые части документа, оставив остальное в неприкосновенности. Например, в предыдущем примере нам нужно было только переименовать все документы <code>bold</code>. Искомое преобразование, импортирующее идентичное преобразование из файла <code>identity.xsl</code>, будет записано следующим образом.</p>
    <subtitle>Листинг 5.12</subtitle>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <p><code> &lt;xsl:import href="identity.xsl"/&gt;</code></p>
    <p><code> &lt;xsl:template match="bold"&gt;</code></p>
    <p><code>  &lt;b&gt;</code></p>
    <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
    <p><code>  &lt;/b&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>Результат будет иметь вид:</p>
    <p><code>&lt;a&gt;</code></p>
    <p><code> text a</code></p>
    <p><code> &lt;b&gt;</code></p>
    <p><code>  text b</code></p>
    <p><code>  &lt;b/&gt;</code></p>
    <p><code> &lt;/b&gt;</code></p>
    <p><code> &lt;c&gt;</code></p>
    <p><code>  text c</code></p>
    <p><code> &lt;/c&gt;</code></p>
    <p><code>&lt;/a&gt;</code></p>
    <p>Другим примером использования идентичного преобразования может послужить случай, когда нужно просто удалить из документа некоторые узлы. Например, нам необходимо избавиться от комментариев (быстро и без шума).</p>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <p><code> &lt;xsl:import href="identity.xsl"/&gt;</code></p>
    <p><code> &lt;xsl:template match="comment()"/&gt;</code></p>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
   </section>
   <section>
    <title>
     <p>Разрешение конфликтов в шаблонах</p>
    </title>
    <section>
     <p>Как правило, каждое преобразование в XSLT определяет, включает или импортирует множество шаблонов, которые обрабатывают указанные части документов. При этом один и тот же узел документа может соответствовать нескольким шаблонным правилам. К примеру, элемент <code>content</code> может быть обработан любым из следующих трех шаблонов.</p>
     <subtitle>Листинг 5.14. Конфликтующие шаблоны</subtitle>
     <p><code>&lt;xsl:template match="*"&gt;</code></p>
     <p><code> &lt;element/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:template match="node()"&gt;</code></p>
     <p><code> &lt;node/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:template match="content"&gt;</code></p>
     <p><code> &lt;content/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Ситуация, когда для обработки узла может быть применено несколько правил, называется конфликтом шаблонов. Конфликты такого рода неизбежны практически в любом преобразовании, к примеру, большинство шаблонов будет вступать в конфликт со встроенными правилами преобразования.</p>
     <p>Для того чтобы в конфликтной ситуации решить, какой именно из шаблонов должен быть применен к данному узлу, процессоры используют два простых правила.</p>
     <p>&#9633; Шаблоны, имеющие младший порядок импорта, исключаются из рассмотрения. Иными словами, из множества правил, подходящих для обработки текущего узла, остаются только правила, имеющие самый старший порядок импорта.</p>
     <p>&#9633; Из оставшегося множества выбирается шаблон с наивысшим приоритетом. Если таких шаблонов несколько, процессор может либо выдать ошибку, либо применить тот, который описан в преобразовании последним.</p>
     <p>Во втором из этих двух правил, мы встретились с понятием приоритета шаблона. Приоритет шаблона это не что иное, как численное значение, которое может быть указано в атрибуте <code>priority</code> элемента <code>xsl:template</code>. В том случае, если значение этого атрибута не определено, приоритет шаблонного правила вычисляется следующим образом.</p>
     <p>&#9633; Прежде всего, шаблон, который обрабатывает несколько альтернатив, перечисленных через знак "<code>|</code>", будет рассматриваться как множество шаблонов, обрабатывающих каждую из возможностей. Например, шаблон с атрибутом <code>match="b|bold|B"</code> будет рассматриваться как три одинаковых шаблона с атрибутами <code>match="b"</code>, <code>match="bold"</code> и <code>match="B"</code> соответственно.</p>
     <p>&#9633; Если паттерн состоит из имени (<code>QName</code>) или конструкции <code>processing-instruction(<emphasis>литерал</emphasis>)</code>, которым предшествует дескриптор оси дочернего узла или атрибута (<code>ChildOrAttributeAxisSpecifier</code>), приоритет шаблона равен <code>0</code>. Такие паттерны могут иметь следующий вид:</p>
     <p> • <code><emphasis>QName</emphasis></code> или <code>child::<emphasis>QName</emphasis></code> — выбор дочерних элементов;</p>
     <p> • <code>@<emphasis>QName</emphasis></code> или <code>attribute::<emphasis>QName</emphasis></code> — выбор атрибутов;</p>
     <p> • <code>processing-instruction(<emphasis>литерал</emphasis>)</code> или <code>child::processing-instruction(<emphasis>литерал</emphasis>)</code> — именной выбор дочерних инструкций по обработке.</p>
     <p>Примеры паттернов с приоритетом, равным <code>0</code>:</p>
     <p> • <code>content</code> — выбор дочернего элемента <code>content</code>;</p>
     <p> • <code>fo:content</code> — выбор дочернего элемента <code>content</code> с префиксом пространств имен <code>fo</code>;</p>
     <p> • <code>child::processing-instruction('арр')</code> — выбор дочерних инструкций по обработке, которые имеют вид <code>&lt;?app содержимое?&gt;</code>;</p>
     <p> • <code>@xsd:name</code> — выбор атрибута <code>xsd:name</code> текущего узла;</p>
     <p> • <code>@select</code> — выбор атрибута <code>select</code> текущего узла.</p>
     <p>&#9633; Если паттерн состоит из конструкции <code>NCName:*</code>, которой предшествует <code>ChildOrAxisSpecifier</code>, приоритет шаблона будет равен <code>-0.25</code>. Такие паттерны могут иметь следующий вид:</p>
     <p> • <code><emphasis>префикс</emphasis>:*</code> или <code>child::<emphasis>префикс</emphasis>:*</code> — выбор всех дочерних элементов в определенном пространстве имен;</p>
     <p> • <code>@<emphasis>префикс</emphasis>:*</code> или <code>attribute::<emphasis>префикс</emphasis>:*</code> — выбор всех атрибутов в определенном пространстве имен.</p>
     <p>Примеры паттернов с приоритетом, равным <code>-0.25</code>:</p>
     <p> • <code>fo:*</code> — выбор всех дочерних элементов в пространстве имен с префиксом <code>fo</code>;</p>
     <p> • <code>attribute::xsl:*</code> — выбор всех атрибутов текущего элемента, которые находятся в пространстве имен с префиксом <code>xsl</code>.</p>
     <p>&#9633; Если паттерн состоит из проверки узла (<code>NodeTest</code>), которой предшествует <code>ChildOrAttributeAxisSpecifier</code>, приоритет шаблона будет равен <code>-0.5</code>. Паттерны такого рода будут выглядеть как:</p>
     <p> • <code><emphasis>NodeTest</emphasis></code> или <code>child::<emphasis>NodeTest</emphasis></code> — выбор всех дочерних узлов, соответствующих данной проверке;</p>
     <p> • <code><emphasis>QNodeTest</emphasis></code> или <code>attribute::<emphasis>NodeTest</emphasis></code> — выбор всех атрибутов, соответствующих данной проверке.</p>
     <p>&#9633; Примеры паттернов с приоритетом, равным <code>-0.5</code>:</p>
     <p> • <code>text()</code> — выбор дочерних текстовых узлов;</p>
     <p> • <code>child::comment()</code> — выбор дочерних комментариев;</p>
     <p> • <code>@*</code> — выбор всех атрибутов данного шаблона.</p>
     <p>&#9633; Если ни одно из предыдущих условий не выполняется, приоритет шаблона равен <code>0.5</code>.</p>
     <p>Для удобства использования составим таблицу (табл. 5.1) с приоритетами тех или иных паттернов.</p>
     <empty-line/>
     <p><emphasis><strong>Таблица 5.1</strong>. Приоритет паттернов</emphasis></p>
     <table>
      <tr>
       <th align="left">Вид паттерна</th>
       <th align="left">Приоритет</th>
      </tr>
      <tr>
       <td align="left"><code><emphasis>QName</emphasis></code></td>
       <td rowspan="5" align="left"><code>0</code></td>
      </tr>
      <tr>
       <td align="left"><code>child::<emphasis>QName</emphasis></code></td>
      </tr>
      <tr>
       <td align="left"><code>@<emphasis>QName</emphasis></code></td>
      </tr>
      <tr>
       <td align="left"><code>attribute::<emphasis>QName</emphasis></code></td>
      </tr>
      <tr>
       <td align="left"><code>processing-instruction(<emphasis>литерал</emphasis>)</code></td>
      </tr>
      <tr>
       <td align="left"><code>child::processing-instruction(<emphasis>литерал</emphasis>)</code></td>
      </tr>
      <tr>
       <td align="left"><code><emphasis>префикс</emphasis>:*</code></td>
       <td rowspan="4" align="left"><code>-0.25</code></td>
      </tr>
      <tr>
       <td align="left"><code>child::<emphasis>префикс</emphasis>:*</code></td>
      </tr>
      <tr>
       <td align="left"><code>@<emphasis>префикс</emphasis>:*</code></td>
      </tr>
      <tr>
       <td align="left"><code>attribute::<emphasis>префикс</emphasis>:*</code></td>
      </tr>
      <tr>
       <td align="left"><code><emphasis>NodeTest</emphasis></code></td>
       <td rowspan="4" align="left"><code>-0.5</code></td>
      </tr>
      <tr>
       <td align="left"><code>child::<emphasis>NodeTest</emphasis></code></td>
      </tr>
      <tr>
       <td align="left"><code>@<emphasis>NodeTest</emphasis></code></td>
      </tr>
      <tr>
       <td align="left"><code>attribute::<emphasis>NodeTest</emphasis></code></td>
      </tr>
      <tr>
       <td align="left">Другие паттерны</td>
       <td align="left"><code>0.5</code></td>
      </tr>
     </table>
     <p>Несмотря на то, что вычислением приоритета преобразований занимается процессор, полезно понимать механизм этого вычисления для того, чтобы уметь предсказывать, как будет решен конфликт тех или иных шаблонов. Довольно часто в преобразованиях допускаются ошибки, связанные с приоритетом применения шаблонов.</p>
     <subtitle>Пример</subtitle>
     <p>Вычислим в качестве упражнения приоритеты шаблонов для следующего примера.</p>
     <subtitle>Листинг 5.15. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform" </code></p>
     <p><code> xmlns:a="a"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:strip-space elements="*"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Первый шаблон --&gt;</code></p>
     <p><code> &lt;xsl:template match="a:b"&gt;</code></p>
     <p><code>  &lt;xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;1&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Второй шаблон --&gt;</code></p>
     <p><code> &lt;xsl:template match="a:a/a:b"&gt;</code></p>
     <p><code>  &lt;xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;2&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Третий шаблон --&gt;</code></p>
     <p><code> &lt;xsl:template match="a:*"&gt;</code></p>
     <p><code>  &lt;xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;3&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Четвертый шаблон --&gt;</code></p>
     <p><code> &lt;xsl:template match="node()"&gt;</code></p>
     <p><code>  &lt;xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;4&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Пятый шаблон --&gt;</code></p>
     <p><code> &lt;xsl:template match="b"&gt;</code></p>
     <p><code>  &lt;xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;5&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template name="print-name"&gt;</code></p>
     <p><code>  &lt;xsl:text&gt; template matched &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="name()"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;.&lt;/xsl:text&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Пять шаблонов этого преобразования могут соответствовать одним и тем же узлам, а значит, создавать множество конфликтов, которые будут разрешаться при помощи механизма приоритетов.</p>
     <p>Приоритет первого шаблона, паттерн которого соответствует продукции QName, будет равен <code>0</code>. Приоритет второго шаблона будет равен <code>0.5</code>, поскольку его паттерн не удовлетворяет другим условиям. Паттерн третьего шаблона имеет вид <code>NCName:*</code>, а значит, его приоритет равен <code>-0.25</code>. Приоритет четвертого шаблона равен <code>-0.5</code>, поскольку его паттерн является проверкой узла (<code>NodeTest</code>). Приоритет последнего, пятого шаблона будет равен 0, поскольку паттерн <code>b</code> соответствует продукции <code>QName</code>.</p>
     <p>Попробуем применить это преобразование к следующему документу:</p>
     <p><code>&lt;?ORA bypass="yes"?&gt;</code></p>
     <p><code>&lt;b&gt;</code></p>
     <p><code> &lt;a xmlns="a"&gt;</code></p>
     <p><code>  &lt;b&gt;</code></p>
     <p><code>   &lt;b&gt;</code></p>
     <p><code>    &lt;c/&gt;</code></p>
     <p><code>   &lt;/b&gt;</code></p>
     <p><code>  &lt;/b&gt;</code></p>
     <p><code> &lt;/a&gt;</code></p>
     <p><code>&lt;/b&gt;</code></p>
     <p>Проследим за тем, как будет выполняться преобразование.</p>
     <p>&#9633; Инструкции по обработке <code>&lt;?ORA bypass="yes"?&gt;,</code> которая идет в документе первой, соответствует только один, четвертый шаблон.</p>
     <p>&#9633; Корневому элементу <code>b</code> соответствуют два шаблона — четвертый и пятый, однако приоритет пятого шаблона выше, и поэтому применен будет именно он.</p>
     <p>&#9633; Следующему элементу, <code>a</code>, соответствуют третий и четвертый шаблоны. Здесь процессор должен применить третий шаблон, так как его приоритет выше, чем приоритет четвертого шаблона.</p>
     <p>&#9633; Элемент <code>b</code>, включенный в элемент <code>а</code>, соответствует первому, второму, третьему и четвертому шаблонам. Наивысший приоритет из них имеет второй шаблон.</p>
     <p>&#9633; Следующему элементу <code>b</code> соответствуют первый, третий и четвертый шаблоны. В этом случае процессор выберет первый шаблон.</p>
     <p>&#9633; Элемент <code>с</code> соответствует третьему и четвертому шаблонному правилу. В этом случае процессор должен будет использовать третий шаблон.</p>
     <p>Сравнивая этот анализ с сообщениями процессора, можно убедиться в верности прогноза:</p>
     <p><code>4 template matched ORA.</code></p>
     <p><code>5 template matched b.</code></p>
     <p><code>3 template matched a.</code></p>
     <p><code>2 template matched b.</code></p>
     <p><code>1 template matched b.</code></p>
     <p><code>3 template matched c.</code></p>
     <p>Напомним, что приоритет преобразований может быть также явно указан в атрибуте <code>priority</code> элемента <code>xsl:template</code>. Например, если бы в предыдущем преобразовании четвертый шаблон был определен в виде</p>
     <p><code>&lt;xsl:template match="node()" priority="1"&gt;</code></p>
     <p><code> &lt;xsl:message&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;4&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code> &lt;/xsl:message&gt;</code></p>
     <p><code> &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>то его приоритет был бы выше, чем у всех остальных шаблонов, а поскольку он соответствует всем узлам в обрабатываемом документе, то во всех случаях применялся бы только он один. Сообщения процессора имели бы вид</p>
     <p><code>4 template matched ORA.</code></p>
     <p><code>4 template matched b.</code></p>
     <p><code>4 template matched a.</code></p>
     <p><code>4 template matched b.</code></p>
     <p><code>4 template matched b.</code></p>
     <p><code>4 template matched c.</code></p>
     <p>Между тем, явное указание приоритета шаблона не может изменить порядок его импорта. То есть, если бы в предыдущем примере четвертый шаблон был бы вынесен во внешний модуль и импортирован в основное преобразование, в любом случае он бы применялся только в отсутствие более подходящих правил.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 5.16. Основное преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:a="a"&gt;</code></p>
     <p><code> &lt;xsl:import href="b.xsl"/&gt;</code></p>
     <p><code> &lt;xsl:strip-space elements="*"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="a:b"&gt;</code></p>
     <p><code>  &lt;xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;1&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="a:a/a:b"&gt;</code></p>
     <p><code>  &lt;xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;2&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="a:*"&gt;</code></p>
     <p><code>  &lt;xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;3&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code>  &lt;/xsl :message&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="b"&gt;</code></p>
     <p><code>  &lt;xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;5&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 5.17. Преобразование b.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:a="a"&gt;</code></p>
     <p><code> &lt;xsl:strip-space elements="*"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="node()" priority="1"&gt;</code></p>
     <p><code>  &lt;xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;4&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="print-name"/&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template name="print-name"&gt;</code></p>
     <p><code>  &lt;xsl:text&gt; template matched &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="name()"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;.&lt;/xsl:text&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Как уже было сказано ранее, четвертое преобразование, вынесенное теперь в импортируемый модуль, при разрешении конфликтов шаблонов будет самым младшим вследствие того, что порядок его импорта меньше, чем у других преобразований. Сообщения процессора будут иметь вид</p>
     <p><code>4 template matched ORA.</code></p>
     <p><code>5 template matched b.</code></p>
     <p><code>3 template matched a.</code></p>
     <p><code>2 template matched b.</code></p>
     <p><code>1 template matched b.</code></p>
     <p><code>3 template matched c.</code></p>
     <p>Кстати сказать, XSLT предоставляет возможность выполнять в преобразованиях импортированные шаблоны вместо тех, которые, по мнению процессора, лучше подходят. Подобно тому, как для применения шаблонных правил мы использовали элемент <code>xsl:apply-templates</code>, импортированные шаблоны могут быть вызваны элементом <code>xsl:apply-imports</code>.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:apply-imports</emphasis></p>
     </title>
     <p>Синтаксис этого элемента:</p>
     <p><code>&lt;xsl:apply-imports/&gt;</code></p>
     <p>Элемент <code>xsl:apply-imports</code> можно использовать в шаблонах для применения правил, которые были импортированы во внешних модулях, но затем переопределены шаблонами основного преобразования.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что в преобразованиях часто используется шаблон, который заменяет элементы <code>home</code> ссылками на сайт <strong>http://www.xsltdev.ru</strong>:</p>
     <p><code>&lt;xsl:template match="home"&gt;</code></p>
     <p><code> &lt;а href="http://www.xsltdev.ru"&gt;www.xsltdev.ru&lt;/a&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>При необходимости этот шаблон может быть переопределен. К примеру, ссылка может выглядеть как</p>
     <p><code>Visit &lt;а href="http://www.xsltdev.ru"&gt;www.xsltdev.ru&lt;/a&gt;</code></p>
     <p>Соответственно, шаблон будет иметь вид</p>
     <p><code>&lt;xsl:template match="home"&gt;</code></p>
     <p><code> &lt;xsl:text&gt;Visit &lt;/xsl:text&gt;</code></p>
     <p><code> &lt;a href="http://www.xsltdev.ru"&gt;www.xsltdev.ru&lt;/a&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Можно заметить, что оба шаблона имеют общую часть, которая выводит гипертекстовую ссылку. Эта часть может быть вынесена во внешнее преобразование <code>home.xsl</code>.</p>
     <subtitle>Листинг 5.18. Преобразование home.xml</subtitle>
     <p><code>&lt;xsl:stylesheet version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> &lt;xsl:template match="home"&gt;</code></p>
     <p><code>  &lt;a href="http://www.xsltdev.ru"&gt;www.xsltdev.ru&lt;/a&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Для того чтобы использовать внешний шаблон, основное преобразование должно импортировать его при помощи <code>xsl:import</code> и применять посредством xsl:apply-imports.</p>
     <subtitle>Листинг 5.19. Основное преобразование base.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> version="1.0"&gt;</code></p>
     <p><code> &lt;xsl:import href="home.xsl"/&gt;</code></p>
     <p><code> &lt;xsl:template match="home"&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;Visit &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:apply-imports/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Элемент <code>xsl:apply-imports</code> нельзя использовать в блоках <code>xsl:for-each</code> и при вычислении глобальных переменных. Дело в том, что при обработке <code>xsl:apply-imports</code> процессор применяет импортируемые правила в соответствии с текущим шаблоном. Текущий шаблон — это то самое правило, которое процессор выполняет при обработке элемента <code>xsl:apply-templates</code>. При вычислении глобальных переменных и обработке блоков <code>xsl:for-each</code> текущее правило становится пустым, и, соответственно, вызов <code>xsl:apply-imports</code> вызовет ошибку.</p>
     <p>Элемент <code>xsl:apply-imports</code> применяет шаблоны точно так же, как и элемент <code>xsl:apply-templates</code>, но при этом он имеет две особенности.</p>
     <p>&#9633; Шаблоны, определенные в основном преобразовании, применяться не будут, поскольку <code>xsl:apply-imports</code> применяет только импортированные правила.</p>
     <p>&#9633; Элемент <code>xsl:apply-imports</code> применяет только те правила, режим (<code>mode</code>) которых совпадает с режимом текущего шаблона.</p>
     <p>В текущей версии XSLT <code>xsl:apply-imports</code> не может вызывать импортированные именованные шаблоны.</p>
     <p>Для того чтобы лучше понять, зачем нужна такая сложная схема импорта, проведем аналогию с объектно-ориентированным программированием. Если рассматривать правила преобразований как методы классов, то импорт преобразований будет ни чем иным, как наследованием — все методы (шаблоны) класса-потомка (импортируемого преобразования) будут доступны в классе-наследнике (импортирующем преобразовании). При этом класс-наследник может переопределить методы класса потомка (шаблоны основного преобразования имеют порядок импорта старше, чем шаблоны импортированного преобразования). В этой схеме использование элемента <code>xsl:apply-imports</code> будет равносильно вызову метода родительского класса вместо переопределенного метода класса потомка.</p>
     <p>Приведем пример Java-классов, которые будут аналогичны преобразованиям <code>home.xsl</code> и <code>base.xsl</code>.</p>
     <subtitle>Листинг 5.20. Класс home</subtitle>
     <p><code>public class home {</code></p>
     <p><code> public String home() {</code></p>
     <p><code>  return "&lt;a href=\"http://www.xsltdev.ru\"&gt;www.xsltdev.ru&lt;/a&gt;";</code></p>
     <p><code> }</code></p>
     <p><code>}</code></p>
     <subtitle>Листинг 5.21. Класс base</subtitle>
     <p><code>public class base extends home {</code></p>
     <p><code> public String home() {</code></p>
     <p><code>  return ("Visit " + super.home());</code></p>
     <p><code> }</code></p>
     <p><code>}</code></p>
     <p>В этом примере вызов родительского метода <code>super.home()</code> соответствует применению элементом <code>xsl:apply-imports</code> импортированного шаблона.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Тело шаблона</p>
    </title>
    <p>Фактически, элемент <code>xsl:template</code>, определяющий шаблонное правило, задает не более чем условия, при которых это правило должно выполняться. Конкретные же действия и инструкции, которые должны быть исполнены, определяются содержимым элемента <code>xsl:template</code> и составляют <emphasis>тело шаблона</emphasis>.</p>
    <subtitle>Пример</subtitle>
    <p>Тело следующего шаблона (выделенное полужирным шрифтом):</p>
    <p><code>&lt;xsl:template match="page"&gt;</code></p>
    <p><code><strong> &lt;body&gt;</strong></code></p>
    <p><code><strong>  &lt;xsl:value-of select="."/&gt;</strong></code></p>
    <p><code><strong> &lt;/body&gt;</strong></code></p>
    <p><code><strong> Комментарии</strong></code></p>
    <p><code><strong> &lt;xsl:copy-of select="comment()"/&gt;</strong></code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>состоит из литерального элемента <code>body</code>, текстового узла и элемента <code>xsl:copy-of</code>. При выполнении этого шаблона элемент <code>body</code> будет выведен как есть (при этом содержимое его будет вычислено); текстовый узел будет скопирован в выходящее дерево; элемент <code>xsl:copy-of</code> будет заменен множеством дочерних комментариев текущего узла.</p>
    <p>Следует заметить, что текстовый узел в данном случае состоит не только из строки "Комментарии". Он включает также все пробельные символы и символы переноса строки.</p>
    <p>Тело шаблона может быть также и пустым. В этом случае результат обработки узлов, соответствующих этому шаблону будет пустым. Например, если в преобразовании содержится шаблон вида</p>
    <p><code>&lt;xsl:template match="comment()"/&gt;</code></p>
    <p>то каждый раз, встретив узел комментария и обрабатывая его этим правилом, процессор будет получать пустой результат. Таким образом, используя пустые шаблоны совместно с идентичным преобразованием можно добиться эффекта удаления определенных узлов из шаблона, как это было показано ранее в этой главе.</p>
    <p>Тело шаблона может содержать любые текстовые узлы, комментарии, инструкции по обработке и литеральные элементы результата при условии, что не будет нарушен синтаксис XML-документа. Тело шаблона может также содержать следующие элементы XSLT, называемые также инструкциями (не путать с инструкциями по обработке):</p>
    <p>&#9633; <code>xsl:apply-imports</code>;</p>
    <p>&#9633; <code>xsl:apply-templates</code>;</p>
    <p>&#9633; <code>xsl:attribute</code>;</p>
    <p>&#9633; <code>xsl:call-template</code>;</p>
    <p>&#9633; <code>xsl:choose</code>;</p>
    <p>&#9633; <code>xsl:comment</code>;</p>
    <p>&#9633; <code>xsl:copy</code>;</p>
    <p>&#9633; <code>xsl:copy-of</code>;</p>
    <p>&#9633; <code>xsl:element</code>;</p>
    <p>&#9633; <code>xsl:fallback</code>;</p>
    <p>&#9633; <code>xsl:for-each</code>;</p>
    <p>&#9633; <code>xsl:if</code>;</p>
    <p>&#9633; <code>xsl:message</code>;</p>
    <p>&#9633; <code>xsl:number</code>;</p>
    <p>&#9633; <code>xsl:param</code>;</p>
    <p>&#9633; <code>xsl:processing-instruction</code>;</p>
    <p>&#9633; <code>xsl:text</code>;</p>
    <p>&#9633; <code>xsl:value-of</code>;</p>
    <p>&#9633; <code>xsl:variable</code>.</p>
    <p>Элементы <code>xsl:param</code> и <code>xsl:variable</code>, которые входят в этот список в преобразовании, могут быть как элементами верхнего уровня, так и инструкциями. В первом случае они определяют глобальные параметры и переменные, во втором — локальные.</p>
    <p>Если элементы <code>xsl:param</code> используются для определения локальных переменных, они должны быть первыми дочерними элементами <code>xsl:template</code>, то есть, строго говоря, определение</p>
    <p><code>&lt;xsl:template name="page"&gt;</code></p>
    <p><code> &lt;xsl:text&gt;Text&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;xsl:param name="foo"/&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>будет некорректным. На самом деле многие процессоры игнорируют эту ошибку, вполне разумно считая, что ничего смертельного в ней нет. Но, конечно, лучше использовать стандартный вариант:</p>
    <p><code>&lt;xsl:template name="page"&gt;</code></p>
    <p><code> &lt;xsl:param name="foo"/&gt;</code></p>
    <p><code> &lt;xsl:text&gt;Text&lt;/xsl:text&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
   </section>
   <section>
    <title>
     <p>Переменные и параметры</p>
    </title>
    <section>
     <p>Было бы слишком просто и слишком бесполезно лишь констатировать, что переменные и параметры в XSLT похожи между собой и сильно отличаются от переменных в других языках программирования. Мы попытаемся разобраться в этом вопросе несколько глубже — <emphasis>чем</emphasis> именно и <emphasis>ради чего</emphasis> конкретно переменные в XSLT обладают такими свойствами.</p>
     <p>В классической книге Монти Бен-Ари "Языки программирования" [Бен-Ари 2000] приводится следующее определение переменной:</p>
     <p><emphasis>Переменная — это имя, присвоенное ячейке памяти или ячейкам, которые могут содержать представление конкретного типа (данных).</emphasis></p>
     <p>Затем следует комментарий:</p>
     <p><emphasis>Значение может изменяться во время выполнения программы.</emphasis></p>
     <p>Если немного сменить уровень абстракции, первая часть этого определения верна и по отношению к параметрам, и переменным XSLT (далее мы будем говорить просто "переменные", поскольку различия между ними на данный момент несущественны). Конечно, где-то там внутри реализации конкретного XSLT-процессора есть память, поделенная на ячейки, в которой процессор хранит информацию. Такие детали нас, естественно, не интересуют, ибо мы больше рассуждаем о логических, чем о физических моделях. В логической же модели переменная представляется как объект определенного типа, с которым связано имя, — по этому имени мы можем обращаться к объекту, использовать его значение и так далее. Иными словами, в XSLT под переменной понимается не более чем ассоциация между значением и именем, и если мы вдруг скажем, что переменная <code>x</code> имеет значение <code>5</code>, это будет означать, что имя "<code>x</code>" связано объектом численного типа, значение которого равно <code>5</code>. Заметим небольшую разницу с определением Бен-Ари: мы не говорим о том, что число <code>5</code> лежит в какой-то ячейке памяти (хотя, несомненно, оно так и есть) и что этой ячейке присвоено имя "<code>x</code>" — мы говорим об ассоциации между объектом и именем и только.</p>
     <p>Теперь, когда более или менее ясно, что же мы имеем в виду под переменными, на новой строчке полужирным шрифтом напишем следующее:</p>
     <subtitle>Переменные в XSLT не могут быть изменены.</subtitle>
     <p>Разработчикам, которые использовали в своей практике только процедурные языки и не имеют опыта функционального или логического программирования будет очень нелегко смириться с такой ситуацией. То, что <emphasis>переменные</emphasis> не могут быть изменены дискредитирует само название — <emphasis>переменные</emphasis>, ибо они уже более похожи на константы.</p>
     <p>Практически во всех процедурных языках оператор присваивания вида</p>
     <p><code><emphasis>переменная</emphasis> = <emphasis>выражение</emphasis></code></p>
     <p>с незначительными вариациями работает приблизительно следующим образом:</p>
     <p>&#9633; сначала вычисляется присваиваемое выражение;</p>
     <p>&#9633; затем вычисляется адрес переменной;</p>
     <p>&#9633; затем значение, полученное на первом шаге, копируется в ячейки памяти, начиная с адреса, полученного на втором шаге присваивания.</p>
     <p>В XSLT нет оператора присваивания. Переменным и параметрам никогда не <emphasis>присваиваются</emphasis> значения в приведенном выше смысле, объявление переменной или параметра лишь <emphasis>связывает</emphasis> указанное имя со значением некоторого выражения. Иными словами, объявление переменной есть создание ассоциации между объектом и именем.</p>
     <p>В конце этой главы мы вернемся к неизменяемым переменным и попытаемся объяснить, почему их нельзя изменить — но прежде мы должны научиться их использовать.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:variable</emphasis></p>
     </title>
     <p>Синтаксис этого элемента в XSLT определен так:</p>
     <p><code>&lt;xsl:variable</code></p>
     <p><code> <strong>name</strong>="<emphasis>имя</emphasis>"</code></p>
     <p><code> select="<emphasis>выражение</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:variable&gt;</code></p>
     <p>Для объявления переменных в XSLT служит элемент <code>xsl:variable</code>, который может как присутствовать в теле шаблона, так и быть элементом верхнего уровня. Элемент <code>xsl:variable</code> связывает имя, указанное в обязательном атрибуте name, со значением выражения, указанного в атрибуте <code>select</code> или с деревом, которое является результатом выполнения шаблона, содержащегося в этом элементе. В том случае, если объявление переменной было произведено элементом верхнего уровня, переменная называется <emphasis>глобальной переменной</emphasis>. Переменные, определенные элементами <code>xsl:variable</code> в шаблонах (то есть не на верхнем уровне) называются <emphasis>локальными переменными</emphasis>.</p>
     <p>Таким образом, объявление переменной в XSLT происходит всего в два шага:</p>
     <p>&#9633; сначала вычисляется значение присваиваемого выражения;</p>
     <p>&#9633; затем полученное значение связывается с указанным именем.</p>
     <p>Значение присваиваемого выражения вычисляется в зависимости от того, как был определен элемент <code>xsl:variable</code>:</p>
     <p>&#9633; если в элементе <code>xsl:variable</code> определен атрибут <code>select</code>, то значением присваиваемого выражения будет результат вычисления выражения, указанного в этом атрибуте;</p>
     <p>&#9633; если атрибут <code>select</code> не определен, но сам элемент <code>xsl:variable</code> имеет дочерние узлы (иными словами, содержит шаблон), значением определяемой переменной будет результирующий фрагмент дерева, полученный в результате выполнения содержимого <code>xsl:variable</code>;</p>
     <p>&#9633; если атрибут <code>select</code> не определен и при этом сам элемент <code>xsl:variable</code> пуст, значением параметра по умолчанию будет пустая строка.</p>
     <p>Использовать значения, присвоенные переменным при инициализации, можно, указывая впереди имени переменной символ "<code>$</code>", например для переменной <code>x</code> — <code>$x</code>. В XPath-выражениях синтаксис обращения к переменным соответствует продукции <code>VariableReference</code>.</p>
     <p>Имя переменной соответствует синтаксическому правилу <code>QName</code>, иными словами, оно может иметь вид <code><emphasis>имя</emphasis></code> или <code><emphasis>префикс</emphasis>:<emphasis>имя</emphasis></code><emphasis>.</emphasis> Как правило, имена переменным даются без префиксов, однако в том случае, если префикс все же указан, переменная ассоциирует с некоторым объектом не простое, а расширенное имя. Соответственно, обращение к объекту должно будет производиться также посредством расширенного имени.</p>
    </section>
    <section>
     <title>
      <p>Область видимости переменных</p>
     </title>
     <p>Каждая из переменных имеет собственную <emphasis>область видимости</emphasis> (англ. scope) — область, в которой может быть использовано ее значение. Область видимости определяется следующим образом.</p>
     <p>&#9633; Областью видимости глобальной переменной является все преобразование, то есть значение переменной, объявленной элементом верхнего уровня, может быть использовано в преобразовании где угодно. К такой переменной можно обращаться даже до ее объявления, единственным ограничением является то, что переменная не должна определяться через собственное значение — явно или неявно.</p>
     <p>&#9633; Локальную переменную можно использовать только после ее объявления и только в том же родительском элементе, которому принадлежит объявляющий элемент <code>xsl:variable</code>. В терминах XPath область видимости локальной переменной будет определяться выражением</p>
     <p><code>following-sibling:node()/descendant-or-self:node()</code>.</p>
     <p>Для того чтобы до конца прояснить ситуацию, приведем несколько примеров.</p>
     <p>Предположим, что мы определяем переменную с именем <code>ID</code> и значением <code>4</code> следующим образом:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> ...</code></p>
     <p><code> &lt;xsl:variable name="ID" select="4"/&gt;</code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Несложно видеть, что здесь мы определили глобальную переменную, а значит, ее значение можно использовать в преобразовании в любом месте. Например, мы можем определить через нее другие глобальные переменные, либо использовать в шаблоне:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> ...</code></p>
     <p><code> &lt;xsl:variable name="leaf" select="//item[@id=$ID]"/&gt;</code></p>
     <p><code> &lt;xsl:variable name="ID" select="4"/&gt;</code></p>
     <p><code> &lt;xsl:variable name="path" select="$leaf/ancestor-or-self::item"/&gt;</code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Причем, как уже было сказано, глобальная переменная может быть использована и до объявления: в нашем случае переменная <code>leaf</code> определяется через переменную <code>ID</code>, a <code>path</code> — через <code>leaf</code>. Конечно же, не следует забывать и то правило, что переменные не могут объявляться посредством самих себя, явно или неявно. Очевидно, что объявление:</p>
     <p><code>&lt;xsl:variable name="ID" select="$ID - 1"/&gt;</code></p>
     <p>было бы некорректным ввиду явного использования переменной при собственном определении. Точно так же были бы некорректны определения:</p>
     <p><code>&lt;xsl:variable name="ID" select="$id — 1/&gt;</code></p>
     <p><code>&lt;xsl:variable name="id" select="$ID + 1"/&gt;</code></p>
     <p>поскольку переменная <code>ID</code> определяется через переменную <code>id</code>, которая определяется через переменную <code>ID</code> и так до бесконечности.</p>
     <p>Дела с локальными переменными обстоят чуть-чуть сложнее. Для того чтобы объяснить, что же такое область видимости, обратимся к следующему преобразованию.</p>
     <subtitle>Листинг 5.22. Преобразование, использующее переменные i, j, k и gt</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="... "&gt;</code></p>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:variable</code></p>
     <p><code>   name="i"</code></p>
     <p><code>   select="2"/&gt;</code></p>
     <p><code>  &lt;xsl:variable</code></p>
     <p><code>   name="j"</code></p>
     <p><code>   select="$i - 1"/&gt;</code></p>
     <p><code>  &lt;xsl:if test="$i &gt; $j"&gt;</code></p>
     <p><code>   &lt;xsl:variable name="k"&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="$i"/&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="$gt"/&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="$j"/&gt;</code></p>
     <p><code>   &lt;/xsl:variable&gt;</code></p>
     <p><code>   &lt;result&gt;</code></p>
     <p><code>    &lt;xsl:copy-of select="$k"/&gt;</code></p>
     <p><code>   &lt;/result&gt;</code></p>
     <p><code>  &lt;/xsl:if&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code> &lt;xsl:variable name="gt"&gt;</code></p>
     <p><code>  is greater than</code></p>
     <p><code> &lt;/xsl:variable&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>В этом преобразовании определены три локальные переменные — <code>i</code>, <code>j</code> и <code>k</code> и одна глобальная переменная — <code>gt</code>. На следующих четырех листингах мы выделим серой заливкой область видимости переменной (то есть область, где ее можно использовать), а само определение переменной отметим полужирным шрифтом.</p>
     <subtitle>Листинг 5.23. Области видимости переменных i, j, k и gt</subtitle>
     <p>Область видимости переменной <code>i</code>               Область видимости переменной <code>j</code></p>
     <p><code>&lt;xsl:stylesheet                  &lt;xsl:stylesheet</code></p>
     <p><code> version="1.0" xmlns:xsl="... "&gt;  version="1.0" xmlns:xsl="... "&gt;</code></p>
     <p><code> &lt;xsl:template match="/"&gt;         &lt;xsl:template match="/"&gt;</code></p>
     <p><code><strong>  &lt;xsl:variable name="i"</strong>           &lt;xsl:variable name="i"</code></p>
     <p><code><strong>   select="2"/&gt;</strong>                     select="2"/&gt;</code></p>
     <p><code>  &lt;xsl:variable name="j"           <strong>&lt;xsl:variable name="j"</strong></code></p>
     <p><code>   select="$i - 1"/&gt;                <strong>select="$i - 1"/&gt;</strong></code></p>
     <p><code>  &lt;xsl:if test="$i &gt; $j"&gt;          &lt;xsl:if test="$i &gt; $j"&gt;</code></p>
     <p><code>   &lt;xsl:variable name="k"&gt;          &lt;xsl:variable name="k"&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="$i"/&gt;      &lt;xsl:value-of select="$i"/&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="$gt"/&gt;     &lt;xsl:value-of select="$gt"/&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="$j"/&gt;      &lt;xsl:value-of select="$j"/&gt;</code></p>
     <p><code>   &lt;/xsl:variable&gt;                  &lt;/xsl:variable&gt;</code></p>
     <p><code>   &lt;result&gt;                         &lt;result&gt;</code></p>
     <p><code>    &lt;xsl:copy-of select="$k"/&gt;       &lt;xsl:copy-of select="$k"/&gt;</code></p>
     <p><code>   &lt;/result&gt;                        &lt;/result&gt;</code></p>
     <p><code>  &lt;/xsl:if&gt;                        &lt;/xsl:if&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;                  &lt;/xsl:template&gt;</code></p>
     <p><code> &lt;xsl:variable name="gt"&gt;         &lt;xsl:variable name="gt"&gt;</code></p>
     <p><code>  is greater than                  is greater than</code></p>
     <p><code> &lt;/xsl:variable&gt;                  &lt;/xsl:variable&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;                &lt;/xsl:stylesheet&gt;</code></p>
     <p>Область видимости переменной <code>k</code>               Область видимости переменной <code>gt</code></p>
     <p><code>&lt;xsl:stylesheet                  &lt;xsl:stylesheet</code></p>
     <p><code> version="1.0" xmlns:xsl="... "&gt;  version="1.0" xmlns:xsl="... "&gt;</code></p>
     <p><code> &lt;xsl:template match="/"&gt;         &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:variable name="i"           &lt;xsl:variable name="i"</code></p>
     <p><code>   select="2"/&gt;                     select="2"/&gt;</code></p>
     <p><code>  &lt;xsl:variable name="j"           &lt;xsl:variable name="j"</code></p>
     <p><code>   select="$i - 1"/&gt;                select="$i - 1"/&gt;</code></p>
     <p><code>  &lt;xsl:if test="$i &gt; $j"&gt;          &lt;xsl:if test="$i &gt; $j"&gt;</code></p>
     <p><code><strong>   &lt;xsl:variable name="k"&gt;</strong>          &lt;xsl:variable name="k"&gt;</code></p>
     <p><code><strong>    &lt;xsl:value-of select="$i"/&gt;</strong>      &lt;xsl:value-of select="$i"/&gt;</code></p>
     <p><code><strong>    &lt;xsl:value-of select="$gt"/&gt;</strong>     &lt;xsl:value-of select="$gt"/&gt;</code></p>
     <p><code><strong>    &lt;xsl:value-of select="$j"/&gt;</strong>      &lt;xsl:value-of select="$j"/&gt;</code></p>
     <p><code><strong>   &lt;/xsl:variable&gt;</strong>                  &lt;/xsl:variable&gt;</code></p>
     <p><code>   &lt;result&gt;                         &lt;result&gt;</code></p>
     <p><code>    &lt;xsl:copy-of select="$k"/&gt;       &lt;xsl:copy-of select="$k"/&gt;</code></p>
     <p><code>   &lt;/result&gt;                        &lt;/result&gt;</code></p>
     <p><code>  &lt;/xsl:if&gt;                        &lt;/xsl:if&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;                  &lt;/xsl:template&gt;</code></p>
     <p><code> &lt;xsl:variable name="gt"&gt;         <strong>&lt;xsl:variable name="gt"&gt;</strong></code></p>
     <p><code>  is greater than                 <strong> is greater than</strong></code></p>
     <p><code> &lt;/xsl:variable&gt;                  <strong>&lt;/xsl:variable&gt;</strong></code></p>
     <p><code>&lt;/xsl:stylesheet&gt;                &lt;/xsl:stylesheet&gt;</code></p>
     <p>В XSLT действует то же правило, что и во многих других языках программирования: нельзя дважды определять переменную с один и тем же именем. Однако и тут есть свои особенности.</p>
     <p>&#9633; Имена двух глобальных переменных могут совпадать в том и только том случае, когда они имеют разный порядок импорта. Например, если переменные с одинаковыми именами определены в разных преобразованиях, одно из них может быть импортировано. В этом случае переменная будет иметь значение, которое задано элементом <code>xsl:variable</code> со старшим порядком импорта.</p>
     <p>&#9633; Допускается совпадение имен локальной и глобальной переменных — в этом случае в области видимости локальной переменной будет использоваться локальное значение, в области видимости глобальной (но не локальной) — глобальное значение. Иными словами, локальные переменные "закрывают" значения глобальных.</p>
     <p>&#9633; Две локальные переменные могут иметь совпадающие имена в том и только том случае, если их области видимости не пересекаются.</p>
     <p>Первое правило мы уже упоминали, когда разбирали порядок импорта: тогда мы сказали, что переменные со старшим порядком импорта переопределяют переменные с младшим порядком импорта. Это довольно важное обстоятельство, поскольку оно добавляет некоторые интересные возможности, но при этом также может породить скрытые ошибки.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что в следующем преобразовании в шаблоне с именем <code>choice</code> мы генерируем два элемента <code>input</code>.</p>
     <subtitle>Листинг 5.24. Преобразование en.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:variable name="submit" select="'Submit'"/&gt;</code></p>
     <p><code> &lt;xsl:variable name="reset" select="'Reset'"/&gt;</code></p>
     <p><code> &lt;xsl:template name="choice"&gt;</code></p>
     <p><code>  &lt;input type="button" value="{$submit}"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#xA;&lt;/xsl: text&gt;</code></p>
     <p><code>  &lt;input type="reset" value="{$reset}"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:call-template name="choice"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результатом этого преобразования будет следующий фрагмент:</p>
     <p><code>&lt;input type="button" value="Submit"/&gt;</code></p>
     <p><code>&lt;input type="reset" value="Reset"/&gt;</code></p>
     <p>Для того чтобы перевести надписи на этих кнопках на другой язык достаточно просто переопределить переменные. Например, результатом выполнения следующего шаблона.</p>
     <subtitle>Листинг 5.25. Преобразование de.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> &lt;xsl:import href="en.xsl"/&gt;</code></p>
     <p><code> &lt;xsl:variable name="submit" select="'Senden'"/&gt;</code></p>
     <p><code> &lt;xsl:variable name="reset" select="'Loeschen'"/&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>будет тот же фрагмент, но уже на немецком языке:</p>
     <p><code>&lt;input type="button" value="Senden"/&gt;</code></p>
     <p><code>&lt;input type="reset" value="Loeschen"/&gt;</code></p>
     <p>С другой стороны, переопределение переменных может быть и опасным: в случае, если отдельные модули разрабатывались независимо, совпадение имен глобальных переменных может привести к ошибкам. Для того чтобы такое было в принципе исключено, имя переменной следует объявлять в определенном пространстве имен, например:</p>
     <p><code>&lt;xsl:variable name="app:href" select="..."/&gt;</code></p>
     <p><code>&lt;xsl:variable name="db:href" select="..."/&gt;</code></p>
     <p>В том случае, если префиксы <code>app</code> и <code>db</code> (которые, конечно же, должны быть объявлены) будут указывать на разные пространства имен, никакого конфликта между этими двумя переменными не будет.</p>
     <p>Возвращаясь к теме совпадений имен переменных, продемонстрируем "скрытие" локальной переменной значения глобальной:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:variable name="i" select="1"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;i equals &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="$i"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:variable name="i" select="$i + 1"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;i equals &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="$i"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результатом выполнения этого шаблона будет:</p>
     <p><code>i equals 1</code></p>
     <p><code>i equals 2</code></p>
     <p>Как можно видеть, объявление локальной переменной <code>i</code> "скрыло" значение глобальной переменной <code>i</code>. Более того, это преобразование любопытно еще и тем, что локальная переменная объявляется через глобальную — такое тоже допускается.</p>
     <p>Рассмотрим теперь случай двух локальных переменных. Попробуем объявить две локальные переменные — одну за другой в следующем шаблоне:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; </code></p>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:variable name="i" select="1"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;i equals &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="$i"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:variable name="i" select="2"/&gt;</code></p>
     <p><code><strong>  &lt;xsl:text&gt;i equals &lt;/xsl:text&gt;</strong></code></p>
     <p><code><strong>  &lt;xsl:value-of select="$i"/&gt;</strong></code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>В тексте этого шаблона мы выделили две области видимости двух переменных: серой заливкой — область видимости первой и полужирным шрифтом — область действия второй переменной. Вследствие того, что эти области пересекаются, шаблон будет некорректным — процессор выдаст сообщение об ошибке вида:</p>
     <p><code>Failed to compile style sheet</code></p>
     <p><code>At xsl:variable on line 9 of file stylesheet.xsl:</code></p>
     <p><code>Variable is already declared in this template</code></p>
     <p>Приведем теперь другое преобразование, в котором элементы <code>xsl:variable</code> принадлежат двум братским элементам:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;p&gt;</code></p>
     <p><code>   &lt;xsl:variable name="i" select="1"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;i equals &lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="$i"/&gt;</code></p>
     <p><code>  &lt;/p&gt;</code></p>
     <p><code>  &lt;p&gt;</code></p>
     <p><code>   &lt;xsl:variable name="i" select="2"/&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;i equals &lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="$i"/&gt;</code></p>
     <p><code>  &lt;/p&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>В этом случае никакого пересечения областей видимости нет, поэтому и ошибкой наличие в одном шаблоне двух локальных переменных с одинаковыми именами тоже не будет. Приведенное выше преобразование возвратит результат вида:</p>
     <p><code>&lt;p&gt;</code></p>
     <p><code> i equals 1</code></p>
     <p><code>&lt;/p&gt;</code></p>
     <p><code>&lt;p&gt;</code></p>
     <p><code> i equals 2</code></p>
     <p><code>&lt;/p&gt;</code></p>
    </section>
    <section>
     <title>
      <p>Использование переменных</p>
     </title>
     <p>Как правило, первой реакцией на известие о том, что переменные в XSLT нельзя изменять является реплика: "Да зачем они вообще тогда нужны?!".</p>
     <p>Претензия со стороны процедурного программирования вполне серьезна и обоснованна — изменяемые переменные являются большим подспорьем в сложных многошаговых вычислениях. Тем не менее, переменные, даже в том виде, в каком они присутствуют в XSLT, являются очень важным и полезным элементом языка. Ниже мы перечислим наиболее типичные случаи использования переменных.</p>
     <p>&#9633; Переменные могут содержать значения выражений, которые много раз используются в преобразовании. Это избавит процессор от необходимости пересчитывать выражение каждый раз по-новому.</p>
     <p>&#9633; Переменной может присваиваться результат преобразования, что позволяет манипулировать уже сгенерированными частями документа.</p>
     <p>&#9633; Переменные могут использоваться для более прозрачного доступа к внешним документам.</p>
     <subtitle>Примеры</subtitle>
     <p>Первый случай использования совершенно очевиден: если в преобразовании многократно используется какое-либо сложное для вычисления или просто громоздкое для записи выражение, переменная может служить для сохранения единожды вычисленного результата. Например, если мы много раз обращаемся ко множеству ссылок данного документа посредством выражения вида:</p>
     <p><code>//a[@href]</code></p>
     <p>гораздо удобней и экономней с точки зрения вычислительных ресурсов объявить переменную вида</p>
     <p><code>&lt;xsl:variable name="links" select="//a[@href]"/&gt;</code></p>
     <p>и использовать ее в преобразовании как <code>$a</code>. Фильтрующие выражения языка XPath (продукция <code>FilterExpr</code>) позволяют затем обращаться к узлам выбранного множества так же, как если бы мы работали с изначальным выражением. Например, <code>$a[1]</code> будет эквивалентно <code>//a[@href][1]</code>, a <code>$a/@href</code> — выражению <code>//a[@href]/@href</code>. При этом при обращении к <code>$a</code> процессор не будет заново искать все элементы a с атрибутом <code>href</code>, что, по всей вероятности, положительно скажется на производительности.</p>
     <p>Другой иллюстрацией этому же случаю использования переменной может быть следующая ситуация: в некоторых случаях выражения могут быть просты для вычисления, но слишком громоздки для записи. Гораздо элегантней один раз вычислить это громоздкое выражение, сохранить его в переменной и затем обращаться по короткому имени. Например, следующий элемент <code>xsl:variable</code> вычисляет и сохраняет в переменной <code>gv</code> длинную и громоздкую ссылку:</p>
     <p><code>&lt;xsl:variable name="gv"</code></p>
     <p><code> select="concat('http://host.com:8080/GeoView/GeoView.jsp?',</code></p>
     <p><code> 'Language=en&amp;amp;',</code></p>
     <p><code> 'SearchText=Select&amp;amp;',</code></p>
     <p><code> 'SearchTarget=mainFrame&amp;amp;',</code></p>
     <p><code> 'SearchURL=http://host.com:8080/servlet/upload')"/&gt;</code></p>
     <p>После такого определения применение этой ссылки в преобразовании становится удобным и лаконичным:</p>
     <p><code>&lt;а href="{$gv}" target="_blank"&gt;Launch GeoBrowser&lt;/a&gt;</code></p>
     <p>Второй типовой случай использования переменных также заметно облегчает создание выходящего дерева, делая этот процесс гибким и легко конфигурируемым. Примером формирования HTML-документа при помощи такого подхода может быть следующий шаблон:</p>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;html&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$head"/&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$body"/&gt;</code></p>
     <p><code> &lt;/html&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Достоинство этого подхода в том, что переменные, содержащие фрагменты деревьев как бы становятся модулями, блоками, из которых в итоге собирается результирующий документ.</p>
     <p>Более практичным применением возможности переменных содержать фрагменты деревьев является условное присвоение переменной значения. Представим себе следующий алгоритм:</p>
     <p><code>если</code></p>
     <p><code><emphasis> условие1</emphasis></code></p>
     <p><code>то</code></p>
     <p><code> присвоить <emphasis>переменной1 значение 1</emphasis></code></p>
     <p><code>иначе</code></p>
     <p><code> присвоить <emphasis>переменной1 значение2</emphasis></code></p>
     <p>Для процедурного языка с изменяемыми переменными это не проблема. На Java такой код выглядел бы элементарно:</p>
     <p><code><emphasis>переменная1</emphasis> = <emphasis>условие1</emphasis> ? <emphasis>значение1</emphasis> : <emphasis>значение2</emphasis>;</code></p>
     <p>или чуть в более длинном варианте:</p>
     <p><code>if (<emphasis>условие1</emphasis>)</code></p>
     <p><code><emphasis> переменная1</emphasis> = <emphasis>значение1</emphasis>;</code></p>
     <p><code>else</code></p>
     <p><code><emphasis> переменная1</emphasis> = <emphasis>значение2</emphasis>;</code></p>
     <p>Однако если бы в XSLT мы написали что-нибудь наподобие:</p>
     <p><code>&lt;xsl:choose&gt;</code></p>
     <p><code> &lt;xsl:when test="<emphasis>условие1</emphasis>"&gt;</code></p>
     <p><code>  &lt;xsl:variable name="<emphasis>переменная1</emphasis>" select="<emphasis>значение1</emphasis>"/&gt;</code></p>
     <p><code> &lt;/xsl:when&gt;</code></p>
     <p><code> &lt;xsl:otherwise&gt;</code></p>
     <p><code>  &lt;xsl:variable name="<emphasis>переменная1</emphasis>" select="<emphasis>значение2</emphasis>"/&gt;</code></p>
     <p><code> &lt;/xsl:otherwise&gt;</code></p>
     <p><code>&lt;/xsl:choose&gt;</code></p>
     <p>то требуемого результата все равно не достигли бы по той простой причине, что определенные нами переменные были бы доступны только в своей области видимости, которая заканчивается закрывающими тегами элементов <code>xsl:when</code> и <code>xsl:otherwise</code>. Правильный шаблон для решения этой задачи выглядит следующим образом:</p>
     <p><code>&lt;xsl:variable name="<emphasis>переменная1</emphasis>"&gt;</code></p>
     <p><code> &lt;xsl:choose&gt;</code></p>
     <p><code>  &lt;xsl:when test="<emphasis>условие1</emphasis>"&gt;</code></p>
     <p><code>   &lt;xsl:copy-of select="<emphasis>значение1</emphasis>"/&gt;</code></p>
     <p><code>  &lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:otherwise&gt;</code></p>
     <p><code>   &lt;xsl:copy-of select="<emphasis>значение2</emphasis>"/&gt;</code></p>
     <p><code>  &lt;/xsl:otherwise&gt;</code></p>
     <p><code> &lt;/xsl:choose&gt;</code></p>
     <p><code>&lt;xsl:variable&gt;</code></p>
     <p>Конечно, это не точно то же самое — на самом деле мы получаем не значение, а дерево, содержащее это значение, но для строковых и численных значений особой разницы нет: дерево будет вести себя точно так же, как число или строка. Для булевых значений и множеств узлов приходится изыскивать другие методы. Булевое значение можно выразить через условие, например:</p>
     <p><code>&lt;xsl:variable name="<emphasis>переменная</emphasis> 1"</code></p>
     <p><code> select="(<emphasis>значение</emphasis> 1 and <emphasis>условие1</emphasis>) or (<emphasis>значение2</emphasis> and not(<emphasis>условие2</emphasis>))"/&gt;</code></p>
     <p>Для множества узлов можно использовать предикаты и операции над множествами:</p>
     <p><code>&lt;xsl:variable name="<emphasis>переменная1</emphasis>"</code></p>
     <p><code> select="<emphasis>значение1</emphasis>[<emphasis>условие1</emphasis>] | <emphasis>значение2</emphasis>[not(<emphasis>условие2</emphasis>)]"/&gt;</code></p>
     <p>Заметим, что шаблон, содержащийся в элементе <code>xsl:variable</code>, может включать в себя такие элементы, как <code>xsl:call-template</code>, <code>xsl:apply-templates</code> и так далее. То есть переменной можно присвоить результат выполнения одного или нескольких шаблонов.</p>
     <p>Использование внешних документов в преобразовании, как правило, сопровождается громоздкими выражениями вида:</p>
     <p><code>document('http://www.xmlhost.com/docs/а.xml')/page/request/param</code></p>
     <p>и так далее.</p>
     <p>Для того чтобы при обращении к внешнему документу не использовать каждый раз функцию <code>document</code>, можно объявить переменную, которая будет содержать корневой узел этого документа, например:</p>
     <p><code>&lt;xsl:variable</code></p>
     <p><code> name="a.xml"</code></p>
     <p><code> select="document('http://www.xmlhost.com/docs/a.xml')"/&gt;</code></p>
     <p>После этого к документу <code>http://www.xmlhost.com/docs/a.xml</code> можно обращаться посредством переменной с именем <code>a.xml</code>, например:</p>
     <p><code>&lt;xsl:value-of select="$a.xml/page/request/param"/&gt;</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Параметры</p>
    </title>
    <section>
     <p>Параметры в XSLT практически полностью идентичны переменным. Они точно так же связывают с объектом имя, посредством которого в дальнейшем можно к этому объекту обращаться. Главным различием является то, что значение, данное параметру при инициализации, является всего лишь значением по умолчанию, которое может быть переопределено при вызове.</p>
     <p>До сих пор мы говорили о шаблонах, как о правилах, часто используя эти слова как синонимы. Попробуем теперь немного сменить угол зрения и представить их как <emphasis>функции</emphasis>, каждая из которых преобразует некоторый узел и возвращает фрагмент дерева в качестве результата. С этой точки зрения параметры шаблонов являются ни чем иным, как аргументами этих функций.</p>
     <p>Работа с параметрами обеспечивается двумя элементами — <code>xsl:param</code>, который объявляет в шаблоне новый параметр и <code>xsl:with-param</code>, который указывает значение параметра при вызове шаблона.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:param</emphasis></p>
     </title>
     <p>Синтаксически этот элемент задается как:</p>
     <p><code>&lt;xsl:param</code></p>
     <p><code> <strong>name</strong>="<emphasis>имя</emphasis>"</code></p>
     <p><code> select="<emphasis>выражение</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:param&gt;</code></p>
     <p>Элемент <code>xsl:template</code>, задающий в преобразовании шаблонное правило, может включать несколько элементов <code>xsl:param</code>, которые и будут определять параметры этого шаблона. Кроме этого, <code>xsl:param</code> может указываться в виде элемента верхнего уровня — в этом случае он будет определять глобальный параметр.</p>
     <p>Элемент <code>xsl:param</code> объявляет параметр с именем, которое задается обязательным атрибутом <code>name</code>. Имя параметра может иметь расширенную форму, например <code>"user:param"</code>, но чтобы не возиться с пространствами имен, на практике имена всегда дают простые — типа <code>"i"</code> или <code>"myParam"</code>.</p>
     <p>Параметру может быть присвоено значение по умолчанию — то есть значение, которое будет использоваться в случае, если параметра с таким именем шаблону передано не было. Значение по умолчанию вычисляется следующим образом:</p>
     <p>&#9633; если в элементе <code>xsl:param</code> определен атрибут <code>select</code>, то значением по умолчанию будет результат вычисления выражения, указанного в этом атрибуте;</p>
     <p>&#9633; если атрибут <code>select</code> не определен, но сам элемент <code>xsl:param</code> имеет дочерние узлы, то значением определяемого параметра по умолчанию будет фрагмент дерева, полученного в результате выполнения содержимого <code>xsl:param</code>;</p>
     <p>&#9633; если атрибут <code>select</code> не определен и при этом сам элемент <code>xsl:param</code> пуст, то значением параметра по умолчанию будет пустая строка.</p>
     <subtitle>Примеры</subtitle>
     <p>Элемент</p>
     <p><code>&lt;xsl:param name="x" select="2 * 2"/&gt;</code></p>
     <p>создаст параметр, значением которого по умолчанию будет <code>4</code>. Точно такой же эффект будет иметь элемент</p>
     <p><code>&lt;xsl:param name="x" select="2 * 2"&gt;</code></p>
     <p><code> &lt;xsl:value-of select="5 * 5/&gt;</code></p>
     <p><code>&lt;/xsl:param&gt;</code></p>
     <p>Его содержимое не будет приниматься в расчет, поскольку в <code>xsl:param</code> присутствует атрибут <code>select</code>. Если же убрать атрибут <code>select</code>:</p>
     <p><code>&lt;xsl:param name="x"&gt;</code></p>
     <p><code> &lt;xsl:value-of select="5 * 5/&gt;</code></p>
     <p><code>&lt;/xsl:param&gt;</code></p>
     <p>то значение параметра <code>x</code> по умолчанию действительно будет результатом вычисления его содержимого. Однако, вопреки довольно здравому разумению, этим значением не будет число <code>25</code> и даже не строка "<code>25</code>" и тем более не множество, состоящее из текстового узла со значением <code>25</code>. Значением параметра <code>x</code> по умолчанию будет результирующий фрагмент дерева, корень которого будет иметь единственный текстовый узел со значением "<code>25</code>" (рис. 5.3).</p>
     <image l:href="#img_46.png"/>
     <p><strong>Рис. 5.3</strong>. Фрагмент дерева, который будет значением параметра x по умолчанию</p>
     <p>Не стоит пугаться такой структуры в качестве значения параметра. То, что параметр <code>x</code> вдруг будет содержать дерево, ничуть не ограничивает его использование, ведь дерево при потребности может быть приведено к числу или к строке; к множеству узлов же не может быть приведен ни один тип данных.</p>
     <cite>
      <subtitle>Предупреждение</subtitle>
      <p>Напомним, что при приведении дерева к булевому типу, результатом всегда будет истина. Дерево всегда содержит как минимум корневой узел, и поэтому оно никогда не будет считаться пустым.</p>
     </cite>
     <p>Определение параметра вида:</p>
     <p><code>&lt;xsl:param name="x"/&gt;</code></p>
     <p>то есть когда в нем нет ни атрибута <code>select</code>, ни содержимого, присвоит параметру пустую строку, то есть будет эквивалентно</p>
     <p><code>&lt;xsl:param name="x" select="''"/&gt;</code></p>
     <p>Точно так же, как и в случае с переменными, значение заданного в шаблоне параметра можно использовать в выражениях, добавляя перед именем параметра префикс "<code>$</code>". К примеру, значение нашего параметра x может быть получено конструкцией вида <code>$x</code>.</p>
     <p>Для того чтобы передать в шаблон определенные значения параметров, элементы, которые вызывают этот шаблон, должны содержать один или несколько элементов <code>xsl:with-param</code>, который мы рассмотрим чуть ниже. Глобальные параметры, объявленные элементами <code>xsl:param</code> верхнего уровня, также могут быть переданы преобразованию, однако конкретный механизм реализации этой передачи целиком и полностью зависит от реализации конкретного процессора.</p>
    </section>
    <section>
     <title>
      <p>Область видимости параметров</p>
     </title>
     <p>Область видимости параметров определяется в точности так же, как область видимости переменных. Единственным, на что следует обратить здесь внимание — это то, что элементы <code>xsl:param</code>, определяемые в шаблонах, должны всегда быть его первыми дочерними элементами. Поэтому область видимости локальных параметров определяется несколько легче, чем область видимости локальных переменных: после определения параметр может использоваться в том шаблоне где угодно.</p>
     <p>Прямым следствием из этого является то, что один шаблон не может иметь двух параметров с одинаковыми именами, поскольку их области видимости будут обязательно пересекаться, ведь один из параметров в любом случае будет следовать за другим.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:with-param</emphasis></p>
     </title>
     <p>Синтаксис этого элемента выглядит следующим образом:</p>
     <p><code>&lt;xsl:with-param</code></p>
     <p><code> <strong>name</strong>="<emphasis>имя</emphasis>"</code></p>
     <p><code> select="<emphasis>выражение</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:with-param&gt;</code></p>
     <p>Как можно заметить, элемент <code>xsl:with-param</code> абсолютно идентичен элементу <code>xsl:param</code> (отличаются только их имена). Практически настолько же похоже и их действие: элемент <code>xsl:with-param</code> тоже связывает с именем параметра значение, и при выполнении шаблона это значение будет использоваться вместо значения параметра по умолчанию.</p>
     <p>Таким образом, значение параметра, заданного в шаблоне, выбирается в соответствии со следующими положениями:</p>
     <p>&#9633; если в элементе, который вызывает этот шаблон, присутствует элемент <code>xsl:with-param</code>, передающий значение этого параметра, в шаблоне будет использоваться переданное значение;</p>
     <p>&#9633; если в элементе, который вызывает этот шаблон, элемента <code>xsl:with-param</code>, с соответствующим именем нет, в качестве значения параметра будет использоваться значение по умолчанию.</p>
     <p>Элемент <code>xsl:with-param</code> может использоваться только в качестве дочернего элемента <code>xsl:apply-templates</code> и <code>xsl:call-template</code>.</p>
     <p>В качестве простого примера приведем шаблон, который выводит сокращение названия для недели по его номеру. Номер дня передается в шаблон параметром с именем <code>day-number</code>.</p>
     <subtitle>Листинг 5.26. Вывод названия дня недели по номеру</subtitle>
     <p><code>&lt;xsl:template name="day-name"&gt;</code></p>
     <p><code> &lt;xsl:param name="day-number" select="0"/&gt;</code></p>
     <p><code> &lt;xsl:choose&gt;</code></p>
     <p><code>  &lt;xsl:when test="$day-number=1"&gt;Mon&lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:when test="$day-number=2"&gt;Tue&lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:when test="$day-number=3"&gt;Wed&lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:when test="$day-number=4"&gt;Thu&lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:when test="$day-number=5"&gt;Fri&lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:when test="$day-number=6"&gt;Sat&lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:when test="$day-number=7"&gt;Sun&lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:otherwise&gt;Hmm...&lt;/xsl:otherwise&gt;</code></p>
     <p><code> &lt;/xsl:choose&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Результатом вызова:</p>
     <p><code>&lt;xsl:call-template name="day-name"&gt;</code></p>
     <p><code> &lt;xsl:with-param name="day-number" select="1"/&gt;</code></p>
     <p><code>&lt;/xsl:call-template&gt;</code></p>
     <p>будет текстовый узел "<code>Mon</code>". Рассмотрим теперь случай, когда параметра передано не было:</p>
     <p><code>&lt;xsl:call-template name="day-name"/&gt;</code></p>
     <p>Шаблон выведет задумчивое <code>Hmm...</code>, поскольку значение параметра <code>day-number</code> будет по умолчанию нулем (атрибут <code>select</code> имеет вид <code>select="0"</code>) и в операторе выбора <code>xsl:choose</code> сработает условие <code>xsl:otherwise</code>.</p>
     <p>Параметры могут быть использованы как в именованных, так и в неименованных шаблонах. Именованные шаблоны с параметрами ведут себя как самые настоящие функции — они могут вызываться с определенными параметрами вне зависимости от контекста, только чтобы выполнить какие-либо действия с переданными значениями. В случае обычных, неименованных шаблонов параметры могут предоставлять некую дополнительную информацию.</p>
     <subtitle>Пример</subtitle>
     <p>Представим себе описание меню в следующем формате:</p>
     <p><code>&lt;menu&gt;</code></p>
     <p><code> &lt;menuitem index="1" name="Home" href="home.htm"/&gt;</code></p>
     <p><code> &lt;menuitem index="2" name="News" href="news.htm"/&gt;</code></p>
     <p><code> &lt;menuitem index="3" name="Profile" href="profile.htm"/&gt;</code></p>
     <p><code> &lt;menuitem index="4" name="Contact" href="contact.htm"/&gt;</code></p>
     <p><code>&lt;/menu&gt;</code></p>
     <p>Для того чтобы при обработке особым образом выделять текущую страницу, определим в шаблоне параметр <code>current</code> и будем выводить название страницы в элементе <code>b</code> (от англ. bold — полужирный), если значение <code>current</code> равно индексу данного пункта меню; если текущая страница и индекс пункта меню не совпадают, то выводиться будет ссылка.</p>
     <p><code>&lt;xsl:template match="menuitem"&gt;</code></p>
     <p><code> &lt;xsl:param name="current" select="1"/&gt;</code></p>
     <p><code> &lt;xsl:choose&gt;</code></p>
     <p><code>  &lt;xsl:when test="$current=@index"&gt;</code></p>
     <p><code>   &lt;b&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="@name"/&gt;</code></p>
     <p><code>   &lt;/b&gt;</code></p>
     <p><code>  &lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:otherwise&gt;</code></p>
     <p><code>   &lt;a href="{@href}"&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="@name"/&gt;</code></p>
     <p><code>   &lt;/a&gt;</code></p>
     <p><code>  &lt;/xsl:otherwise&gt;</code></p>
     <p><code> &lt;/xsl:choose&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Результатом выполнения шаблона</p>
     <p><code>&lt;xsl:template match="menu"&gt;</code></p>
     <p><code> &lt;xsl:apply-templates select="menuitem"&gt;</code></p>
     <p><code>  &lt;xsl:with-param name="current" select="3"/&gt;</code></p>
     <p><code> &lt;/xsl:apply-templates&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>будет фрагмент меню вида</p>
     <p><code>&lt;a href="home.htm"&gt;Home&lt;/a&gt;</code></p>
     <p><code>&lt;a href="news.htm"&gt;News&lt;/a&gt;</code></p>
     <p><code>&lt;b&gt;Profile&lt;/b&gt;</code></p>
     <p><code>&lt;a href="contact.htm"&gt;Contact&lt;/a&gt;</code></p>
     <p>Попробуем теперь обработать элементы <code>menuitem</code>, не указывая значение параметра <code>current</code>:</p>
     <p><code>&lt;xsl:template match="menu"&gt;</code></p>
     <p><code> &lt;xsl:apply-templates select="menuitem"/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Результат будет получен в виде:</p>
     <p><code>&lt;b&gt;Home&lt;/b&gt;</code></p>
     <p><code>&lt;а href="news.htm"&gt;News&lt;/a&gt;</code></p>
     <p><code>&lt;а href="profile.htm"&gt;Profile&lt;/a&gt;</code></p>
     <p><code>&lt;a href="contact.htm"&gt;Contact&lt;/a&gt;</code></p>
     <p>Этот фрагмент выходящего документа легко объяснить. Вследствие определения:</p>
     <p><code>&lt;xsl:param name="current" select="1"/&gt;</code></p>
     <p>значением параметра <code>current</code> по умолчанию является <code>1</code>, и поэтому в меню был выбран пункт с индексом <code>1</code>.</p>
     <p>Мы упомянули, что значением параметра может быть дерево. Попробуем пояснить эту концепцию на примере генерации HTML-документа.</p>
     <p>Итак, предположим, что мы генерируем выходящий документ следующим именованным шаблоном:</p>
     <p><code>&lt;xsl:template name="html"&gt;</code></p>
     <p><code> &lt;xsl:param name="head"&gt;</code></p>
     <p><code>  &lt;head&gt;</code></p>
     <p><code>   &lt;title&gt;Title one&lt;/title&gt;</code></p>
     <p><code>  &lt;/head&gt;</code></p>
     <p><code> &lt;/xsl:param&gt;</code></p>
     <p><code> &lt;html&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$head"/&gt;</code></p>
     <p><code>   &lt;body&gt;</code></p>
     <p><code>    &lt;xsl:text&gt;content&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;/body&gt;</code></p>
     <p><code>  &lt;/html&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p>Параметр <code>head</code> по умолчанию будет содержать дерево, состоящее из элемента <code>head</code> и его дочернего элемента <code>title</code>, который содержит текст "<code>Title one</code>". Результат выполнения вызова</p>
     <p><code>&lt;xsl:call-template name="html"/&gt;</code></p>
     <p>мы можем видеть на следующем листинге:</p>
     <p><code>&lt;html&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;title&gt;Title one&lt;/title&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code> &lt;body&gt;content&lt;/body&gt;</code></p>
     <p><code>&lt;/html&gt;</code></p>
     <p>Выделенный фрагмент относится к части дерева, которая была создана копированием значения параметра <code>head</code>.</p>
     <p>Попробуем теперь передать в качестве параметра дерево, сгенерированное следующим шаблоном:</p>
     <p><code>&lt;xsl:template name="head"&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;title&gt;Title two&lt;/title&gt;</code></p>
     <p><code>  &lt;style type="text/css"&gt;</code></p>
     <p><code>   H1 {border-width: 1; border: solid; text-align: center}</code></p>
     <p><code>  &lt;/style&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Для того чтобы передать результат выполнения этого шаблона в виде значения параметра <code>head</code> именованному шаблону <code>head</code>, воспользуемся следующей конструкцией:</p>
     <p><code>&lt;xsl:call-template name="html"&gt;</code></p>
     <p><code> &lt;xsl:with-param name="head"&gt;</code></p>
     <p><code>  &lt;xsl:call-template name="head"/&gt;</code></p>
     <p><code> &lt;/xsl:with-param&gt;</code></p>
     <p><code>&lt;/xsl:call-template&gt;</code></p>
     <p>Выходящий документ будет получен в виде:</p>
     <p><code>&lt;html&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;title&gt;Title two&lt;/title&gt;</code></p>
     <p><code>  &lt;style type="text/css"&gt;</code></p>
     <p><code>   H1 {border-width: 1; border: solid; text-align: center}</code></p>
     <p><code>  &lt;/style&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code> &lt;body&gt;content&lt;/body&gt;</code></p>
     <p><code>&lt;/html&gt;</code></p>
     <p>Выделенный фрагмент, как и в предыдущем случае, соответствует части документа, полученной при копировании значения параметра <code>head</code>.</p>
     <p>Приведенные выше примеры демонстрируют, как можно собрать выходящий документ по кусочкам из фрагментов деревьев. При умелом использовании изложенные подходы позволяют добиться очень высокой гибкости и универсальности преобразований.</p>
    </section>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 6</p>
    <p>XPath-выражения</p>
   </title>
   <section>
    <title>
     <p>Выражения для XML-документов</p>
    </title>
    <section>
     <p>По мере распространения XML-технологий и развития смежных с ними областей стали выделяться не только задачи, которые хорошо подходят для решения с помощью XML, но и задачи, которые нужно решать при программировании самих XML-приложений. Одной из таких задач является обращение к определенным частям XML-документа. Например, если нам нужно получить из документа, скажем, цену продукта, которая находится в атрибуте <code>value</code> элемента <code>price</code>, принадлежащему элементу <code>product</code>, сделать это при помощи стандартных SAX- или DOM-интерфейсов было бы, мягко говоря, не очень удобно. И это еще простой пример. Бывают, действительно, сложные случаи, когда нужно выбрать узел определенного типа, который может находиться в нескольких местах в документе, да еще и должен обладать заданными свойствами.</p>
     <p>Для выполнения часто встречающихся задач такого рода был создан язык XPath, название которого расшифровывается, как XML Path — язык XML- путей. Главной задачей этого языка является адресация, или, по-другому, определение местоположения частей XML-документа. На практике это означает выбор в документе множества узлов, которые соответствуют определенным условиям расположения.</p>
     <p>Помимо главной задачи, в XPath имеются также дополнительные функции для работы со строками, числами, булевыми значениями и множествами узлов. Поэтому на самом деле XPath — это много больше, чем просто язык адресации. XPath-выражения, являющиеся самой общей конструкцией языка, могут возвращать значения любого из основных типов (кроме результирующего фрагмента дерева — этот тип может быть использован только в XSLT).</p>
     <p>В языке XSLT очень часто используются XPath-выражения — во всех вычислениях, выборках, сравнениях и так далее, XSLT опирается на XPath. В XPath есть арифметические и логические операции, а также библиотека базовых функций (которые, правда, дополняются некоторыми функциями XSLT). Можно с уверенностью заявить, что без знания языка XPath будет невозможно создавать реально функционирующие преобразования.</p>
     <p>К счастью, несмотря на все особенности, язык XPath настолько прост, что иногда его используют, даже не отдавая себе отчета, что это XPath. Скажем, когда мы пишем</p>
     <p><code>&lt;xsl:value-of select="page/number"/&gt;</code></p>
     <p>для того, чтобы вывести номер страницы, указанный в элементе <code>number</code>, который находится в элементе <code>page</code>, мы не задумываемся о том, что <code>page/number</code> — это на самом деле XPath-выражение, точнее, путь выборки.</p>
     <p>Более того, как мы позднее увидим, пути выборки настолько аналогичны путям в файловых системах, что использовать их можно, абсолютно не понимая семантики — чисто по аналогии. Однако, для построения сложных выражений нужно хорошо понимать, что стоит за тем или иным синтаксисом.</p>
     <p>Для того чтобы четко определить все грамматические конструкции этого языка, мы опять будем применять расширенные формы Бэкуса-Наура, по возможности раскрывая и упрощая их. Чтобы не путать номера XPath-продукций с другими синтаксическими правилами, мы будем использовать в номере префикс <code>XP</code>, например:</p>
     <p><code>[ХР1] LocationPath ::= RelativeLocationPath</code></p>
     <p><code>                       | AbsoluteLocationPath</code></p>
     <p>В синтаксических правилах, которые мы будем приводить, используются три нетерминала <code>NCName</code>, <code>QName</code> и <code>S</code>, которые мы уже рассматривали ранее. <code>NCName</code> и <code>QName</code> относятся к расширенным именам, a <code>S</code> обозначает пробельное пространство.</p>
     <p>XPath-выражения являются статическими компонентами языка XSLT. Выражения нельзя создавать во время выполнения преобразования, иначе говоря, функции высшего порядка (функции, результатом вычисления которых также являются функции) в XSLT отсутствуют. Нельзя сделать, например, следующее:</p>
     <p><code>&lt;!-- Создаем XPath-выражение --&gt;</code></p>
     <p><code>&lt;xsl:variable name="expr" select="concat(.'page/number[', id, ']')"/&gt;</code></p>
     <p><code>&lt;!-- Вычисляем динамически созданное XPath-выражение --&gt;</code></p>
     <p><code>&lt;xsl:value-of select="eval($expr)"/&gt;</code></p>
     <p>В XPath отсутствует функция <code>eval</code>, которая вычисляла бы значение XPath-выражения, переданного ей в виде строки.</p>
     <cite>
      <subtitle>Примечание</subtitle>
      <p>Функция <code>eval</code> присутствует в некоторых XSLT-процессорах, например в Saxon в виде расширения <code>saxon:evaluate</code>.</p>
     </cite>
    </section>
    <section>
     <title>
      <p>Контекст вычисления выражений</p>
     </title>
     <p>Как мы видели ранее, в XSLT одно и то же правило преобразования может применяться к различным частям XML-документа и в каждом случае результат будет разным — в зависимости от того, как выглядит обрабатываемый фрагмент. Подобно этому, XPath-выражения тоже вычисляются в зависимости от контекста. Контекст показывает, какой узел в данный момент обрабатывается преобразованием, какова позиция этого узла в обрабатываемом множестве, сколько всего узлов в этом множестве, какие переменные доступны и какие значения они имеют, какие функции могут быть вызваны и, наконец, какие пространства имен объявлены. Иными словами, контекст — это полное описание положения, окружения или ситуации, в которой происходит вычисление.</p>
     <p>Если давать строгое определение в соответствии со спецификацией XPath, то контекст составляют следующие части.</p>
     <p>&#9633; Контекстный узел — узел, который обрабатывается в текущий момент. Контекстный узел оказывает влияние на вычисление многих выражений — например, относительные пути выборки будут отсчитываться относительно контекстного узла. В большинстве случаев контекстный узел совпадает с текущим узлом преобразования, однако во время вычисления самих XPath-выражений, они могут различаться.</p>
     <p>&#9633; Целое положительное число, показывающее <emphasis>размер</emphasis> контекста — количество узлов во множестве, которое обрабатывается в данный момент. Это число может быть получено функцией <code>last</code>.</p>
     <p>&#9633; Целое положительное число, показывающее <emphasis>позицию</emphasis> контекстного узла в контексте вычисления выражения — то есть порядковый номер узла в текущем множестве преобразования, которое было соответствующим образом упорядочено. Это число может быть получено функцией <code>position</code>. Позиция первого узла равна 1, позиция последнего — значению функции <code>last</code>.</p>
     <p>&#9633; Множество связанных переменных. Это множество есть множество пар вида "имя-значение", в котором имя переменной связывается со значением, присвоенным ей. Переменные не определяются в самом XPath, для этого следует использовать элемент языка XSLT <code>xsl:variable</code>. Переменные могут содержать как значения любого из четырех базовых типов XPath (булевый тип, строка, число, множество узлов), так и значения других типов. Например, в XSLT значению переменной можно присвоить результирующий фрагмент дерева, а расширения языка так и вовсе могут присваивать переменным объекты любых типов. Другое дело, что XPath-выражения в соответствии со стандартом не должны непосредственно работать другими типами объектов, кроме своих четырех базовых. Механизмы расширения XPath и XSLT будут рассматриваться <emphasis>в главе 10</emphasis>.</p>
     <p>В отношении переменных важно понимать, что это не более чем объекты, доступ к которым можно получить по имени.</p>
     <p>&#9633; Библиотека функций, состоящая из множества функций, которые могут быть выполнены процессором. В XPath определяется базовая библиотека, функции которой должны быть реализованы в процессоре, однако эта библиотека может быть расширена. Например, XSLT определяет несколько дополнительных функций, которые также должны поддерживаться всеми XSLT-процессорами. Более того, в преобразованиях можно использовать и собственные функции расширения. Таким образом, библиотека функций контекста состоит из всех функций, доступных при вычислении выражения.</p>
     <p>&#9633; Множество объявлений пространств имен. Это множество связывает префиксы пространств имен с уникальными идентификаторами ресурсов (URI), которые им соответствуют.</p>
    </section>
    <section>
     <title>
      <p>Пути выборки</p>
     </title>
     <section>
      <p>Одна из важнейших функций XPath — это выбор множеств узлов в документе. Особый вид XPath-выражений, называемый <emphasis>путями выборки</emphasis> позволяет выбирать в документе множества узлов в соответствии с самыми разнообразными критериями — по расположению, по типу, а также по выполнению одного или нескольких логических условий, называемых <emphasis>предикатами</emphasis>.</p>
      <p>Синтаксис путей выборки во многом похож на синтаксис путей в файловых системах — сказывается то обстоятельство, что иерархическая структура данных в XML-документах очень близка к древовидной структуре каталогов. В качестве примера сравним дерево каталогов (рис. 6.1) с таким же деревом, записанным в виде XML-документа (листинг 6.1).</p>
      <image l:href="#img_47.png"/>
      <p><strong>Рис. 6.1</strong>. Древовидная структура каталогов</p>
      <subtitle>Листинг 6.1 XML-документ</subtitle>
      <p><code>&lt;Java&gt;</code></p>
      <p><code> &lt;Doc&gt;</code></p>
      <p><code>  &lt;ClassGenerator/&gt;</code></p>
      <p><code>  &lt;SchemaProcessor/&gt;</code></p>
      <p><code>  &lt;XMLParser&gt;</code></p>
      <p><code>   &lt;images/&gt;</code></p>
      <p><code>  &lt;/XMLParser&gt;</code></p>
      <p><code> &lt;/Doc&gt;</code></p>
      <p><code> &lt;Lib&gt;</code></p>
      <p><code>  &lt;Servlets&gt;</code></p>
      <p><code>   &lt;classes/&gt;</code></p>
      <p><code>   &lt;doc&gt;</code></p>
      <p><code>    &lt;images/&gt;</code></p>
      <p><code>   &lt;/doc&gt;</code></p>
      <p><code>   &lt;lib/&gt;</code></p>
      <p><code>   &lt;src/&gt;</code></p>
      <p><code>  &lt;/Servlets&gt;</code></p>
      <p><code> &lt;/Lib&gt;</code></p>
      <p><code>&lt;/Java&gt;</code></p>
      <p>В этой иерархии каталогов путь "<code>/</code>" соответствует корневому каталогу, путь "<code>/Java/Lib/Servlets/src</code>" — каталогу <code>src</code>. Путь из каталога <code>Java</code> в каталог <code>XMLParser</code> имеет вид "<code>Doc/XMLParser</code>", а путь из каталога <code>Lib</code> в каталог <code>images</code> — "<code>Servlets/doc/images</code>".</p>
      <p>Перемещаться в системе каталогов можно не только вглубь, но также на верхние уровни при помощи пути "<code>..</code>", который осуществляет переход в родительский каталог. К примеру, для того, чтобы перейти из каталога "<code>/Java/Lib/Servlets/doc/images</code>" в каталог "<code>/Java/Doc/XMLParser/images</code>", можно воспользоваться путем "<code>../../../../Doc/XMLParser/images</code>".</p>
      <p>Пути файловой системы, приведенные выше, в точности совпадают с путями выборки, которые мы бы использовали для обращения к соответствующим частям ХМL-документа. Путь выборки "<code>/</code>" содержит корневой узел, путь выборки "<code>/java/Lib/Servlets/src</code>" — элемент <code>src</code>, принадлежащий элементу <code>Servlets</code>, который принадлежит элементу <code>Lib</code>, который принадлежит элементу <code>Java</code>, находящемуся в корне элемента. Путь выборки "<code>Doc/XMLParser</code>" выбирает элементы <code>XMLParser</code>, находящиеся в элементах <code>Doc</code>, принадлежащих контекстному узлу.</p>
      <p>В XPath существует два вида путей выборки — относительные и абсолютные пути. Абсолютный путь (например, "<code>/Java/Doc/ClassGenerator</code>") начинается ведущей косой чертой ("<code>/</code>") и отсчитывается от корневого узла документа, в то время как относительный путь (например, "<code>Doc/XMLParser</code>") отсчитывается от контекстного узла.</p>
      <p>И абсолютный, и относительный пути выборки состоят из нескольких <emphasis>шагов выборки</emphasis>, разделенных косой чертой ("<code>/</code>"). Вычисление пути выборки производится последовательным выполнением составляющих его шагов. В случае абсолютного пути выборки, первый шаг выполняется относительно корневого узла дерева, в случае относительного пути — относительно контекстного узла контекста.</p>
      <subtitle>Пример</subtitle>
      <p>В файловой системе выполнить путь вида <code>Lib/Servlets/classes</code> означает:</p>
      <p>&#9633; из текущего каталога перейти в подкаталог <code>Lib</code>;</p>
      <p>&#9633; затем перейти в подкаталог <code>Servlets</code>;</p>
      <p>&#9633; и наконец — в подкаталог <code>classes</code>.</p>
      <p>Для того чтобы выполнить такой же путь выборки в XML-документе, нужно</p>
      <p>сделать следующее:</p>
      <p>&#9633; выполнить первый шаг, "<code>Lib</code>" — выбрать все дочерние элементы контекстного узла, имеющие имя "<code>Lib</code>";</p>
      <p>&#9633; затем выполнить шаг "<code>Servlets</code>" — для каждого из узлов, выбранных предыдущим шагом, выбрать дочерние элементы "<code>Servlets</code>" и объединить их в одно множество;</p>
      <p>&#9633; наконец, выполнить шаг "<code>classes</code>" — для каждого из узлов, выбранных на предыдущем этапе, выбрать дочерние элементы <code>classes</code> и объединить их в одно множество.</p>
      <p>Опишем более подробно алгоритм вычисления пути выборки:</p>
      <p>&#9633; если путь выборки является абсолютным путем, то первый его шаг выполняется в контексте корневого узла документа, который содержит контекстный узел;</p>
      <p>&#9633; если путь выборки является относительным путем, то первый его шаг выполняется относительно контекстного узла;</p>
      <p>&#9633; каждый последующий шаг пути выборки выполняется для каждого узла множества, выбранного на предыдущем шаге, — таким образом выбирается несколько множеств, которые затем объединяются — это и есть множество, выбранное на текущем шаге.</p>
      <subtitle>Пример</subtitle>
      <p>Рассмотрим процесс выполнения пути выборки <code>/A/B/D/G/I</code> в следующем документе:</p>
      <p><code>&lt;A&gt;</code></p>
      <p><code> &lt;B/&gt;</code></p>
      <p><code> &lt;B&gt;</code></p>
      <p><code>  &lt;D&gt;</code></p>
      <p><code>   &lt;G/&gt;</code></p>
      <p><code>  &lt;/D&gt;</code></p>
      <p><code>  &lt;G&gt;</code></p>
      <p><code>   &lt;I/&gt;</code></p>
      <p><code>  &lt;/G&gt;</code></p>
      <p><code>  &lt;G/&gt;</code></p>
      <p><code>  &lt;G&gt;</code></p>
      <p><code>   &lt;I/&gt;</code></p>
      <p><code>   &lt;I/&gt;</code></p>
      <p><code>  &lt;/G&gt;</code></p>
      <p><code>  &lt;D/&gt;</code></p>
      <p><code>  &lt;E/&gt;</code></p>
      <p><code>  &lt;F&gt;</code></p>
      <p><code>   &lt;H/&gt;</code></p>
      <p><code>  &lt;/F&gt;</code></p>
      <p><code> &lt;/B&gt;</code></p>
      <p><code> &lt;C/&gt;</code></p>
      <p><code>&lt;/A&gt;</code></p>
      <p>На рис. 6.2 показано логическое дерево, соответствующее этому документу.</p>
      <image l:href="#img_48.png"/>
      <p><strong>Рис. 6.2</strong>. Логическое дерево, представляющее XML-документ</p>
      <p>Для того чтобы лучше понять процесс выбора, проследим по шагам за тем, как будет обрабатываться этот путь.</p>
      <p>1. Данный путь (рис. 6.3) является абсолютным путем выборки, значит, он должен выполняться, начиная от корневого узла.</p>
      <image l:href="#img_49.png"/>
      <p><strong>Рис. 6.3</strong>. Начальный узел пути выборки</p>
      <p>2. Первым шагом пути (рис. 6.4) является шаг <code>A</code>, который выбирает все дочерние элементы <code>A</code> контекстного узла.</p>
      <image l:href="#img_50.png"/>
      <p><strong>Рис. 6.4</strong>. Первый шаг</p>
      <p>3. Вторым шагом пути (рис. 6.5) является шаг <code>B</code>, который выбирает все дочерние элементы в узлов множества, выбранного на предыдущем шаге. Так как тогда был выбран единственный узел <code>A</code>, текущий шаг выберет два дочерних элемента в этого узла.</p>
      <image l:href="#img_51.png"/>
      <p><strong>Рис. 6.5</strong>. Второй шаг</p>
      <p>4. На очередном шаге (рис. 6.6) мы выбираем дочерние элементы <code>D</code>. Как можно заметить, один из элементов в, выбранных на прошлом этапе, не содержит таких элементов, значит, в этом случае, шаг выборки возвратит пустое множество. Второй элемент <code>B</code> имеет три дочерних элемента <code>B</code>. В итоге мы получим множество, состоящее из трех элементов <code>D</code>.</p>
      <image l:href="#img_52.png"/>
      <p><strong>Рис. 6.6</strong>. Третий шаг</p>
      <p>5. Следующий шаг, <code>G</code> (рис. 6.7) выбирает дочерние элементы <code>G</code>. Первый элемент <code>D</code>, выбранный на прошлом шаге, включает один элемент <code>G</code>, второй не имеет таких элементов, третий — имеет три дочерних элемента <code>G</code>. Таким образом, на данном шаге будет выбрано множество, состоящее из четырех элементов <code>G</code>.</p>
      <image l:href="#img_53.png"/>
      <p><strong>Рис. 6.7</strong>. Четвертый шаг</p>
      <p>6. Последний шаг, <code>I</code> (рис. 6.8) выбирает для каждого из четырех элементов <code>G</code> дочерние элементы <code>I</code>. Первый элемент <code>G</code> не имеет дочерних элементов, второй имеет один дочерний элемент <code>I</code>, третий не содержит элементов и четвертый содержит два элемента <code>I</code>. В итоге результатом выполнения этого шага будет множество, состоящее из 3 элементов <code>I</code>.</p>
      <image l:href="#img_54.png"/>
      <p><strong>Рис. 6.8</strong>. Пятый шаг</p>
      <p>Пути выборки соответствует продукция <code>LocationPath</code>, которая записывается следующим образом:</p>
      <p><code>[XP1] LocationPath ::= RelativeLocationPath</code></p>
      <p><code>                       | AbsoluteLocationPath</code></p>
      <p>Эта продукция означает, что путь выборки может быть либо относительным путем, которому соответствует продукция <code>RelativeLocationPath</code>, либо абсолютным путем с продукцией <code>AbsoluteLocationPath</code>:</p>
      <p><code>[XP2] AbsoluteLocationPath ::= '/' RelativeLocationPath?</code></p>
      <p><code>                               | AbbreviatedAbsoluteLocationPath</code></p>
      <p><code>[XP3] RelativeLocationPath ::= Step</code></p>
      <p><code>                               | RelativeLocationPath '/' Step</code></p>
      <p><code>                               | AbbreviatedRelativeLocationPath</code></p>
      <p>Упростим <code>LocationPath</code>, раскрыв дочерние продукции:</p>
      <p><code>LocationPath ::= '/'</code></p>
      <p><code>                 | RelativeLocationPath</code></p>
      <p><code>                 | '/' RelativeLocationPath</code></p>
      <p><code>                 | '//' RelativeLocationPath</code></p>
      <p>Таким образом, путь выборки имеет четыре основных варианта, которые мы сейчас и разберем:</p>
      <p>&#9633; путь <code>'/'</code> — используется для обращения к корневому узлу дерева;</p>
      <p>&#9633; путь вида <code>RelativeLocationPath</code> — есть относительный путь выборки;</p>
      <p>&#9633; путь вида <code>'/' RelativeLocationPath</code> — это абсолютный путь выборки, то есть относительный путь, которому предшествует <code>'/'</code>;</p>
      <p>&#9633; путь вида <code>'//' RelativeLocationPath</code> — это абсолютный путь выборки, в котором использован сокращенный синтаксис. Путь такого вида эквивалентен пути вида <code>'/descendant-or-self:node()/' RelativeLocationPath</code>. Первой его частью является путь <code>'/descendant-or-self:node()'</code>, который выбирает все узлы документа (кроме узлов атрибутов и пространств имен).</p>
      <p>Главной деталью <code>LocationPath</code> является относительный путь выборки, продукция которого также может быть переписана в раскрытом и упрощенном виде:</p>
      <p><code>RelativeLocationPath ::= Step</code></p>
      <p><code>                         | RelativeLocationPath '/' Step</code></p>
      <p><code>                         | RelativeLocationPath '//' Step</code></p>
      <p>В соответствии с этой продукцией, относительный путь выборки состоит из одного или нескольких шагов выборки, разделенных <code>'/'</code> или <code>'//'</code>. Как уже отмечалось ранее, конструкция <code>'//'</code> есть сокращенный вариант от <code>'/descendant-or-self::node()/'</code>. Таким образом, главным элементом пути выборки является шаг выборки.</p>
      <subtitle>Примеры:</subtitle>
      <p>&#9633; <code>/</code> — выберет корневой узел документа;</p>
      <p>&#9633; <code>/а</code> — выберет элемент <code>а</code>, находящийся в корне документа;</p>
      <p>&#9633; <code>//а</code> — выберет множество всех элементов <code>а</code> текущего документа.</p>
     </section>
     <section>
      <title>
       <p>Шаги выборки</p>
      </title>
      <p>Любой путь — это последовательность шагов, путь выборки — это последовательности шагов выборки, которые нужно совершить, чтобы получить искомый результат. Каждый шаг выборки состоит из трех частей.</p>
      <p>&#9633; Первая часть называется <emphasis>осью навигации</emphasis> — она показывает направление, в котором будет производиться выбор на данном шаге. Например, можно выбирать дочерние узлы, узлы-атрибуты или родительские узлы контекстного узла (<emphasis>см. также раздел "Оси навигации" данной главы</emphasis>).</p>
      <p>&#9633; Второй частью шага выборки является <emphasis>тест узла</emphasis>. Тест узла показывает, узлы какого типа или с какими именами должны быть выбраны на данном шаге.</p>
      <p>&#9633; Третья часть шага выборки — это один или несколько <emphasis>предикатов</emphasis>, логических выражений, которые фильтруют множество узлов, выбранных на данном шаге.</p>
      <p>Проще говоря, ось навигации отвечает на вопрос "куда двигаемся?", тест узла — на вопрос "какие узлы ищем?", а предикаты — на вопрос "какими свойствами должны обладать выбираемые узлы?".</p>
      <subtitle>Пример</subtitle>
      <p>Шаг выборки <code>attribute::href[. = 'http://www.xsltdev.ru']</code> состоит из оси навигации <code>attribute</code>, которая выбирает атрибуты данного узла, теста узла <code>href</code>, который выбирает узлы с именем <code>href</code> и нулевым пространством имен, и предиката <code>[. = 'http://www.xsitdev.ru']</code>, который оставляет в выбираемом множестве те узлы, текстовое значение которых равно <code>"http://www.xsltdev.ru"</code>. Таким образом, на этом шаге будут выбраны все атрибуты <code>href</code> текущего узла, имеющие значение <code>"http://www.xsltdev.ru"</code>.</p>
      <p>Шаг выборки соответствует EBNF-продукции <code>Step</code>, а первая его часть, ось навигации — продукции <code>AxisSpecifier</code>:</p>
      <p><code>[XP4] Step          ::= AxisSpecifier NodeTest Predicate*</code></p>
      <p><code>                        | AbbreviatedStep</code></p>
      <p><code>[XP5] AxisSpecifier ::= AxisName '::'</code></p>
      <p><code>                        | AbbreviatedAxisSpecifier</code></p>
      <p>Продукцию <code>Step</code> можно значительно упростить и записать в следующем виде:</p>
      <p><code>Step ::= '.'</code></p>
      <p><code>         | '..'</code></p>
      <p><code>         | NodeTest Predicate*</code></p>
      <p><code>         | '@' NodeTest Predicate*</code></p>
      <p><code>         | AxisName '::' NodeTest Predicate*</code></p>
      <p>В первых четырех случаях шаг выборки записан при помощи сокращенного синтаксиса, а именно:</p>
      <p>&#9633; шаг выборки <code>'.'</code> эквивалентен шагу <code>self::node()</code>, который выбирает контекстный узел;</p>
      <p>&#9633; шаг выборки <code>'..'</code> эквивалентен шагу <code>parent::node()</code>, который выбирает родительский узел контекстного узла;</p>
      <p>&#9633; шаг выборки вида <code>NodeTest Predicate*</code> эквивалентен шагу выборки вида <code>'child::' NodeTest Predicate*</code>, который выбирает узлы из множества дочерних узлов контекстного узла;</p>
      <p>&#9633; шаг выборки вида <code>'@' NodeTest Predicate*</code> эквивалентен шагу выборки вида <code>'attribute::' NodeTest Predicate*</code>, который выбирает узлы из множества атрибутов контекстного узла.</p>
      <p>Последний случай, <code>AxisName ' ::' NodeTest Predicate*</code> представляет полный синтаксис шага выборки: сначала идет наименование оси и тест узла, разделенные двумя двоеточиями (<code>"::"</code>), затем несколько предикатов.</p>
     </section>
     <section>
      <title>
       <p>Оси навигации</p>
      </title>
      <p>Важной особенностью путей выборки является то, что шаги в них могут совершаться не в двух направлениях (вглубь и на верхний уровень), как в случае с файловыми системами, а во многих других. При выполнении шага выборки из некоторого контекстного узла направление движения по логическому дереву документа задается первой частью этого шага, осью навигации. В XPath имеется 13 осей навигации, а именно:</p>
      <p>&#9633; <code>self</code> — эта ось навигации содержит только сам контекстный узел;</p>
      <p>&#9633; <code>child</code> — содержит все дочерние узлы контекстного узла; не содержит узлов атрибутов и пространств имен;</p>
      <p>&#9633; <code>parent</code> — содержит родительский узел контекстного узла, если он есть;</p>
      <p>&#9633; <code>descendant</code> — содержит все узлы-потомки контекстного узла; не содержит узлов атрибутов и пространств имен;</p>
      <p>&#9633; <code>descendant-or-self</code> — содержит контекстный узел, а также всех его потомков; не содержит узлов атрибутов и пространств имен;</p>
      <p>&#9633; <code>ancestor</code> — содержит узлы, которые являются предками контекстного узла;</p>
      <p>&#9633; <code>ancestor-or-self</code> — содержит контекстный узел, а также всех его предков;</p>
      <p>&#9633; <code>following</code> — содержит узлы, следующие за контекстным узлом, в порядке просмотра документа; не содержит его потомков; не содержит узлов атрибутов и пространств имен;</p>
      <p>&#9633; <code>following-sibling</code> — содержит братские узлы контекстного узла, которые следуют за ним в порядке просмотра документа; если контекстный узел является атрибутом или узлом пространства имен, то <code>following-sibling</code> не будет содержать никаких узлов;</p>
      <p>&#9633; <code>preceding</code> — содержит узлы, предшествующие контекстному узлу в порядке просмотра документа; не содержит его предков; не содержит узлов атрибутов и пространств имен;</p>
      <p>&#9633; <code>preceding-sibling</code> — содержит братские узлы контекстного узла, которые предшествуют ему в порядке просмотра документа; в случае, если контекстный узел является узлом атрибута или пространства имен, <code>preceding-sibling</code> не будет содержать никаких узлов;</p>
      <p>&#9633; <code>attribute</code> — содержит атрибуты контекстного узла, если он является элементом; в противном случае не содержит ничего;</p>
      <p>&#9633; <code>namespace</code> — содержит узлы пространств имен контекстного узла, если он является элементом; в противном случае не содержит ничего.</p>
      <p>Шаг выборки вида <code><emphasis>ось</emphasis>::node()</code> будет содержать все узлы, принадлежащие этой оси. Например, <code>attribute::node()</code> (или, сокращенно <code>@node()</code>) будет содержать все атрибуты текущего узла.</p>
      <p>Для того чтобы понять, как оси навигации расположены в дереве документа, обратимся к рис. 6.9.</p>
      <image l:href="#img_55.png"/>
      <p><strong>Рис. 6.9</strong>. Расположение в документе осей навигации</p>
      <p>На этом рисунке не показано расположение осей атрибутов и пространств имен вследствие того, что эти оси не имеют в документе физического направления.</p>
      <p>Каждая ось имеет <emphasis>базовый тип</emphasis> узла — это тип узла, который считается "главным" в этом направлении навигации. Этот тип устанавливается следующим образом: если ось может содержать узлы элементов, ее базовым типом является элемент, в противном случае базовым типом оси навигации является тип узлов, которые она может содержать.</p>
      <p>Кроме того, каждой оси соответствует прямое или обратное направление просмотра, которое определяет, в каком порядке будут перебираться узлы, выбираемые этой осью. Оси навигации, которые содержат узлы, предшествующие в порядке просмотра документа контекстному узлу, имеют обратное направление просмотра, все остальные оси просматриваются в прямом порядке. Поскольку оси как <code>self</code> и <code>parent</code> не могут содержать более одного узла, порядок просмотра для них не играет никакого значения.</p>
      <p>Базовые типы узлов и направление их просмотра можно свести в одну таблицу (табл. 6.1).</p>
      <empty-line/>
      <p><emphasis><strong>Таблица 6.1</strong>. Базовые типы узлов и направления просмотра осей навигации</emphasis></p>
      <table>
       <tr>
        <th align="left">Ось навигации</th>
        <th align="left">Базовый тип узла</th>
        <th align="left">Направление просмотра</th>
       </tr>
       <tr>
        <td align="left"><code>self</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Нет</td>
       </tr>
       <tr>
        <td align="left"><code>child</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Прямое</td>
       </tr>
       <tr>
        <td align="left"><code>parent</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Нет</td>
       </tr>
       <tr>
        <td align="left"><code>descendant</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Прямое</td>
       </tr>
       <tr>
        <td align="left"><code>descendant-or-self</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Прямое</td>
       </tr>
       <tr>
        <td align="left"><code>ancestor</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Обратное</td>
       </tr>
       <tr>
        <td align="left"><code>ancestor-or-self</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Обратное</td>
       </tr>
       <tr>
        <td align="left"><code>following</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Прямое</td>
       </tr>
       <tr>
        <td align="left"><code>following-sibling</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Прямое</td>
       </tr>
       <tr>
        <td align="left"><code>preceding</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Обратное</td>
       </tr>
       <tr>
        <td align="left"><code>preceding-sibling</code></td>
        <td align="left">Узел элемента</td>
        <td align="left">Обратное</td>
       </tr>
       <tr>
        <td align="left"><code>attribute</code></td>
        <td align="left">Узел атрибута</td>
        <td align="left">Прямое</td>
       </tr>
       <tr>
        <td align="left"><code>namespace</code></td>
        <td align="left">Узел пространства имен</td>
        <td align="left">Прямое</td>
       </tr>
      </table>
      <p>Базовый тип влияет на то, как в данном шаге выборки будет выполняться тест узла, а направление просмотра на позицию, которую будет занимать тот или иной узел в данном направлении.</p>
      <p>Легче всего понять, какие узлы и в каком порядке содержат те или иные оси навигации, представив это графически. Рис. 6.10 иллюстрирует выбор узлов осями навигации. Здесь показано дерево документа, контекстный узел, выделенный жирной линией, и множество узлов, содержащееся в данной оси, ограниченное пунктиром. Узлы выбранного множества пронумерованы в порядке просмотра оси.</p>
      <image l:href="#img_56.png"/>
      <p><strong>Рис. 6.10</strong>. Расположение и порядок просмотра осей навигации в документе</p>
      <p>Приведем продукцию <code>AxisName</code>, которая описывает синтаксис осей навигации.</p>
      <p><code>[XP6] AxisName ::= 'ancestor'</code></p>
      <p><code>                   | 'ancestor-or-self'</code></p>
      <p><code>                   | 'attribute'</code></p>
      <p><code>                   | 'child'</code></p>
      <p><code>                   | 'descendant'</code></p>
      <p><code>                   | 'descendant-or-self'</code></p>
      <p><code>                   | 'following'</code></p>
      <p><code>                   | 'following-sibling'</code></p>
      <p><code>                   | 'namespace'</code></p>
      <p><code>                   | 'parent'</code></p>
      <p><code>                   | 'preceding'</code></p>
      <p><code>                   | 'preceding-sibling'</code></p>
      <p><code>                   | 'self'</code></p>
      <p>Оси навигации показывают, в каком направлении следует искать узлы, — среди тех, которые предшествовали контекстному узлу, или тех, которые будут следовать за ним, родительские или дочерние элементы, узлы атрибутов или пространств имен.</p>
      <p>При этом оси навигации могут содержать узлы разных типов и с разными именами. Следующая часть шага выборки, тест узла уточняет, что конкретно мы ищем.</p>
     </section>
     <section>
      <title>
       <p>Тесты узлов</p>
      </title>
      <p>Вторая часть шага выборки, тест узла, оставляет из множества, которое содержит ось навигации, только узлы, соответствующие определенному типу или имеющие определенные имена.</p>
      <p>Продукция <code>NodeTest</code>, соответствующая тесту узла, определяется следующим образом:</p>
      <p><code>[XP7] NodeTest ::= NameTest</code></p>
      <p><code>                   | NodeType '(' ')'</code></p>
      <p><code>                   | 'processing-instruction' '(' Literal ')'</code></p>
      <p>Раскрыв продукции <code>NameTest</code> и <code>NodeType</code>, EBNF-синтаксис теста узла можно переписать в упрощенном виде:</p>
      <p><code>NodeTest ::= '*'</code></p>
      <p><code>             | NCName:*</code></p>
      <p><code>             | QName</code></p>
      <p><code>             | 'comment()'</code></p>
      <p><code>             | 'text()'</code></p>
      <p><code>             | 'processing-instruction'</code></p>
      <p><code>             | 'processing-instruction' '(' Literal ')'</code></p>
      <p><code>             | 'node()'</code></p>
      <p>Рассмотрим подробно каждый случай.</p>
      <p>&#9633; Тест узла <code>'*'</code> выполняется для любого узла, тип которого является базовым типом оси навигации данного шага выборки. Иными словами, шаг выборки <code>attribute::*</code> или <code>@*</code> выберет все атрибуты контекстного узла, а <code>namespace::*</code> — все узлы пространств имен. Для всех остальных осей тест <code>*</code> будет выбирать узлы элементов, принадлежащих данной оси.</p>
      <p>&#9633; Тест узла вида <code>'NCName:*'</code> выполняется для узлов определенного пространства имен. Этот тест имеет вид <code><emphasis>префикс</emphasis>:*</code>, где <code><emphasis>префикс</emphasis></code> соответствует проверяемому пространству (он должен быть определен в контексте вычисляемого шага выборки). Этот тест выполняется для всех узлов пространства имен, которое соответствует префиксу вне зависимости от локальной части имени.</p>
      <p>&#9633; Тест вида <code>QName</code> выполняется для узлов базового типа, которые имеют расширенные имена, равные <code>QName</code>. Если в <code>QName</code> не указан префикс, то тест будет выполняться для узлов с соответствующим именем и нулевым пространством имен. В случае, если префикс указан, узел будет удовлетворять тесту, если его пространство имен будет совпадать с пространством имен, которое соответствует префиксу, а локальная часть имени будет равна локальной части <code>QName</code>.</p>
      <p>&#9633; Тест <code>'comment()'</code> выполняется для любого узла комментария.</p>
      <p>&#9633; Тест <code>'text()'</code> выполняется для любого текстового узла.</p>
      <p>&#9633; Тест узла <code>'processing-instruction()'</code> выполняется для любого узла инструкции по обработке.</p>
      <p>&#9633; Тест <code>'processing-instruction (' Literal ')'</code>, или, в упрощенном виде <code>processing-instruction(<emphasis>строка</emphasis>)</code> выполняется для инструкций по обработке, имеющих имя, равное строковому параметру этого теста узла.</p>
      <p>&#9633; Тест узла <code>'node()'</code> выполняется для любого узла. Шаг выборки вида <code><emphasis>ось</emphasis>::node()</code> выберет все узлы, принадлежащие данной оси.</p>
      <p>Примеры:</p>
      <p>&#9633; <code>child::node()</code> — выберет все дочерние узлы контекстного узла;</p>
      <p>&#9633; <code>child::*</code> — выберет дочерние элементы контекстного узла;</p>
      <p>&#9633; <code>attribute::*</code> — выберет атрибуты контекстного узла;</p>
      <p>&#9633; <code>xsl:*</code> — выберет все дочерние элементы контекстного узла, принадлежащие пространству имен с префиксом <code>xsl</code>;</p>
      <p>&#9633; <code>xsl:template</code>  — выберет все дочерние элементы <code>template</code> контекстного узла, принадлежащие пространству имен с префиксом <code>xsl</code>;</p>
      <p>&#9633; <code>comment()</code> — выберет все дочерние узлы комментариев;</p>
      <p>&#9633; <code>self::comment()</code> — выберет контекстный узел, если он является комментарием, или пустое множество в противном случае;</p>
      <p>&#9633; <code>descendant::processing-instruction()</code> — выберет все узлы инструкций по обработке, которые являются потомками контекстного узла;</p>
      <p>&#9633; <code>following::processing-instruction('арр')</code>— выберет все узлы инструкций по обработке с целевым приложением "<code>app</code>", которые следуют за контекстным узлом в порядке просмотра документа.</p>
      <p>Тест узла показывает, какого типа узлы мы ищем. Комментарии? Текстовые узлы? Узлы с определенными именами или принадлежащие определенному пространству имен? Или подойдут любые узлы?</p>
      <p>Итак, ось навигации позволяет указывать направления шага по дереву документа, тест узла — тип или имя выбираемого узла. Третья часть шага выборки (один или несколько предикатов) позволяет дополнять эти критерии логическими условиями, которые должны выполняться для выбираемых на данном шаге узлов.</p>
     </section>
     <section>
      <title>
       <p>Предикаты</p>
      </title>
      <p>При выборе узлов каждый шаг выборки может иметь один или несколько предикатов, которые будут фильтровать выбираемое множество узлов. Предикат — это логическое выражение, вычисляемое для. каждого узла выбранного множества, и только в том случае, если результатом является истина, узел остается в фильтруемом множестве.</p>
      <p>Продукция предиката, <code>Predicate</code>, определяется следующим образом:</p>
      <p><code>[XP8] Predicate     ::= '[' PredicateExpr ']'</code></p>
      <p><code>[XP9] PredicateExpr ::= Expr</code></p>
      <p><code>PredicateExpr</code> — это логическое выражение предиката, которое в данной версии языка ничем не отличается от обычного выражения. Продукцию предиката можно упростить и переписать в следующем виде:</p>
      <p><code>Predicate ::= '[' Expr ']'</code></p>
      <p>Как можно видеть, синтаксис предикатов довольно примитивен — это просто выражение, заключенное в квадратные скобки. При вычислении предиката результат этого выражения приводится к булевому типу.</p>
      <p>Фильтрация множества узлов выполняется следующим образом.</p>
      <p>&#9633; Фильтруемое множество сортируется в направлении просмотра оси навигации данного шага. Для осей <code>ancestor</code>, <code>ancestor-or-self</code>, <code>preceding</code>, <code>preceding-sibling</code> фильтруемое множество сортируется в обратном порядке просмотра документа, для остальных осей — в прямом порядке просмотра.</p>
      <p>&#9633; Выражение предиката вычисляется для каждого узла отсортированного множества в следующем контексте.</p>
      <p> • Фильтруемый узел (тот, для которого в данный момент вычисляется предикат) становится контекстным узлом.</p>
      <p> • Количество узлов фильтруемого множества становится размером контекста.</p>
      <p> • Позиция фильтруемого узла в отсортированном множестве становится позицией контекста.</p>
      <p>&#9633; Результат вычисления предиката преобразуется в булевый тип согласно следующим правилам.</p>
      <p> • Если результатом вычисления является число, равное позиции контекста, булевым значением предиката будет <code>true</code>, в противном случае — <code>false</code>. Например, предикат <code>[2]</code> равносилен предикату <code>[position()=2]</code> — он обратится в истину только для второго узла фильтруемого множества.</p>
      <p> • Все остальные типы данных приводятся к булевому типу в соответствии со стандартными правилами (<emphasis>см. также раздел "Типы данных" настоящей главы</emphasis>).</p>
      <p>&#9633; Из фильтруемого множества исключаются все узлы, булевое значение предиката для которых было ложью.</p>
      <p>&#9633; В случае, если в шаге выборки было несколько предикатов, процедура фильтрации повторяется с каждым из них, оставляя в отфильтрованном множестве только те узлы, для которых каждый из предикатов будет истиной.</p>
      <p>Таким образом, предикаты определяют свойства, которыми должны обладать выбираемые узлы.</p>
      <p>Примеры:</p>
      <p>&#9633; <code>a[1]</code> — выберет первый в порядке просмотра документа дочерний элемент <code>а</code> контекстного узла;</p>
      <p>&#9633; <code>a[position() mod 2 = 0]</code> — выберет все четные дочерние элементы <code>а</code>;</p>
      <p>&#9633; <code>*[. = 'а']</code> — выберет все дочерние элементы, текстовое значение которых равно "<code>а</code>";</p>
      <p>&#9633; <code>*[name() = 'a']</code> — выберет все дочерние элементы, имя которых равно "<code>а</code>";</p>
      <p>&#9633; <code>*[starts-with(name(), 'a')]</code> — выберет все дочерние элементы, имя которых начинается с "<code>а</code>";</p>
      <p>&#9633; <code>*[. = 'а'][1]</code> — выберет первый дочерний элемент, текстовое значение которого равно "<code>а</code>";</p>
      <p>&#9633; <code>*[. = 'a'][position() mod 2 = 0]</code> — выберет все дочерние элементы, текстовое значение которых равно "<code>а</code>", затем из них выберет четные элементы.</p>
     </section>
     <section>
      <title>
       <p>Сокращенный синтаксис</p>
      </title>
      <p>Пути выборки — это наиболее часто используемые XPath-выражения и для того, чтобы сделать их менее громоздкими, в XPath имеется так называемый сокращенный синтаксис, с которым мы уже встречались в предыдущих главах. Его продукции записываются следующим образом:</p>
      <p><code>[XP10] AbbreviatedAbsoluteLocationPath</code></p>
      <p><code> :: = '//' RelativeLocationPath</code></p>
      <p><code>[XP11] AbbreviatedRelativeLocationPath</code></p>
      <p><code> ::= RelativeLocationPath '//' Step</code></p>
      <p><code>[XP12] AbbreviatedStep</code></p>
      <p><code> ::= '.'</code></p>
      <p><code>     | '..'</code></p>
      <p><code>[XP13] AbbreviatedAxisSpecifier</code></p>
      <p><code> ::= '@'?</code></p>
      <p>Первое сокращение, <code>'//'</code> — это краткая версия для <code>"/descendant-or-self::node()/"</code>. Шаг выборки <code>descendant-or-self::node()</code> возвращает всех потомков контекстного узла (не включая узлов атрибутов и пространств имен). Сокращенный путь вида <code>'//' RelativeLocationPath</code> раскрывается в путь вида</p>
      <p><code>'/descendant-or-self::node()/' RelativeLocation</code></p>
      <p>а путь вида <code>RelativeLocationPath '//' Step</code> — в путь</p>
      <p><code>RelativeLocationPath '/descendant-or-self::node()/' Step</code></p>
      <p>Сокращенный шаг вида <code>'.'</code> возвращает контекстный узел, его полная версия — <code>self::node()</code>.</p>
      <p>Сокращенный шаг '<code>..</code>' возвращает родительский узел контекстного узла. Это сокращение равносильно шагу выборки <code>parent::node()</code>.</p>
      <p>Заметим, что сокращения <code>"."</code> и <code>".."</code> являются сокращенными <emphasis>шагами</emphasis> выборки. Это, в частности, означает, что к ним нельзя присовокуплять предикаты и так далее. Выражение <code>".[ancestor::body]"</code> будет с точки зрения синтаксиса XPath некорректным. Вместо этого можно использовать выражение <code>"self::node()[ancestor::body]"</code>, которое будет синтаксически правильным.</p>
      <p>Наиболее часто используемой осью навигации является ось <code>child</code>, содержащая все дочерние узлы контекстного узла. Шаги выборки, которые обращаются к дочерним узлам, имеют вид <code>'child::' NodeTest Predicate*</code>. Самым полезным сокращением является то, что в шагах такого вида дескриптор оси <code>'child::'</code> может быть опущен, и тогда упрощенные шаги будут иметь вид <code>NodeTest Predicate*</code>.</p>
      <p>Дескриптор оси навигации <code>'attribute::'</code> также может быть сокращен до <code>'@'</code>. Шаг выборки <code>'attribute::' NodeTest Predicate*</code> может быть переписан с использованием, сокращенного синтаксиса в виде <code>'@'. NodeTest Predicate*</code>.</p>
      <p>Примеры:</p>
      <p>&#9633; <code>.//*</code> — выберет все элементы-потомки контекстного узла;</p>
      <p>&#9633; <code>..//*</code> — выберет все дочерние элементы родителя контекстного узла;</p>
      <p>&#9633; <code>@*</code> — выберет все атрибуты контекстного узла;</p>
      <p>&#9633; <code>.//@*</code> — выберет все атрибуты всех потомков контекстного узла;</p>
      <p>&#9633; <code>//*</code> — выберет все элементы документа, содержащего контекстный узел;</p>
      <p>&#9633; <code>//@*</code> — выберет все атрибуты всех элементов документа, содержащего контекстный узел;</p>
      <p>&#9633; <code>html/body</code> — выберет элементы <code>body</code>, принадлежащие дочерним элементам <code>html</code> контекстного узла.</p>
     </section>
     <section>
      <title>
       <p>Примеры путей выборки</p>
      </title>
      <p>Простые шаги выборки:</p>
      <p>&#9633; <code>child::*</code> — выберет все дочерние элементы контекстного узла;</p>
      <p>&#9633; <code>child::comment()</code> — выберет все узлы комментариев контекстного узла;</p>
      <p>&#9633; <code>child::node()</code> — выберет все дочерние узлы контекстного узла вне зависимости от их типа;</p>
      <p>&#9633; <code>child::query</code> — выберет все дочерние элементы контекстного узла, имеющие имя <code>query</code>;</p>
      <p>&#9633; <code>child::xsql:*</code> — выберет все дочерние элементы, которые находятся в пространстве имен, определяемом префиксом <code>xsql</code>;</p>
      <p>&#9633; <code>child::xsql:query</code> — выберет все дочерние элементы <code>query</code>, которые находятся в пространстве имен, определяемом префиксом <code>xsql</code>;</p>
      <p>&#9633; <code>attribute::*</code> — выберет все атрибуты контекстного узла;</p>
      <p>&#9633; <code>attribute::href</code> — выберет атрибут <code>href</code> контекстного узла, если он существует;</p>
      <p>&#9633; <code>parent::*</code> — выберет родительский узел контекстного узла, если тот является элементом, и пустое множество, если родительский узел имеет другой тип, например является корнем дерева;</p>
      <p>&#9633; <code>parent::node()</code> — выберет родительский узел контекстного узла вне зависимости от его типа. Единственный случай, когда этот шаг выберет пустое множество — это когда контекстный узел является корневым узлом документа;</p>
      <p>&#9633; <code>parent::xsl:template</code> — выберет родительский узел, если тот является элементом с именем template и имеет пространство имен с префиксом <code>xsl</code>, иначе выберет пустое множество;</p>
      <p>&#9633; <code>self::*</code> — выберет контекстный узел, если он является элементом и пустое множество узлов, если контекстный узел имеет другой тип;</p>
      <p>&#9633; <code>self:*</code> — выберет все дочерние элементы контекстного узла, принадлежащие пространству имен с префиксом <code>self</code>;</p>
      <p>&#9633; <code>self::text()</code> — выберет контекстный узел, если он является текстовым узлом;</p>
      <p>&#9633; <code>self::node()</code> — выберет контекстный узел вне зависимости от его типа;</p>
      <p>&#9633; <code>self::query</code> — выберет контекстный узел, если он является элементом с именем <code>query</code>, и пустое множество, если контекстный узел имеет другое имя или не является элементом;</p>
      <p>&#9633; <code>preceding::para</code> — выберет все элементы <code>para</code>, которые предшествуют контекстному узлу в порядке просмотра документа;</p>
      <p>&#9633; <code>preceding::comment()</code> — выберет все узлы комментариев, которые предшествуют контекстному узлу в порядке просмотра документа;</p>
      <p>&#9633; <code>preceding-sibling::*</code> — выберет все братские (принадлежащие тому же родителю) элементы контекстного узла, которые предшествуют ему в порядке просмотра документа;</p>
      <p>&#9633; <code>following::processing-instruction('fop')</code> — выберет все узлы инструкций по обработке, которые имеют имя (целевое приложение) <code>"fop"</code> и следуют за контекстным узлом в порядке просмотра документа;</p>
      <p>&#9633; <code>following-sibling::text()</code> — выберет все текстовые узлы, которые являются братьями контекстного узла и следуют за ним в порядке просмотра документа;</p>
      <p>&#9633; <code>descendant::*</code> — выберет все элементы-потомки контекстного узла;</p>
      <p>&#9633; <code>descendant::node()</code> — выберет все узлы-потомки контекстного узла;</p>
      <p>&#9633; <code>descendant::b</code> — выберет все элементы <code>b</code>, являющиеся потомками контекстного узла;</p>
      <p>&#9633; <code>descendant-or-self::*</code> — выберет все элементы-потомки контекстного узла, а также сам контекстный узел, если он также является элементом;</p>
      <p>&#9633; <code>ancestor::*</code> — выберет все элементы, которые являются предками контекстного узла; выбранное множество не будет включать корневой узел, поскольку он не является элементом;</p>
      <p>&#9633; <code>ancestor::node()</code> — выберет все узлы, являющиеся предками контекстного узла; выбранное множество будет включать корневой узел (за исключением того случая, когда контекстный узел сам является корневым);</p>
      <p>&#9633; <code>ancestor::p</code> — выберет все элементы <code>p</code>, являющиеся предками контекстного узла;</p>
      <p>&#9633; <code>ancestor-or-self::node()</code> — выберет контекстный узел, а также все узлы, являющиеся его предками. Выбранное этим шагом множество будет всегда включать корневой узел;</p>
      <p>&#9633; <code>ancestor-or-self::body</code> — выберет все элементы <code>body</code>, которые являются предками контекстного узла, а также сам контекстный узел, если он является элементом <code>body</code>;</p>
      <p>&#9633; <code>namespace::*</code> — выберет все узлы пространств имен, ассоциированные с контекстным узлом; это множество будет, как минимум, содержать узел пространства имен <code>xml</code>;</p>
      <p>&#9633; <code>namespace::xyz</code> — выберет узел пространства имен, определяемого префиксом <code>xyz</code>; поскольку один префикс может соответствовать только одному пространству, возвращаемое множество будет содержать не более одного узла.</p>
      <p>Шаги выборки с предикатами:</p>
      <p>&#9633; <code>child::*[1]</code> — выберет первый дочерний элемент контекстного узла; этот шаг выборки равносилен <code>child::*[position()=1]</code>;</p>
      <p>&#9633; <code>child::p[1]</code> — выберет первый дочерний элемент p контекстного узла; этот шаг выборки равносилен <code>child::p[position()=1]</code>;</p>
      <p>&#9633; <code>child::*[last()]</code> — выберет последний дочерний узел контекстного узла; этот шаг выборки равносилен <code>child::*[position()=last()]</code>;</p>
      <p>&#9633; <code>child::*[last()-1]</code> — выберет предпоследний дочерний узел контекстного узла; этот шаг выборки равносилен шагу <code>child::*[position()=last()]</code>. Если контекстный узел имеет только один дочерний элемент, выбираемое множество будет пустым;</p>
      <p>&#9633; <code>child::p[position() mod 2 = 0]</code> — выберет все четные элементы <code>p</code>;</p>
      <p>&#9633; <code>child::p[position() mod 2 = 1]</code> — выберет все нечетные элементы <code>p</code>;</p>
      <p>&#9633; <code>child::а[2][attribute::name='b']</code> — Выберет второй дочерний элемент <code>а</code> контекстного узла, если он имеет атрибут <code>name</code> со значением <code>"b"</code>;</p>
      <p>&#9633; <code>child::a[attribute::name='b'][2]</code> — выберет второй дочерний элемент а контекстного узла из тех, которые имеют атрибут <code>name</code> со значением <code>"b"</code>; этот шаг выборки отличается от шага выборки в предыдущем примере — порядок следования предикатов имеет значение;</p>
      <p>&#9633; <code>child::a[position()=$i]</code> — выберет дочерний элемент <code>а</code>, позиция которого равна значению переменной <code>i</code>;</p>
      <p>&#9633; <code>parent::*['root']</code> — выберет родительский узел контекстного узла, если он является элементом; если он является корнем документа, этот шаг выборки не выберет ничего; предикат <code>['root']</code> не имеет никакого действия, поскольку строка <code>'root'</code> как непустая строка тождественно преобразуется в истину;</p>
      <p>&#9633; <code>preceding-sibling::*[attribute::*]</code> — выберет все братские узлы контекстного узла, которые предшествуют ему, являются элементами и содержат, по крайней мере, один атрибут;</p>
      <p>&#9633; <code>preceding-sibling:p[1]</code> — выберет ближайший (первый в обратном порядке просмотра) элемент p, который предшествует контекстному узлу;</p>
      <p>&#9633; <code>following::а[attribute::href][not(descendant::img)]</code> — выберет все узлы, которые следуют за контекстным в порядке просмотра документа, являются элементами с именем <code>а</code>, имеют атрибут <code>href</code>, но не имеют элементов-потомков с именем <code>img</code>;</p>
      <p>&#9633; <code>ancestor::node()[2]</code> — выберет второго предка (то есть "деда") контекстного узла;</p>
      <p>&#9633; <code>descendant-or-self::a[attribute::href]</code> — выберет контекстный узел, а также все узлы-потомки контекстного узла, если они являются элементами с именем <code>а</code> и имеют атрибут <code>href</code>;</p>
      <p>&#9633; <code>namespace::*[contains(self::node(), 'XML')]</code> — выберет узлы пространств имен, которые ассоциируются с контекстным узлом, и строковое значение (URI) которых содержит подстроку <code>'XML'</code>.</p>
      <p>Использование сокращенного синтаксиса в шагах выборки:</p>
      <p>&#9633; <code>table</code> — выберет все дочерние элементы <code>table</code> контекстного узла; этот шаг выборки равносилен <code>child::table</code>;</p>
      <p>&#9633; <code>@*</code> — выберет все атрибуты контекстного узла; полная версия этого шага выборки выглядит как <code>attribute::*</code>;</p>
      <p>&#9633; <code>*[i] </code>— выберет первый дочерний элемент контекстного узла; этот шаг выборки равносилен шагу <code>child::*[position()=1]</code>;</p>
      <p>&#9633; <code>*[last()]</code> — выберет последний дочерний узел контекстного узла; этот шаг выборки равносилен шагу <code>child::*[position()=last()]</code>;</p>
      <p>&#9633; <code>descendant-or-self::a[@href]</code> — выберет контекстный узел, а также все узлы-потомки контекстного узла, если они являются элементами с именем а и имеют атрибут <code>href</code>; этот шаг выборки эквивалентен шагу <code>descendant-or-self::a[attribute::href]</code>; еще короче его можно записать как <code>.//a[@href]</code>;</p>
      <p>&#9633; <code>following::a[@href][not(@target)]</code> — выберет все узлы, которые следуют в порядке просмотра документа за контекстным узлом, являются элементами с именем <code>а</code>, имеют атрибут <code>href</code>, но не имеют атрибута <code>target</code>; этот шаг эквивалентен шагу <code>following::a[attribute::href][not(attribute::target)]</code>;</p>
      <p>&#9633; <code>..</code> — выберет родительский узел контекстного узла; этот шаг выборки эквивалентен шагу <code>parent::node()</code>;</p>
      <p>&#9633; <code>namespace::*[contains(., 'XML')]</code> — выберет узлы пространств имен, которые ассоциируются с контекстным узлом, и строковое значение (URI) которых содержит подстроку <code>'XML'</code>. Этот шаг выборки эквивалентен шагу <code>namespace::*[contains(self::node(), 'XML')]</code>;</p>
      <p>&#9633; <code>preceding-sibling::*[@*]</code> — выберет все братские узлы контекстного узла, которые предшествуют ему, являются элементами и содержат, по крайней мере, один атрибут;</p>
      <p>&#9633; <code>*[not(self::para)]</code> — выберет все дочерние элементы контекстного узла, кроме элементов <code>para</code>;</p>
      <p>&#9633; <code>*[para or chapter]</code> — выберет все дочерние элементы контекстного узла, которые имеют хотя бы один дочерний элемент <code>para</code> или <code>chapter</code>;</p>
      <p>&#9633; <code>*[para and chapter]</code> — выберет все дочерние элементы контекстного узла, которые имеют хотя бы один дочерний элемент para и хотя бы один дочерний элемент <code>chapter</code>;</p>
      <p>&#9633; <code>*[para][chapter]</code> — выберет все дочерние элементы контекстного узла, <code>которые</code> имеют хотя бы один дочерний элемент <code>para</code> и хотя бы один дочерний элемент <code>chapter</code>; этот шаг выборки равносилен <code>*[para and chapter]</code>, однако в общем случае это неверно;</p>
      <p>&#9633; <code>*[* or @*]</code> — выберет все дочерние элементы, содержащие атрибуты или элементы;</p>
      <p>&#9633; <code>*[not(* or @*)]</code> — выберет все дочерние элементы, не содержащие ни атрибутов, ни элементов;</p>
      <p>&#9633; <code>*[@name or @href]</code> — выберет все дочерние элементы контекстного узла, имеющие хотя бы один из атрибутов <code>name</code> или <code>href</code>;</p>
      <p>&#9633; <code>@*[count(.|../@href) != count(../@href)]</code> — выберет все атрибуты контекстного узла, кроме атрибутов <code>href</code>;</p>
      <p>&#9633; <code>[local-name() != 'href']</code> — выберет все атрибуты контекстного узла, кроме атрибутов <code>href</code>; это выражение практически аналогично предыдущему (за тем исключением, что в этом способе не учитываются пространства имен).</p>
      <p>Примеры путей выборки:</p>
      <p>&#9633; <code>/</code> — выберет корневой узел документа;</p>
      <p>&#9633; <code>/*</code> — выберет элемент, находящийся в корне документа (элемент документа);</p>
      <p>&#9633; <code>ancestor::body/a</code> — выберет все элементы <code>а</code>, принадлежащие всем предкам-элементам <code>body</code> контекстного узла;</p>
      <p>&#9633; <code>/ancestor::body/a</code> — выберет все элементы <code>а</code>, принадлежащие всем предкам-элементам <code>body</code> корневого узла (это будет пустое множество);</p>
      <p>&#9633; <code>//ancestor::body/a</code> — выберет все элементы <code>а</code>, принадлежащие всем предкам-элементам <code>body</code> корневого узла и потомков корневого узла; иными словами, путь <code>//ancestor::body</code> выбирает элементы <code>body</code>, являющиеся предками каких-либо узлов документа, шаг <code>a</code> — дочерние узлы этих элементов; это выражение равносильно выражению <code>//body[node()]/a</code>;</p>
      <p>&#9633; <code>preceding::а/@b</code> — выберет атрибуты <code>b</code> элементов <code>а</code>, предшествующих контекстному узлу;</p>
      <p>&#9633; <code>/doc/chapter</code> — выберет элементы <code>chapter</code>, принадлежащие элементам <code>doc</code>, которые находятся в корне документа;</p>
      <p>&#9633; <code>//doc/chapter</code> — выберет элементы <code>chapter</code>, которые находятся в любом элементе <code>doc</code> документа;</p>
      <p>&#9633; <code>doc/chapter</code> — выберет элементы <code>chapter</code>, которые находятся в дочерних элементах <code>doc</code> контекстного узла;</p>
      <p>&#9633; <code>self::node()[ancestor::body[1]]</code> — выберет множество, состоящее из контекстного узла, если во множестве его предков <code>body</code> есть первый элемент (иначе — пустое множество); это выражение равносильно выражению <code>self::node()[ancestor::body]</code>, поскольку если <code>ancestor::body</code> — непустое множество, то у него будет первый элемент;</p>
      <p>&#9633; <code>*[contains(name(), 'ody')]/*[contains(name(),'able')]</code> — выберет множество элементов, в имени которых присутствует строка <code>"able"</code> при условии, что они принадлежат дочерним элементам контекстного узла, в имени которых присутствует строка <code>"ody"</code>;</p>
      <p>&#9633; <code>*[last()]/preceding-sibling::*[2]</code> — выберет второй с конца дочерний элемент контекстного узла. Это выражение равносильно <code>*[last()-2]</code>;</p>
      <p>&#9633; <code>*/@*</code> — выберет все атрибуты всех дочерних элементов контекстного узла;</p>
      <p>&#9633; <code>//* [local-name(.) = 'body']</code> — выберет все элементы <code>body</code> текущего документа вне зависимости от их пространств имен.</p>
     </section>
    </section>
    <section>
     <title>
      <p>Паттерны</p>
     </title>
     <section>
      <p>В языке XSLT определяется подмножество выражений языка XPath, которые называются <emphasis>паттернами</emphasis> (от англ. pattern — образец). Паттерны представляют собой упрощенные пути выборки, которые используются для определения, соответствует ли узел заданному образцу.</p>
      <p>Чаще всего паттерны применяются в элементе <code>xsl:template</code> в атрибуте <code>match</code>. Шаблоны такого типа будут выполняться только для тех узлов, которые удовлетворяют заданному образцу. Например, следующий шаблон будет выполняться только для элементов <code>body</code>, принадлежащих элементу <code>html</code>:</p>
      <p><code>&lt;xsl:template match="html/body"&gt;</code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/xsl:template&gt;</code></p>
      <p>Кроме этого, паттерны применяются при нумерации и при определениях ключей.</p>
      <p>Паттерны являются сильно упрощенными путями выборки. Единственные оси, которые могут использоваться в паттернах, — это <code>child</code>, <code>attribute</code> и <code>descendant-or-self</code>, причем ось навигации <code>descendant-or-self </code>может быть указана только в сокращенном виде оператором "<code>//</code>". То, что в паттернах используются только оси атрибутов и узлов-потомков, позволяет XSLT-процессорам значительно оптимизировать процесс сопоставления узла заданному образцу — ведь теперь даже в самом худшем сценарии не нужно метаться по всему документу, выбирая узлы, содержащиеся в тех или иных осях навигации. Правда, оператор "<code>//</code>" остается не менее опасным — при его проверке может понадобиться перебрать всех предков текущего узла, что может быть весьма и весьма затруднительно (хотя и проще, чем перебор всех потомков).</p>
      <p>Хоть паттерны и выглядят как пути выборки, на самом деле механизм их работы несколько иной. Они не выбирают множество узлов, как таковое, они проверяют узлы на соответствие образцу, который они определяют. Это в принципе эквивалентно выбору множества и проверке узла на вхождение в него, но, как правило, так не делается, поскольку такая проверка потребовала бы слишком больших затрат времени. Гораздо дешевле в этом смысле воспользоваться тем фактом, что синтаксис паттернов упрощен, и осей не так много для того, чтобы создать более эффективный алгоритм проверки соответствия узлов. Например, для того чтобы проверить соответствие некоторого узла, назовем его <code>X</code>, паттерну <code>body/a</code>, совершенно необязательно вычислять путь выборки <code>body/a</code> и затем проверять, входит ли узел <code>X</code> в полученное множество. Достаточно проверить, является ли именем узла "<code>a</code>", а именем его родителя (если он, конечно, есть) — "<code>body</code>".</p>
      <p>Образцы для сравнения могут состоять из одного или нескольких паттернов, которые перечисляются через знак "<code>|</code>". Для того чтобы соответствовать такому перечислению в целом, узел должен соответствовать хотя бы одному из паттернов, входящих в него. Здесь тоже есть определенная аналогия с множествами, оператор "<code>|</code>" означает как бы объединение: узел входит в объединение множеств, если он входит хотя бы в одно из объединяемых множеств. Но, конечно же, и здесь упрощенный синтаксис играет свою роль для оптимизации — оперировать множествами, выбираемыми каждым из паттернов, было бы очень неэкономно.</p>
      <p>Паттерны и их продукции описываются в спецификации самого языка XSLT, но мы приводим их в той же главе, что и выражения языка XPath, поскольку они очень похожи и имеют к тому же практические одинаковые семантические принципы. Паттерны используют также некоторые продукции языка XPath (такие, как <code>NodeTest</code>, <code>Predicate</code> и другие).</p>
      <p>При нумерации EBNF-продукций паттернов мы будем нумеровать их с префиксом <code>PT</code> (<code>[PT1]</code>, <code>[PT2]</code> и т.д.), чтобы не путать с продукциями других языков, рассматриваемых в этой книге.</p>
      <p>Самая общая продукция паттерна называется <code>Pattern</code> и показывает, что образец соответствия может быть как одиночным паттерном, так и перечислением нескольких паттернов с разделяющими символами "<code>|</code>". Продукция <code>LocationPathPattern</code> соответствует одиночному паттерну, показывая своим названием (англ. location path pattern — образец пути выборки) конструкционную близость к самим путям выборки.</p>
      <p><code>[PT1] Pattern ::= LocationPathPattern</code></p>
      <p><code>                  | Pattern '|' LocationPathPattern</code></p>
      <p>Одиночный паттерн определяется следующим образом:</p>
      <p><code>[PT2] LocationPathPattern</code></p>
      <p><code> ::= '/' RelativePathPattern?</code></p>
      <p><code>     | IdKeyPattern (('/' | '//') RelativePathPattern)?</code></p>
      <p><code>     | '//'? RelativePathPattern</code></p>
      <p>Упростив эту продукцию, мы получим следующее правило:</p>
      <p><code>LocationPathPattern ::= '/'</code></p>
      <p><code>                        | RelativePathPattern</code></p>
      <p><code>                        | '/' RelativePathPattern</code></p>
      <p><code>                        | '//' RelativePathPattern</code></p>
      <p><code>                        | IdKeyPattern</code></p>
      <p><code>                        | IdKeyPattern '/' RelativePathPattern</code></p>
      <p><code>                        | IdKeyPattern '//' RelativePathPattern</code></p>
      <p>Если учесть, что нетерминал <code>RelativePathPattern</code> соответствует образцу относительного пути, можно легко заметить, как похожи первые четыре возможности в этом правиле на то, что мы разбирали при описании самих абсолютных и относительных путей.</p>
      <p>&#9633; Паттерну <code>'/'</code> соответствует только корневой узел.</p>
      <p>&#9633; Паттерн <code>RelativePathPattern</code> задает образец относительного пути. Например, паттерну <code>a/b</code> соответствуют элементы <code>b</code>, находящиеся в элементах <code>a</code>.</p>
      <p>&#9633; Паттерну <code>'/' RelativePathPattern</code> соответствуют узлы, которые соответствуют образцу относительного пути при отсчете от корневого узла. Например, паттерну <code>/a/b</code> соответствуют элементы <code>b</code>, находящиеся в элементах <code>a</code>, находящихся в корне документа.</p>
      <p>&#9633; Паттерну <code>'//' RelativePathPattern</code> соответствуют узлы, которые соответствуют относительному пути при отсчете от любого узла документа. Например, паттерну <code>//a/b</code> соответствуют любые элементы <code>b</code>, имеющие родителем элемент с именем <code>а</code>. Фактически, этот паттерн не отличается от паттерна <code>a/b</code> (единственное различие в том, что они могут иметь разные приоритеты).</p>
      <p>Последние три случая в правиле <code>LocationPathPattern</code> относятся к таким механизмам XSLT, как адресация по уникальным идентификаторам и ключам.</p>
      <p>В первой главе книги, когда мы описывали синтаксис и семантику языка разметки документов XML, мы коротко остановились на уникальных атрибутах — атрибутах, которые определяются типом <code>ID</code> и значения которых должны быть уникальны внутри документа. Как мы узнали, это позволяет более эффективно обращаться к элементам в документе.</p>
      <p>XSLT позволяет использовать уникальные атрибуты элементов при помощи функции <code>id</code>, которая возвращает множество, состоящее из узла, уникальный атрибут которого равен переданному ей значению, или пустое множество, если такого элемента нет.</p>
      <p>Кроме того, XSLT предоставляет похожий механизм, механизм ключей, который выбирает узлы не по уникальным атрибутам, а по значениям именованных ключей, определенных в преобразовании. Для этого служит функция <code>key</code>.</p>
      <p>Поскольку два этих механизма схожи по семантике, они определяются в XSLT в едином паттерне:</p>
      <p><code>[PT3] IdKeyPattern ::= 'id' '(' Literal ')'</code></p>
      <p><code>                       | 'key' '(' Literal ',' Literal ')'</code></p>
      <p>Этому паттерну соответствуют только узлы, принадлежащие результату одной из двух функций — <code>id</code> или <code>key</code>.</p>
      <p>Оставим детали использования ключей и <code>ID</code>-атрибутов на потом и вернемся к разбору вариантов синтаксиса паттернов.</p>
      <p>&#9633; Паттерну <code>IdKeyPattern '/' RelativePathPattern</code> соответствуют узлы, которые соответствуют образцу пути <code>RelativePathPattern</code> отсчитанного относительного узла, соответствующего <code>IdKeyPattern</code>. Например, узел соответствует паттерну <code>id('index5')/a/b</code>, если он является элементом с именем <code>b</code>, его родителем является элемент <code>а</code>, а его родитель в свою очередь имеет уникальный атрибут со значением <code>"index5"</code>.</p>
      <p>&#9633; Паттерн <code>IdKeyPattern '//' RelativePathPattern</code> аналогичен предыдущему: ему соответствуют узлы, которые соответствуют паттерну <code>RelativePathPattern</code>, отсчитанному от любого потомка или самого узла, входящего в <code>IdKeyPattern</code>. Например, паттерну <code>id('index5')//a/b</code> будет соответствовать любой дочерний элемент <code>b</code> элемента <code>a</code>, являющегося потомком элемента, уникальный атрибут которого имеет значение <code>index5</code>, или если он сам имеет такой атрибут.</p>
      <p>Мы более подробно остановимся на ключевых паттернах, когда будем разбирать функции <code>id</code> и <code>key</code>, а пока обратимся к главной детали всех вышеперечисленных продукций — к образцу относительного пути, <code>RelativePathPattern</code>. Его продукция записывается в следующем виде:</p>
      <p><code>[PT4] RelativePathPattern</code></p>
      <p><code> ::= StepPattern</code></p>
      <p><code>     | RelativePathPattern '/' StepPattern</code></p>
      <p><code>     | RelativePathPattern '//' StepPattern</code></p>
      <p>Если сравнить это правило с упрощенной продукцией <code>RelativeLocationPath</code>, можно заметить совпадение с точностью до имен продукций. Образец относительного пути строится точно так же, как и обычный путь выборки — перечислением через разделяющие символы <code>"/"</code> и <code>"//"</code> шагов, в данном случае — шагов образца относительного пути.</p>
      <p>Эти шаги соответствуют продукции <code>StepPattern</code>, которая отличается от продукции <code>Step</code> только тем, что разрешает использовать только оси <code>child</code> и <code>attribute</code>.</p>
      <p><code>[PT5] StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest</code></p>
      <p><code>                      Predicate*</code></p>
      <p>Продукция <code>ChildOrAxisSpecifier</code> описывает дескрипторы осей <code>child</code> и <code>attribute</code> в полном или сокращенном виде:</p>
      <p><code>[P6] ChildOrAttributeAxisSpecifier</code></p>
      <p><code> ::= AbbreviatedAxisSpecifier</code></p>
      <p><code>     | ('child' | 'attribute') '::'</code></p>
      <p>Для простоты мы можем раскрыть эту продукцию, получив ее в следующем виде:</p>
      <p><code>ChildOrAttributeAxisSpecifier</code></p>
      <p><code> ::= '@' ?</code></p>
      <p><code>     | 'child::'</code></p>
      <p><code>     | 'attribute::'</code></p>
      <p>Тогда продукцию <code>StepPattern</code> тоже можно переписать:</p>
      <p><code>StepPattern ::= NodeTest Predicate*</code></p>
      <p><code>                | '@' NodeTest Predicate*</code></p>
      <p><code>                | 'child::' NodeTest Predicate*</code></p>
      <p><code>                | 'attribute::' NodeTest Predicate*</code></p>
      <p>Теперь стало совершенно очевидно, что шаг паттерна это не что иное, как подмножество шагов выборки, в которых ограничено множество осей навигации.</p>
      <p>Таким образом, синтаксически паттерны отличаются от путей выборки тем, что в них можно использовать только две оси навигации (не считая <code>descendant-or-self</code> в виде оператора), но зато можно в качестве узла отсчета использовать узел, выбранный по своему уникальному атрибуту или по значению ключа.</p>
      <p>Паттерны могут использоваться в XSLT в следующих атрибутах:</p>
      <p>&#9633; атрибуты <code>count</code> и <code>from</code> элемента <code>xsl:number</code>;</p>
      <p>&#9633; атрибут <code>match</code> элемента <code>xsl:key</code>;</p>
      <p>&#9633; атрибут <code>match</code> элемента <code>xsl:template</code>.</p>
      <p>Последние два случая паттернов отличаются от первого тем, что в них нельзя использовать переменные. Определение вида</p>
      <p><code>&lt;xsl:template match="*[name() = $name]"&gt;</code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/xsl:template&gt;</code></p>
      <p>будет некорректным.</p>
     </section>
     <section>
      <title>
       <p>Семантика паттернов</p>
      </title>
      <p>Остановимся подробнее на вопросе — что же означает "соответствие узла некоторому паттерну".</p>
      <p>Прежде всего, заметим, что любой паттерн является также и XPath-выражением. Тогда строгое определение соответствия узла паттерну можно дать следующим образом.</p>
      <p>Узел <code>X</code> соответствует паттерну <code>P</code> тогда и только тогда, когда существует такой узел <code>Y</code>, принадлежащий оси <code>ancestor-or-self</code> узла <code>X</code>, что множество, получаемое в результате вычисления выражения <code>P</code> в контексте узла <code>Y</code> будет содержать узел <code>X</code>.</p>
      <subtitle>Пример</subtitle>
      <p>Рассмотрим это определение на примере паттерна <code>body//а</code>. Строго говоря, узел будет соответствовать этому паттерну, если во множестве его предков (плюс сам узел) найдется такой узел, что множество <code>body//а</code>, вычисленное в его контексте, будет содержать проверяемый узел. На практике первые два элемента <code>а</code> приведенного ниже документа соответствуют этому паттерну, потому что существует элемент <code>html</code>, содержащий элемент <code>body</code>, потомками которого эти элементы <code>а</code> являются.</p>
      <subtitle>Листинг 6.2</subtitle>
      <p><code>&lt;html&gt;</code></p>
      <p><code> &lt;body&gt;</code></p>
      <p><code>  &lt;a&gt;</code></p>
      <p><code>   &lt;!-- Соответствует паттерну body//a --&gt;</code></p>
      <p><code>  &lt;/a&gt;</code></p>
      <p><code>  &lt;p&gt;</code></p>
      <p><code>   &lt;a&gt;</code></p>
      <p><code>    &lt;!-- Соответствует паттерну body//a --&gt;</code></p>
      <p><code>   &lt;/a&gt;</code></p>
      <p><code>  &lt;/p&gt;</code></p>
      <p><code> &lt;/body&gt;</code></p>
      <p><code> &lt;а&gt;</code></p>
      <p><code>  &lt;!-- Не соответствует паттерну body//а --&gt;</code></p>
      <p><code> &lt;/а&gt;</code></p>
      <p><code>&lt;/html&gt;</code></p>
      <p>Существует также и более простое определение соответствия. Узел <code>X</code> соответствует паттерну <code>P</code> тогда и только тогда, когда <code>X</code> принадлежит множеству <code>//P</code>. В приведенном выше примере паттерну <code>body//а</code> соответствуют все узлы множества <code>//body//а</code>.</p>
      <p>Эти определения эквивалентны. На практике следует пользоваться тем, которое кажется более понятным.</p>
     </section>
     <section>
      <title>
       <p>Примеры паттернов</p>
      </title>
      <p>&#9633; <code>body</code> — соответствует элементам <code>body</code> с нулевым пространством имен;</p>
      <p>&#9633; <code>xhtml:body</code> — соответствует элементам <code>body</code>, принадлежащим пространству имен с префиксом <code>xhtml</code>;</p>
      <p>&#9633; <code>body/a</code> — соответствует дочерним элементам <code>а</code> элемента <code>body</code>;</p>
      <p>&#9633; <code>*</code> — соответствует любому элементу, который принадлежит нулевому пространству имен;</p>
      <p>&#9633; <code>а[1]</code> — соответствует каждому первому элементу <code>а</code> своего родительского узла; элемент будет соответствовать этому паттерну, если ему не предшествует никакой братский элемент <code>a</code> — то есть из всех дочерних элементов <code>а</code> некоторого узла этому паттерну будет соответствовать только первый в порядке просмотра документа элемент;</p>
      <p>&#9633; <code>a[position() mod 2 = 0]</code> — соответствует каждому четному элементу <code>a</code> своего родительского узла; иначе говоря, из всех элементов <code>а</code> некоторого узла этому паттерну будут соответствовать только четные;</p>
      <p>&#9633; <code>/</code> — соответствует корневому узлу;</p>
      <p>&#9633; <code>/html</code> — узел будет соответствовать этому паттерну тогда и только тогда, когда он является элементом с именем <code>html</code> и нулевым пространством имен и находится при этом в корне элемента;</p>
      <p>&#9633; <code>//html</code> — соответствует любому элементу <code>html</code> документа, принадлежащему нулевому пространству имен; этот паттерн равносилен паттерну <code>html</code>;</p>
      <p>&#9633; <code>*[starts-with(local-name(), 'A') or starts-with(local-name(), 'a')]</code> — соответствует любому элементу, имя которого начинается на букву <code>"а"</code> в любом регистре символов;</p>
      <p>&#9633; <code>*[string-length(local-name())=2]</code> — соответствует любому элементу, локальная часть имени которого состоит из двух символов;</p>
      <p>&#9633; <code>*[starts-with(namespace-uri(),'http') or starts-with(namespace-uri(), 'HTTP')]</code> — соответствует любому элементу, URI пространства имен которого начинается на <code>"http"</code> или <code>"HTTP"</code>;</p>
      <p>&#9633; <code>br[not(*)]</code> — соответствует элементу <code>br</code>, который не имеет дочерних элементов;</p>
      <p>&#9633; <code>id('i')</code> — соответствует элементу, уникальный атрибут которого (атрибут, имеющий тип <code>ID</code>) равен <code>"i"</code>;</p>
      <p>&#9633; <code>id('i')/@id</code> — соответствует атрибуту <code>id</code> элемента, уникальный атрибут которого равен <code>"i"</code>; заметим, что уникальный атрибут элемента вовсе не обязательно должен иметь имя <code>id</code>;</p>
      <p>&#9633; <code>key('name', 'html')/@href</code> — соответствует атрибуту <code>href</code> узла, значение ключа с именем <code>"name"</code> которого равно <code>"html"</code>;</p>
      <p>&#9633; <code>*|@*</code> — соответствует любому элементу или атрибуту;</p>
      <p>&#9633; <code>a|b|с</code> — соответствует элементам <code>а</code>, <code>b</code> и <code>с</code>;</p>
      <p>&#9633; <code>node()</code> — соответствует любому узлу, кроме узла атрибута и пространства имен (поскольку они не являются дочерними узлами своих родителей);</p>
      <p>&#9633; <code>node() | attribute::* | namespace::*</code> — соответствует любому узлу, включая узлы атрибутов и пространств имен;</p>
      <p>&#9633; <code>node()[not(self::text())]</code> — соответствует любому узлу, кроме текстового узла, узла атрибута и узла пространства имен.</p>
     </section>
    </section>
   </section>
   <section>
    <title>
     <p>Выражения</p>
    </title>
    <section>
     <p>Выражения XPath являются наиболее общими конструкциями этого языка. Пути выборки, разобранные ранее, — это всего лишь частный случай выражения. Выражения включают в себя арифметические и логические операции, вызов функций, операции с путями выборки и так далее.</p>
     <p>Выражениям языка соответствует нетерминал <code>Expr</code>. И хотя синтаксическое правило, определяющее этот нетерминал, записывается очень просто, в данный момент оно нам абсолютно ничего не скажет.</p>
     <p>Базовая конструкция, использующаяся в выражениях, называется первичным выражением (от англ. primary expression). Первичные выражения могут быть переменными, литералами, числами, вызовами функций, а также обычными выражениями Expr, сгруппированными в круглых скобках:</p>
     <p><code>[XP15] PrimaryExpr ::= VariableReference</code></p>
     <p><code>                       | '(' Expr ')'</code></p>
     <p><code>                       | Literal</code></p>
     <p><code>                       | Number</code></p>
     <p><code>                       | FunctionCall</code></p>
    </section>
    <section>
     <title>
      <p>Переменные</p>
     </title>
     <p>Переменные вызываются в выражениях XPath по своему имени, которому предшествует символ "<code>$</code>". Например, если мы объявили переменную <code>nodes</code>:</p>
     <p><code>&lt;xsl:variable name="nodes" select="a/b"/&gt;</code></p>
     <p>то использовать в выражениях мы ее будем как <code>$nodes</code>.</p>
     <p>Переменные, так же как элементы и атрибуты XML, могут иметь расширенные имена вида <code>QName</code>, состоящие из префикса пространства имен и локальной части имени. Это позволяет создавать переменные, принадлежащие различным пространствам имен.</p>
     <subtitle>Пример</subtitle>
     <p>Мы можем определить две переменные с одинаковыми локальными частями имен в разных пространствах, используя при определении имени префикс. Естественно, префикс должен быть заранее связан с URI пространства имен.</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:a="uri:a"</code></p>
     <p><code> xmlns:b="uri:b"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:variable name="a:elementcount" select="count(//a:*)"/&gt;</code></p>
     <p><code> &lt;xsl:variable name="b:elementcount" select="count(//b:*)"/&gt;</code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>В этом преобразовании количество элементов документа, принадлежащих пространству имен <code>а</code>, будет содержаться в переменной <code>a:elementcount</code>, а пространству имен <code>b</code> — в переменной <code>b:elementcount</code>.</p>
     <p>Отсутствие префикса в XPath-выражениях не означает, что следует использовать префикс по умолчанию. Отсутствие префикса означает, что префикс является нулевым со всеми вытекающими последствиями. Например, если шаблон</p>
     <p><code>&lt;xsl:template match="counts"&gt;</code></p>
     <p><code> &lt;xsl:value-of select="$a:elementcount"/&gt;</code></p>
     <p><code> &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code> &lt;xsl:value-of select="$b:elementcount"/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>будет корректен, в шаблоне</p>
     <p><code>&lt;xsl:template match="counts" xmlns="uri:a"&gt;</code></p>
     <p><code> &lt;xsl:value-of select="$elementcount"/&gt;</code></p>
     <p><code> &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code> &lt;xsl:value-of select="$b:elementcount"/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>процессор не сможет найти объявление переменной <code>$elementcount</code>, потому что расширенное имя объявленной переменной состоит из URI пространства имен <code>"uri:а"</code> и локальной части имени <code>elementcount</code>, а расширенное имя переменной <code>elementcount</code> состоит из нулевого URI и локальной части <code>elementcount</code>. Иными словами, эти переменные принадлежат разным пространствам.</p>
    </section>
    <section>
     <title>
      <p>Операции с булевыми значениями</p>
     </title>
     <p>XPath поддерживает только две логические операции — <code>and</code> (логическое "и") и <code>or</code> (логическое "или"). В XPath нет оператора логического отрицания, вместо него применяется функция <code>not</code>, которая возвращает "истину", если аргументом была "ложь" и наоборот.</p>
     <p>Логические операторы в XPath бинарны, то есть требуют два операнда булевого типа. Если операнды имеют другой тип, то они будут приведены к булевым значениям.</p>
     <p>Логические вычисления в XPath абсолютно стандартны. Мы приведем их для справки в табл. 6.2.</p>
     <empty-line/>
     <p><emphasis><strong>Таблица 6.2</strong>. Вычисление логических выражений</emphasis></p>
     <table>
      <tr>
       <th colspan="2" align="left">Значение</th>
       <th colspan="2" align="left">Выражение</th>
      </tr>
      <tr>
       <th align="left"><code>A</code></th>
       <th align="left"><code>B</code></th>
       <th align="left"><code>A or В</code></th>
       <th align="left"><code>A and В</code></th>
      </tr>
      <tr>
       <td align="left"><code>false</code></td>
       <td align="left"><code>false</code></td>
       <td align="left"><code>false</code></td>
       <td align="left"><code>false</code></td>
      </tr>
      <tr>
       <td align="left"><code>false</code></td>
       <td align="left"><code>true</code></td>
       <td align="left"><code>true</code></td>
       <td align="left"><code>false</code></td>
      </tr>
      <tr>
       <td align="left"><code>true</code></td>
       <td align="left"><code>false</code></td>
       <td align="left"><code>true</code></td>
       <td align="left"><code>false</code></td>
      </tr>
      <tr>
       <td align="left"><code>true</code></td>
       <td align="left"><code>true</code></td>
       <td align="left"><code>true</code></td>
       <td align="left"><code>true</code></td>
      </tr>
     </table>
     <p>Как и во многих других языках, операция "и" (<code>and</code>) старше операции "или" (<code>or</code>). Например, такое выражение, как <code>A and B or C and D or E</code> эквивалентно выражению <code>(A and В) or (С and D) or E</code>.</p>
     <p>Приведем синтаксические правила продукций логических операций XPath. Операции "или" соответствует продукция <code>OrExpr</code>, операции "и" — продукция <code>AndExpr</code>.</p>
     <p><code>[XP21] OrExpr  ::= AndExpr | OrExpr 'or' AndExpr</code></p>
     <p><code>[XP22] AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr</code></p>
    </section>
    <section>
     <title>
      <p>Операции с числами</p>
     </title>
     <section>
      <p>Перечень арифметических операций в XPath довольно ограничен. К ним относится сложение, вычитание, умножение, деление и унарная операция отрицания, которая меняет значение операнда на противоположное. Кроме того, числа можно сравнивать при помощи операторов сравнения.</p>
     </section>
     <section>
      <title>
       <p>Арифметические операции</p>
      </title>
      <p>Арифметические операции XPath сведены в табл. 6.3.</p>
      <empty-line/>
      <p><emphasis><strong>Таблица 6.3</strong>. Арифметические операции в XPath-выражениях</emphasis></p>
      <table>
       <tr>
        <th align="left">Операция</th>
        <th align="left">Синтаксис</th>
       </tr>
       <tr>
        <td align="left">Сложение</td>
        <td align="left"><code>A + B</code></td>
       </tr>
       <tr>
        <td align="left">Вычитание</td>
        <td align="left"><code>A - B</code></td>
       </tr>
       <tr>
        <td align="left">Умножение</td>
        <td align="left"><code>A * B</code></td>
       </tr>
       <tr>
        <td align="left">Деление</td>
        <td align="left"><code>A div B</code></td>
       </tr>
       <tr>
        <td align="left">Остаток деления</td>
        <td align="left"><code>A mod B</code></td>
       </tr>
       <tr>
        <td align="left">Унарное отрицание</td>
        <td align="left"><code>- A</code></td>
       </tr>
      </table>
      <p>Если операнды, значения, участвующие в операции, не являются числами, они сначала приводятся к этому типу, а уж затем производится операция. Например, можно легко перемножать литералы:</p>
      <p><code>'2' * '2' </code>&#8594;<code> 4</code></p>
      <p>Арифметические действия в XPath работают, что называется, "как обычно", то есть совершенно стандартным образом. Арифметика XPath основывается на стандарте IEEE 754, который был использован и в других распространенных языках программирования, например в Java. Пожалуй, следует лишь обратить внимание на операторы деления, поскольку в разных языках они означают разные действия и потому легко запутаться.</p>
      <p>Оператор <code>div</code> делит свой первый операнд на второй. Это не целочисленное деление, как в некоторых других языках, <code>div</code> осуществляет деление чисел с плавающей точкой. Оператор <code>div</code> аналогичен оператору деления "<code>/</code>" в таких языках, как Java, С++ и Pascal.</p>
      <p>Примеры:</p>
      <p><code>3.2 div 2.5 </code>&#8594;<code> 1.28</code></p>
      <p><code>3.2 div -2.5 </code>&#8594;<code> -1.28</code></p>
      <p><code>-3.2 div -2.5 </code>&#8594;<code> 1.28</code></p>
      <p>Оператор <code>mod</code> возвращает остаток деления первого своего оператора на второй. Поскольку в разных языках остаток деления вычисляется по-разному, легче всего будет пояснить его функционирование в XPath на примере:</p>
      <p><code>3.2 mod 2 </code>&#8594;<code> 1.2</code></p>
      <p><code>3.2 mod -2 </code>&#8594;<code> 1.2</code></p>
      <p><code>-3.2 mod 2 </code>&#8594;<code> -1.2</code></p>
      <p><code>-3.2 mod -2 </code>&#8594;<code> -1.2</code></p>
      <p>Оператор mod аналогичен оператору "<code>%</code>" в таких языках, как Java и ECMAScript.</p>
      <p>Результат остатка от деления имеет тот же знак, что и делимое. Этот факт можно использовать для того, чтобы выполнять деление без остатка, например число <code>A</code> можно нацело разделить на число <code>B</code> выражением <code>(A - (A mod B)) div B</code>.</p>
      <p>Пример:</p>
      <p><code>(3.2 - (3.2 mod 2)) div 2 </code>&#8594;<code> 1</code></p>
      <p>Во избежание ошибок следует аккуратно использовать знак вычитания в арифметических операциях. Дело в том, что синтаксис XML разрешает использовать символ "<code>-</code>" в именах элементов, которые в свою очередь также могут быть использованы в выражениях в составе путей выборки. Например, <code>A - B</code> означает разность <code>A</code> и <code>B</code>, в то время как <code>A-B</code> будет воспринято, как имя '<code>A-B</code>'. Поэтому рекомендуется выделять знак минуса пробелами.</p>
      <p>Приведем продукции выражений с арифметическими операциями.</p>
      <p>Унарному отрицанию соответствует продукция <code>UnaryExpr</code>. Как можно видеть, в текущей версии языка это — единственная унарная операция (то есть операция одного элемента).</p>
      <p><code>[XP27] UnaryExpr ::= UnionExpr | '-' UnaryExpr</code></p>
      <p>Попробуем упростить это правило, раскрыв рекурсию</p>
      <p><code>UnaryExpr ::= '-' * UnionExpr</code></p>
      <p>Таким образом, унарное отрицание можно повторять несколько раз:</p>
      <p><code>------5 </code>&#8594;<code> 5</code></p>
      <p>Умножению, делению и вычислению остатка деления соответствует одна продукция <code>MultiplicativeExpr</code>:</p>
      <p><code>[XP26] MultiplicativeExpr ::= UnaryExpr</code></p>
      <p><code>                              | MultiplicativeExpr MultiplyOperator UnaryExpr</code></p>
      <p><code>                              | MultiplicativeExpr 'div' UnaryExpr</code></p>
      <p><code>                              | MultiplicativeExpr 'mod' UnaryExpr</code></p>
      <p>Оператор умножения вынесен в отдельное правило:</p>
      <p><code>[XP34] MultiplyOperator ::= '*'</code></p>
      <p>Сложению и вычитанию соответствует правило <code>AdditiveExpr</code>:</p>
      <p><code>[XP25] AdditiveExpr ::= MultiplicativeExpr</code></p>
      <p><code>                        | AdditiveExpr '+' MultiplicativeExpr</code></p>
      <p><code>                        | AdditiveExpr '-' MultiplicativeExpr</code></p>
     </section>
     <section>
      <title>
       <p>Операции сравнения</p>
      </title>
      <p>XPath позволяет сравнивать числа при помощи операторов, перечисленных в табл. 6.4.</p>
      <empty-line/>
      <p><emphasis><strong>Таблица 6.4</strong>. Операторы сравнения</emphasis></p>
      <table>
       <tr>
        <th align="left">Оператор</th>
        <th align="left">Значение</th>
       </tr>
       <tr>
        <td align="left"><code>=</code></td>
        <td align="left">Равно</td>
       </tr>
       <tr>
        <td align="left"><code>!=</code></td>
        <td align="left">Не равно</td>
       </tr>
       <tr>
        <td align="left"><code>&lt;</code></td>
        <td align="left">Меньше</td>
       </tr>
       <tr>
        <td align="left"><code>&gt;</code></td>
        <td align="left">Больше</td>
       </tr>
       <tr>
        <td align="left"><code>&lt;=</code></td>
        <td align="left">Меньше или равно (не больше)</td>
       </tr>
       <tr>
        <td align="left"><code>&gt;=</code></td>
        <td align="left">Больше или равно (не меньше)</td>
       </tr>
      </table>
      <p>XPath-выражения чаще всего используются в значениях атрибутов, символ "<code>&lt;</code>" в которых в соответствии с синтаксисом XML использовать нельзя. Поэтому операторы сравнения "меньше" ("<code>&lt;</code>") и "не больше" ("<code>&lt;=</code>") нужно записывать с использованием сущностей. Оператор "меньше" может быть записан как "<code>&amp;lt</code>;", а оператор "не больше" как "<code>&amp;lt;=</code>".</p>
      <subtitle>Пример</subtitle>
      <p>Результатом обработки элемента</p>
      <p><code>&lt;xsl:value-of select="1&amp;lt;2"/&gt;</code></p>
      <p>будет строка "<code>true</code>".</p>
      <p>Сравнение всегда требует наличия двух операндов числового типа. Если операнды не являются числами, они будут соответствующим образом преобразованы.</p>
      <p>В XPath вполне корректным будет выражение вида <code>A &gt; B &gt; C</code>. Однако результат его будет довольно неожиданным. В XPath действует правило левой ассоциативности операторов сравнения, поэтому <code>A &gt; B &gt; C</code> будет равносильно <code>(А &gt; B) &gt; C</code>. То есть <code>A</code> будет сравнено с <code>B</code>, затем результат, истина или ложь, будет преобразован в числовой тип (получится <code>1</code> или <code>0</code>) и затем сравнен со значением <code>C</code>.</p>
      <p>Пример:</p>
      <p><code>3 &gt; 2 &gt; 1 </code>&#8594;<code> (3 &gt; 2) &gt; 1 </code>&#8594;<code> 1 &gt; 1 </code>&#8594;<code> false</code></p>
      <p><code>3 &gt; 2 &gt; 0 </code>&#8594;<code> (3 &gt; 2) &gt; 0 </code>&#8594;<code> 1 &gt; 0 </code>&#8594;<code> true</code></p>
      <p>Неравенствам в XPath соответствует продукция <code>RelationalExpr</code>:</p>
      <p><code>[XP24] RelationalExpr ::= AdditiveExpr</code></p>
      <p><code>                          | RelationalExpr '&lt;' AdditiveExpr</code></p>
      <p><code>                          | RelationalExpr '&gt;' AdditiveExpr</code></p>
      <p><code>                          | RelationalExpr '&lt;=' AdditiveExpr</code></p>
      <p><code>                          | RelationalExpr '&gt;=' AdditiveExpr</code></p>
      <p>Операции "равно" и "не равно" записываются при помощи продукции</p>
      <p><code>EqualityExpr:</code></p>
      <p><code>[XP23] EqualityExpr ::= RelationalExpr</code></p>
      <p><code>                        | EqualityExpr '=' RelationalExpr</code></p>
      <p><code>                        | EqualityExpr '!=' RelationalExpr</code></p>
     </section>
    </section>
    <section>
     <title>
      <p>Операции с множествами узлов</p>
     </title>
     <section>
      <p>Три основные операции с множествами узлов, которые поддерживает язык XPath, — это фильтрация множества, выборка с использованием путей и объединение.</p>
     </section>
     <section>
      <title>
       <p>Фильтрация</p>
      </title>
      <p>Множества узлов, которые получаются в результате вычисления выражений, можно фильтровать — то есть выбирать из них узлы, удовлетворяющие заданным свойствам подобно тому, как это делалось предикатами в шагах выборки.</p>
      <p>В выражениях множества узлов могут также фильтроваться одним или несколькими предикатами. Узел остается в фильтруемом множестве, только если он удовлетворяет всем предикатам поочередно.</p>
      <subtitle>Пример</subtitle>
      <p>Предположим, что нам нужно оставить в фильтруемом множестве узлов, которое присвоено переменной <code>nodes</code>, только те узлы, которые имеют имя <code>а</code> и атрибут <code>href</code>. Искомое выражение может быть записано следующим образом:</p>
      <p><code>$nodes[self::а][@href]</code></p>
      <p>Можно использовать и более сложные конструкции, например, фильтровать объединение двух множеств — присвоенного переменной <code>nodes</code> и возвращаемого путем выборки <code>body/*</code>:</p>
      <p><code>($nodes|body/*)[self::a][@href]</code></p>
      <p>Выражение, в котором производится фильтрация узлов, отвечает EBNF-правилу <code>FilterExpr</code>:</p>
      <p><code>[XP20] FilterExpr ::= PrimaryExpr | FilterExpr Predicate</code></p>
      <p>Если раскрыть рекурсию, которая имеется в этом правиле, его можно переписать в более простом виде:</p>
      <p><code>FilterExpr ::= PrimaryExpr Predicate*</code></p>
      <p>Выражение <code>PrimaryExpr</code>, которое используется в этой продукции, должно обязательным образом возвращать множество узлов. В противном случае процессор выдаст ошибку, потому что никакой другой тип не может быть преобразован во множество узлов.</p>
     </section>
     <section>
      <title>
       <p>Использование в выражениях путей выборки</p>
      </title>
      <p>Помимо того, что выражение само по себе может быть путем выборки, относительные пути можно комбинировать с другими выражениями. Например, можно выбрать все дочерние элементы узлов множества, содержащегося в переменной</p>
      <p><code>$nodes/*</code></p>
      <p>Для разделения шагов выборки в фильтрующих выражениях можно использовать операторы "<code>/</code>" и "<code>//</code>". Например, для того, чтобы получить всех потомков узлов из множества, присвоенного переменной, можно использовать выражение вида</p>
      <p><code>$nodes//node()</code></p>
      <p>Здесь <code>node()</code> — это тест узла, выполняющийся для всех типов узлов, а <code>//</code>, как и обычно, сокращение от <code>/descendant-or-self:node()/</code>.</p>
      <p>Выражения, которые используют пути выборки, соответствуют продукции <code>PathExpr</code>:</p>
      <p><code>[XP19] PathExpr ::= LocationPath</code></p>
      <p><code>                    | FilterExpr</code></p>
      <p><code>                    | FilterExpr '/' RelativeLocationPath</code></p>
      <p><code>                    | FilterExpr '//' RelativeLocationPath</code></p>
     </section>
     <section>
      <title>
       <p>Объединение множеств</p>
      </title>
      <p>Множества могут быть объединены при помощи оператора "<code>|</code>". В объединение будут входить узлы, которые присутствуют хотя бы в одном из множеств, причем результат не содержит повторений. Объединять можно любые выражения, результатом вычисления которых являются множества узлов.</p>
      <subtitle>Пример</subtitle>
      <p>Множество всех элементов <code>а</code>, <code>b</code> и <code>с</code> документа может быть задано выражением <code>//a|//b|//c</code>.</p>
      <p>Выражению объединения соответствует продукция <code>UnionExpr</code>:</p>
      <p><code>[XP18] UnionExpr ::= PathExpr | UnionExpr '|' PathExpr</code></p>
     </section>
    </section>
    <section>
     <title>
      <p>Старшинство операций</p>
     </title>
     <p>Теперь, когда мы изучили все типы операций XPath, можно дать синтаксическое определение выражению и выстроить все операции в порядке старшинства.</p>
     <p>Выражению, как самой общей конструкции XPath, соответствует продукция <code>Expr</code>, которая определяется следующим образом:</p>
     <p><code>[XP14] Expr ::= OrExpr</code></p>
     <p>То есть, фактически, выражение в XPath определяется через логическое выражение. Естественно, выражения не обязаны быть логическими. Просто в иерархии синтаксических правил логическое выражение "или" находится выше всего. Верхние правила определяются через более примитивные правила и так далее. В итоге иерархия выражений выстраивается следующим образом (в скобках приведены названия EBNF-правил):</p>
     <p>&#9633; выражения (<code>Expr</code>);</p>
     <p>&#9633; логические выражения "или" (<code>OrExpr</code>);</p>
     <p>&#9633; логические выражения "и" (<code>AndExpr</code>);</p>
     <p>&#9633; выражения равенства и неравенства (<code>EqualityExpr</code>);</p>
     <p>&#9633; выражения сравнения (<code>RelationalExpr</code>);</p>
     <p>&#9633; выражения сложения и вычитания (<code>AdditiveExpr</code>);</p>
     <p>&#9633; выражения умножения и деления (<code>MultiplicativeExpr</code>);</p>
     <p>&#9633; унарные выражения (<code>UnaryExpr</code>);</p>
     <p>&#9633; выражения объединения множеств (<code>UnionExpr</code>);</p>
     <p>&#9633; выражения путей выборки (<code>PathExpr</code>);</p>
     <p>&#9633; пути выборки (<code>LocationPath</code>), фильтрация множеств (<code>FilterExpr</code>), относительные пути выборки (<code>RelativeLocationPath</code>).</p>
     <p>По этой схеме несложно выяснить старшинство операций — чем ниже выражение находится в этой иерархии, тем выше его приоритет. Для полной ясности, перечислим операции в порядке старшинства от старших, с большим приоритетом, к младшим, с меньшим приоритетом выполнения:</p>
     <p>&#9633; операции с путями выборки;</p>
     <p>&#9633; операция объединения множеств (<code>|</code>);</p>
     <p>&#9633; унарная операция отрицания (<code>-</code>);</p>
     <p>&#9633; умножение, деление и вычисление остатка от деления (<code>*</code>, <code>div</code> и <code>mod</code>);</p>
     <p>&#9633; операции сложения и вычитания (<code>+</code> и <code>-</code>);</p>
     <p>&#9633; операции сравнения (<code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>, <code>=&gt;</code>);</p>
     <p>&#9633; операции проверки равенства и неравенства (<code>=</code> и <code>!=</code>);</p>
     <p>&#9633; операция "и" (<code>and</code>);</p>
     <p>&#9633; операция "или" (<code>or</code>).</p>
     <p>Операции одного порядка имеют левую ассоциативность, как это было показано на примере с операциями сравнения (<code>3 &gt; 2 &gt; 1</code> равносильно <code>(3 &gt; 2) &gt;1</code>).</p>
    </section>
   </section>
   <section>
    <title>
     <p>Функции</p>
    </title>
    <section>
     <p>Кроме операций, которые обеспечивают примитивные базовые действия, в XPath можно использовать функции. Спецификация языка XPath определяет <emphasis>базовую библиотеку функций</emphasis>, которую должны поддерживать все XSLT-процессоры. В XSLT эта библиотека дополняется еще несколькими полезными функциями. Кроме этого, большинство процессоров реализуют механизм расширений, при помощи которого можно использовать в XSLT собственные функции.</p>
     <p>В этой главе мы будем рассматривать только функции базовой библиотеки XPath. Функции, которые добавляются в XSLT, будут разбираться чуть позже, а функции-расширения и их создание вообще является достаточно сложной темой, вынесенной в отдельную главу.</p>
     <p>Прежде, чем разбирать функции, рассмотрим синтаксис их вызова. Он описывается правилом <code>FunctionCall</code>:</p>
     <p><code>[XP16] FunctionCall ::= FunctionName</code></p>
     <p><code>                        '(' ( Argument ( ',' Argument )* )? ')'</code></p>
     <p>Таким образом, вызов функции состоит из имени и перечисленных в круглых скобках аргументов, которых может в принципе и не быть. С точки зрения синтаксиса аргументом функции может быть любое выражение, однако на практике функции предъявляют к своим аргументам определенные требования. Мы будем записывать правила вызова той или иной функции прототипом вида</p>
     <p><code><emphasis>тип1 </emphasis><strong>функция</strong>(<emphasis>тип2</emphasis>, <emphasis>тип3</emphasis>, <emphasis>тип4</emphasis>?)</code></p>
     <p>где <code><emphasis>тип1</emphasis></code> — тип возвращаемого значения, <code><emphasis>тип2</emphasis></code>, <code><emphasis>тип3</emphasis></code>, <code><emphasis>тип4</emphasis></code> — типы передаваемых параметров, символ "<code>?</code>" обозначает аргумент, который может быть опущен. Также может быть использован символ <code>*</code> для обозначения аргумента, который может повторяться несколько раз. Например,</p>
     <p><code><emphasis>string <strong>concat</strong>(string, string, string*)</emphasis></code></p>
     <p>определяет функцию <code>concat</code>, которая возвращает строку, а на вход принимает два или более строковых параметра.</p>
     <p>Аргументы функции отвечают EBNF-продукции <code>Argument</code>:</p>
     <p><code>[XP17] Argument ::= Expr</code></p>
     <p>Имя функции определяется синтаксическим правилом <code>FunctionName</code>. Функция может иметь любое корректное с точки зрения XML имя, кроме названий типов узлов (<code>comment</code>, <code>processing-instruction</code>, <code>text</code> и <code>node</code>):</p>
     <p><code>[XP35] FunctionName ::= QName - NodeType</code></p>
     <p>В базовой библиотеке XPath выделяют четыре типа функций: функции для работы с булевыми значениями, с числами, со строками и с множествами узлов.</p>
    </section>
    <section>
     <title>
      <p>Булевые функции</p>
      <p>Функция<emphasis> boolean</emphasis></p>
     </title>
     <section>
      <p><code><emphasis>boolean </emphasis><strong>boolean</strong>(<emphasis>object</emphasis>)</code></p>
      <p>Функция <code>boolean</code> явным образом преобразует объект, который ей передается в булевый тип в соответствии с правилами, изложенными <emphasis>в главе "Типы данных XPath"</emphasis>. Напомним вкратце эти правила.</p>
      <p>&#9633; Число преобразуется в "ложь", если оно является положительным или отрицательным нулем или не-числом (<code>NaN</code>). В противном случае число будет преобразовано в "истину".</p>
      <p>&#9633; Строка преобразуется в "ложь", если она не содержит символов, то есть, ее длина равна нулю. Непустая строка преобразуется в "истину".</p>
      <p>&#9633; Множество узлов преобразуется в "ложь", если оно пусто. Непустое множество узлов преобразуется в "истину".</p>
      <p>&#9633; Объекты других типов преобразуются в булевые значения по собственным правилам. Например, результирующий фрагмент дерева всегда преобразуется в "истину".</p>
      <p>Примеры:</p>
      <p><code>boolean(2-2) </code>&#8594;<code> false</code></p>
      <p><code>boolean(number('two')) </code>&#8594;<code> false</code></p>
      <p><code>boolean(-1) </code>&#8594;<code> true</code></p>
      <p><code>boolean(1 div 0) </code>&#8594;<code> true</code></p>
      <p><code>boolean(-1 div (1 div 0)) </code>&#8594;<code> false</code></p>
      <p><code>boolean(-1 div (-1 div 0)) </code>&#8594;<code> false</code></p>
      <p><code>boolean(-1 div (-1 div 0) +1) </code>&#8594;<code> true</code></p>
      <p><code>boolean('') </code>&#8594;<code> false</code></p>
      <p><code>boolean('true') </code>&#8594;<code> true</code></p>
      <p><code>boolean('false') </code>&#8594;<code> true</code></p>
      <p><code>boolean(/) </code>&#8594;<code> true</code></p>
      <p>Это выражение всегда будет обращаться в <code>true</code>, поскольку у документа всегда есть корневой узел.</p>
      <p><code>boolean(/self::node()) </code>&#8594;<code> true</code></p>
      <p>Это выражение также обратится в <code>true</code>, поскольку корневой узел соответствует тесту <code>node()</code>.</p>
      <p><code>boolean(/self::text()) </code>&#8594;<code> false</code></p>
      <p>Это выражение обратится в <code>false</code>, поскольку корневой узел не является текстовым узлом.</p>
     </section>
     <section>
      <title>
       <p>Функция<emphasis> not</emphasis></p>
      </title>
      <p><code><emphasis>boolean </emphasis><strong>not</strong>(<emphasis>boolean</emphasis>)</code></p>
      <p>Функция <code>not</code> выполняет логическое отрицание. Если аргументом была "истина", <code>not</code> возвращает "ложь", если аргумент был "ложью", <code>not</code> вернет "истину". Если функции был передан аргумент не булевого типа (например, число), то он сначала будет сконвертирован в тип <code>boolean</code>.</p>
      <p>Примеры:</p>
      <p><code>not(false) </code>&#8594;<code> true</code></p>
      <p><code>not(true) </code>&#8594;<code> false</code></p>
      <p><code>not('false') </code>&#8594;<code> false</code></p>
      <p><code>not('true') </code>&#8594;<code> false</code></p>
      <p><code>not(0) </code>&#8594;<code> true</code></p>
      <p><code>not(/) </code>&#8594;<code> false</code></p>
     </section>
     <section>
      <title>
       <p>Функции <emphasis>true</emphasis> и <emphasis>false</emphasis></p>
      </title>
      <p><code><emphasis>boolean </emphasis><strong>true</strong>()</code></p>
      <p><code><emphasis>boolean </emphasis><strong>false</strong>()</code></p>
      <p>Две функции <code>true</code> и <code>false</code> возвращают тождественную "истину" и тождественную "ложь" соответственно. В XPath нет констант и, тем более, логических констант, определяющих "истину" и "ложь", как в других языках. Функции <code>true</code> и <code>false</code> восполняют эту нехватку.</p>
      <p>Примеры:</p>
      <p><code>true() or $var </code>&#8594;<code> true</code></p>
      <p>Это выражение всегда будет истинным вне зависимости от значения переменной <code>var</code>, поскольку дизъюнкция (логическая операция "или") с тождественной "истиной" всегда будет "истиной".</p>
      <p><code>false() and $var </code>&#8594;<code> false</code></p>
      <p>Это выражение всегда будет ложным вне зависимости от значения переменной <code>var</code>, поскольку конъюнкция (логическая операция "и") с тождественной "ложью" всегда будет "ложью".</p>
     </section>
     <section>
      <title>
       <p>Функция<emphasis> lang</emphasis></p>
      </title>
      <p><code><emphasis>boolean </emphasis><strong>lang</strong>(<emphasis>string</emphasis>)</code></p>
      <p>Функция <code>lang</code> может использоваться для того, чтобы определить языковой контекст контекстного узла. В элементах XML можно использовать атрибут <code>lang</code> пространства имен <code>xml</code> для определения языка содержимого узла, например;</p>
      <p><code>&lt;text xml:lang="en-gb"&gt;</code></p>
      <p><code>Yet no living human being have been ever blessed with seeing...</code></p>
      <p><code>&lt;/text&gt;</code></p>
      <p>Пространство имен, соответствующее префиксу <code>xml</code>, не требуется объявлять. Это служебное пространство имен, которое неявно задано во всех XML-документах.</p>
      <p>Функция <code>lang</code> возвратит "истину", если идентификатор языка, который передан ей в виде строкового параметра, соответствует языковому контексту контекстного узла. Это определяется следующим образом.</p>
      <p>&#9633; Если ни один из предков контекстного узла не имеет атрибута <code>xml:lang</code>, функция возвращает "ложь".</p>
      <p>&#9633; Иначе строковый параметр проверяется на соответствие значению атрибута <code>xml:lang</code> ближайшего предка. Если эти значения равны в любом регистре символов, или атрибут начинается как значение параметра функции и имеет суффикс, начинающийся знаком "<code>-</code>", функция возвращает "истину".</p>
      <p>&#9633; В противном случае функция возвращает "ложь".</p>
      <p>Примеры:</p>
      <p>Функция <code>lang('en')</code> возвратит "истину" в контексте любого из следующих элементов:</p>
      <p><code>&lt;body xml:lang="EN"/&gt;</code></p>
      <p><code>&lt;body xml:lang="en-GB"/&gt;</code></p>
      <p><code>&lt;body xml:lang="en-us"/&gt;</code></p>
      <p><code>&lt;body xml:lang="EN-US"/&gt;</code></p>
      <p>Функция <code>lang('de')</code> возвратит "истину" в контексте элемента <code>b</code> и "ложь" — в контексте элементов <code>а</code> и <code>с</code>:</p>
      <p><code>&lt;а&gt;</code></p>
      <p><code> &lt;b xml:lang="de"&gt;</code></p>
      <p><code>  &lt;c xml:lang="en"/&gt;</code></p>
      <p><code> &lt;/b&gt;</code></p>
      <p><code>&lt;/a&gt;</code></p>
     </section>
    </section>
    <section>
     <title>
      <p>Числовые функции</p>
     </title>
     <section>
      <title>
       <p>Функция<emphasis> number</emphasis></p>
      </title>
      <p><code><emphasis>number </emphasis><strong>number</strong>(<emphasis>object</emphasis>?)</code></p>
      <p>Функция <code>number</code> явным образом конвертирует свой аргумент в числовой тип. Если аргумент не указан, функции передается множество узлов, состоящее из единственного контекстного узла. Коротко напомним правила преобразования в числовой тип.</p>
      <p>&#9633; Значения булевого типа преобразуются в <code>0</code> или <code>1</code> следующим образом: "ложь" преобразуется в <code>0</code>, "истина" в <code>1</code>.</p>
      <p>&#9633; Строковое значение преобразуется в число, которое оно представляет.</p>
      <p>&#9633; Множество узлов сначала преобразуется в строку, а затем, как строка в число. Фактически численным значением множества узлов является численное значение его первого узла.</p>
      <p>&#9633; Объекты других типов преобразуются в число в соответствии с собственными правилами. Например, результирующий фрагмент дерева так же как и множество узлов сначала преобразуется к строке, а затем в численный формат.</p>
      <subtitle>Примеры</subtitle>
      <p><code>number($to_be or not($to_be)) </code>&#8594;<code> 1</code></p>
      <p>Значение этого выражения будет <code>1</code>, поскольку <code>$to_be or not($to_be)</code> будет истинным вне зависимости от значения переменной <code>to_be</code>.</p>
      <p><code>number(false()) </code>&#8594;<code> 0</code></p>
      <p><code>number('00015.0001000') </code>&#8594;<code> 15.0001</code></p>
      <p><code>number('.0001000') </code>&#8594;<code> 0.0001</code></p>
      <p><code>number('1.') </code>&#8594;<code> 1</code></p>
      <p><code>number('-.1') </code>&#8594;<code> -0.1</code></p>
      <p><code>number('-5') </code>&#8594;<code> -5</code></p>
     </section>
     <section>
      <title>
       <p>Функция<emphasis> sum</emphasis></p>
      </title>
      <p><code><emphasis>number </emphasis><strong>sum</strong>(<emphasis>node-set</emphasis>)</code></p>
      <p>Функция <code>sum</code> суммирует значения узлов из переданного ей множества. Строковые значения узлов сначала преобразуются в числа, а затем все полученные числа складываются.</p>
      <subtitle>Пример</subtitle>
      <subtitle>Листинг 6.3. Входящий документ</subtitle>
      <p><code>&lt;list&gt;</code></p>
      <p><code> &lt;item&gt;1&lt;/item&gt;</code></p>
      <p><code> &lt;item&gt;3&lt;/item&gt;</code></p>
      <p><code> &lt;item&gt;5&lt;/item&gt;</code></p>
      <p><code>&lt;/list&gt;</code></p>
      <subtitle>Листинг 6.4. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
      <p><code> version="1.0"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="list"&gt;</code></p>
      <p><code>  &lt;xsl:copy&gt;</code></p>
      <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
      <p><code>  &lt;/xsl:copy&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="item"&gt;</code></p>
      <p><code>  &lt;sum&gt;</code></p>
      <p><code>   &lt;xsl:value-of select="sum(preceding-sibling::item|.)"/&gt;</code></p>
      <p><code>  &lt;/sum&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 6.5. Результат</subtitle>
      <p><code>&lt;list&gt;</code></p>
      <p><code> &lt;sum&gt;1&lt;/sum&gt;</code></p>
      <p><code> &lt;sum&gt;4&lt;/sum&gt;</code></p>
      <p><code> &lt;sum&gt;9&lt;/sum&gt;</code></p>
      <p><code> &lt;sum&gt;16&lt;/sum&gt;</code></p>
      <p><code> &lt;sum&gt;25&lt;/sum&gt;</code></p>
      <p><code>&lt;/list&gt;</code></p>
      <p>В этом преобразовании мы заменяем каждый элемент <code>item</code> на сумму значений предшествующих ему элементов плюс собственное значение. Предшествующие элементы выбираются путем выборки <code>preceding-sibling::item</code>, текущий элемент — сокращенным путем "<code>.</code>", затем эти два множества объединяются при помощи оператора <code>|</code>, и, наконец, мы вычисляем сумму значений узлов, входящих в них функцией <code>sum</code>.</p>
      <p>Строковые значения суммируемых узлов преобразовываются в числовой формат так же, как они преобразовывались бы функцией <code>number</code>. Например, если входящий документ будет иметь вид</p>
      <p><code>&lt;list&gt;</code></p>
      <p><code> &lt;item&gt;1&lt;/item&gt;</code></p>
      <p><code> &lt;item&gt;3&lt;/item&gt;</code></p>
      <p><code> &lt;item&gt;five&lt;/item&gt;</code></p>
      <p><code> &lt;item&gt;7&lt;/item&gt;</code></p>
      <p><code> &lt;item&gt;9&lt;/item&gt;</code></p>
      <p><code>&lt;/list&gt;</code></p>
      <p>то на выходе мы получим</p>
      <p><code>&lt;list&gt;</code></p>
      <p><code> &lt;sum&gt;1&lt;/sum&gt;</code></p>
      <p><code> &lt;sum&gt;4&lt;/sum&gt;</code></p>
      <p><code> &lt;sum&gt;NaN&lt;/sum&gt;</code></p>
      <p><code> &lt;sum&gt;NaN&lt;/sum&gt;</code></p>
      <p><code> &lt;sum&gt;NaN&lt;/sum&gt;</code></p>
      <p><code>&lt;/list&gt;</code></p>
      <p>потому что, начиная с третьего элемента, в суммировании будет участвовать значение <code>number('five')</code>, то есть не-число (<code>NaN</code>).</p>
     </section>
     <section>
      <title>
       <p>Функции <emphasis>floor</emphasis> и <emphasis>ceiling</emphasis></p>
      </title>
      <p><code><emphasis>number </emphasis><strong>floor</strong>(<emphasis>number</emphasis>)</code></p>
      <p><code><emphasis>number </emphasis><strong>ceiling</strong>(<emphasis>number</emphasis>)</code></p>
      <p>Функции <code>floor</code> и <code>ceiling</code> (англ. пол и потолок соответственно) осуществляют округление численного аргумента до ближайшего не большего и ближайшего не меньшего целого соответственно.</p>
      <subtitle>Примеры</subtitle>
      <p><code>floor(2.3) </code>&#8594;<code> 2</code></p>
      <p><code>ceiling(2.3) </code>&#8594;<code> 3</code></p>
      <p><code>floor(-2.3) </code>&#8594;<code> -3</code></p>
      <p><code>ceiling(-2.3) </code>&#8594;<code> -2</code></p>
      <p><code>floor(-1 div 0) </code>&#8594;<code> -Infinity</code></p>
      <p><code>ceiling(-1 div 0) </code>&#8594;<code> -Infinity</code></p>
      <p><code>floor('zero') </code>&#8594;<code> NaN</code></p>
      <p><code>ceiling(-1 div (-1 div 0)) </code>&#8594;<code> 0</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>round</emphasis></p>
      </title>
      <p><code><emphasis>number </emphasis><strong>round</strong>(<emphasis>number</emphasis>)</code></p>
      <p>Функция <code>round</code> округляет число до ближайшего целого значения. У этой функции есть несколько нюансов, которые мы сейчас разберем.</p>
      <p>&#9633; Если дробная часть числа равна 0.5, то функция вернет ближайшее большее целое.</p>
      <p>&#9633; Если аргумент является не-числом (NaN), то результат также будет NaN.</p>
      <p>&#9633; Если аргумент является положительной или отрицательной бесконечностью, то результатом будет тоже положительная или отрицательная бесконечность, то есть аргумент не изменится.</p>
      <p>&#9633; Если аргумент является положительным или отрицательным нулем, результатом будет также положительный или отрицательный нуль, то есть аргумент не изменится.</p>
      <p>&#9633; Если аргумент меньше нуля, но больше или равен — 0.5, результатом будет отрицательный нуль.</p>
      <subtitle>Примеры</subtitle>
      <p><code>round(2.5) </code>&#8594;<code> 3</code></p>
      <p><code>round(2.49) </code>&#8594;<code> 2</code></p>
      <p><code>round(-1.7) </code>&#8594;<code> -2</code></p>
      <p><code>1 div round(0.5) </code>&#8594;<code> Infinity</code></p>
      <p><code>1 div round(-0.5) </code>&#8594;<code> -Infinity</code></p>
      <p><code>round(1 div 0) </code>&#8594;<code> Infinity</code></p>
      <p><code>round('one') </code>&#8594;<code> NaN</code></p>
     </section>
    </section>
    <section>
     <title>
      <p>Строковые функции</p>
     </title>
     <section>
      <title>
       <p>Функция<emphasis> string</emphasis></p>
      </title>
      <p><code><emphasis>string </emphasis><strong>string</strong>(<emphasis>object</emphasis>?)</code></p>
      <p>Подобно функциям <code>boolean</code> и <code>number</code>, функция <code>string</code> преобразует свой аргумент к строковому типу явным образом. Если аргумент опущен, функции передается множество узлов, состоящее из единственного контекстного узла.</p>
      <p>Напомним вкратце правила приведения других типов к строке.</p>
      <p>&#9633; Булевые значения преобразуются в строку следующим образом:</p>
      <p> • "истина" (<code>true</code>) преобразуется в строку "<code>true</code>";</p>
      <p> • "ложь" (<code>false</code>) преобразуется в строку "<code>false</code>".</p>
      <p>&#9633; Числа преобразуются к строковому виду следующим образом:</p>
      <p> • не-число (<code>NaN</code>) преобразуется в строку "<code>NaN</code>";</p>
      <p> • положительный нуль преобразуется в строку "<code>0</code>";</p>
      <p> • отрицательный нуль преобразуется в строку "<code>0</code>";</p>
      <p> • положительная бесконечность преобразуется в строку "<code>Infinity</code>";</p>
      <p> • отрицательная бесконечность преобразуется в строку "<code>-Infinity</code>";</p>
      <p> • положительные целые преобразуются в свое десятичное представление без ведущих нулей и без точки ("<code>.</code>"), отделяющей дробную часть от целой;</p>
      <p> • отрицательные целые преобразуются так же, как и положительные, но с начальным знаком "минус" ("<code>-</code>");</p>
      <p> • остальные числа преобразуются в десятичное представление с использованием точки ("<code>.</code>"), отделяющей целую часть от дробной части; целая часть не содержит ведущих нулей (кроме случая с числами в интервале (-1;1)), дробная часть содержит столько цифр, сколько требуется для точного представления числа.</p>
      <p>&#9633; Множество узлов преобразуется в строковое значение своего первого в порядке просмотра документа узла. Если множество пусто, функция возвращает пустую строку.</p>
      <p>&#9633; Объекты других типов преобразуются в строку в соответствии с собственными правилами. Например, результирующий фрагмент дерева преобразуется в конкатенацию всех своих строковых узлов.</p>
      <subtitle>Примеры</subtitle>
      <p><code>string(boolean(0)) </code>&#8594;<code> false</code></p>
      <p><code>string(number('zero')) </code>&#8594;<code> NaN</code></p>
      <p><code>string(number('.50000')) </code>&#8594;<code>0.5</code></p>
      <p><code>string(number(00500.)) </code>&#8594;<code> 500</code></p>
      <p>Для строкового форматирования чисел рекомендуется использовать функцию XSLT <code>format-number</code> совместно с элементом <code>xsl:decimal-format</code>.</p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>concat</emphasis></p>
      </title>
      <p><code><emphasis>string </emphasis><strong>concat</strong>(<emphasis>string</emphasis>, <emphasis>string</emphasis>, <emphasis>string</emphasis>*)</code></p>
      <p>Функция <code>concat</code> принимает на вход две или более строки и возвращает конкатенацию (строковое сложение) своих аргументов.</p>
      <p>Пример:</p>
      <p><code>concat('not','with','standing',' problem') </code>&#8594;<code> 'notwithstanding problem'</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>starts-with</emphasis></p>
      </title>
      <p><code><emphasis>boolean </emphasis><strong>starts-with</strong>(<emphasis>string</emphasis>, <emphasis>string</emphasis>)</code></p>
      <p>Функция <code>starts-with</code> принимает на вход два строковых аргумента и возвращает <code>true</code>, если первая строка начинается второй и <code>false</code> в противном случае.</p>
      <p><code>starts-with('http://www.xsltdev.ru', 'http') </code>&#8594;<code> true</code></p>
      <p><code>starts-with('Title', 'ti') </code>&#8594;<code> false</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>contains</emphasis></p>
      </title>
      <p><code><emphasis>boolean </emphasis><strong>contains</strong>(<emphasis>string</emphasis>, <emphasis>string</emphasis>)</code></p>
      <p>Функция <code>contains</code> принимает на вход два строковых аргумента и возвращает <code>true</code>, если первая строка содержит вторую и <code>false</code> в противном случае.</p>
      <p><code>contains('address@host.com', '(@') </code>&#8594;<code> true</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>substring-before</emphasis></p>
      </title>
      <p><code><emphasis>string </emphasis><strong>substring-before</strong>(<emphasis>string</emphasis>, <emphasis>string</emphasis>)</code></p>
      <p>Функция <code>substring-before</code> принимает на вход два строковых аргумента. Эта функция находит в первой строке вторую и возвращает подстроку, которая ей предшествует. Если вторая строка не содержится в первой, функция вернет пустую строку.</p>
      <subtitle>Примеры</subtitle>
      <p><code>substring-before('12-May-1998', '-') </code>&#8594;<code> '12'</code></p>
      <p><code>substring-before('12 May 1998', ' ') </code>&#8594;<code> '12'</code></p>
      <p><code>substring-before('12 May 1998', '&amp;#32;') </code>&#8594;<code> '12'</code></p>
      <p><code>substring-before('12 May 1998', '-') </code>&#8594;<code> ''</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>substring-after</emphasis></p>
      </title>
      <p><code><emphasis>string </emphasis><strong>substring-after</strong>(<emphasis>string</emphasis>, <emphasis>string</emphasis>)</code></p>
      <p>Эта функция аналогична функции <code>substring-before</code>, только она возвращает строку, которая следует за вторым аргументом. Если вторая строка не содержится в первой, эта функция также вернет пустую строку.</p>
      <subtitle>Примеры</subtitle>
      <p><code>substring-after('12-May-1998', '-') </code>&#8594;<code> 'May-1998'</code></p>
      <p><code>substring-after('12 May 1998', ' ') </code>&#8594;<code> 'May 1998'</code></p>
      <p><code>substring-after('12 May 1998', '&amp;#32;') </code>&#8594;<code> 'May 1998'</code></p>
      <p><code>substring-after('12 May 1998', '-') </code>&#8594;<code> ''</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>substring</emphasis></p>
      </title>
      <p><code><emphasis>string </emphasis><strong>substring</strong>(<emphasis>string</emphasis>, <emphasis>number</emphasis>, <emphasis>number</emphasis>?)</code></p>
      <p>Функция <code>substring</code> возвращает подстроку переданного ей строкового аргумента, которая начинается с позиции, указанной вторым аргументом и длиной, указанной третьим аргументом. Если третий аргумент опущен, подстрока продолжается до конца строки. Если численные аргументы являются нецелыми, они округляются при помощи функции <code>round</code>.</p>
      <p>В XPath позицией первого символа является <code>1</code>, а не <code>0</code>, как в некоторых других языках программирования.</p>
      <p>При вычислении подстроки учитываются следующие условия.</p>
      <p>&#9633; Если первый численный аргумент меньше <code>1</code> (это относится и к отрицательной бесконечности), то подстрока начинается с начала строки.</p>
      <p>&#9633; Если первый численный аргумент больше длины строки (это относится и к положительной бесконечности), то подстрока будет пустой.</p>
      <p>&#9633; Если второй численный аргумент меньше <code>1</code> (это относится и к отрицательной бесконечности), то подстрока будет пустой.</p>
      <p>&#9633; Если второй численный аргумент, сложенный с первым, больше длины строки плюс один, подстрока будет продолжаться до конца строки.</p>
      <subtitle>Примеры</subtitle>
      <p><code>substring('123456', 2, 3) </code>&#8594;<code> '234'</code></p>
      <p><code>substring('123456', 2, 5) </code>&#8594;<code> '23456'</code></p>
      <p><code>substring('123456', 2, 6) </code>&#8594;<code> '23456'</code></p>
      <p><code>substring('123456', 2) </code>&#8594;<code> '23456'</code></p>
      <p><code>substring('123456', -4) </code>&#8594;<code> '123456'</code></p>
      <p><code>substring('123456', 5, 5) </code>&#8594;<code> '5'</code></p>
      <p><code>substring('123456', 5) </code>&#8594;<code> '56'</code></p>
      <p><code>substring ('123456', 6) </code>&#8594;<code> '6'</code></p>
      <p><code>substring('123456', 1 div 0, ) </code>&#8594;<code> ''</code></p>
      <p><code>substring('123456', 2, -1) </code>&#8594;<code> ''</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>string-length</emphasis></p>
      </title>
      <p><code><emphasis>number </emphasis><strong>string-length</strong>(<emphasis>string</emphasis>?)</code></p>
      <p>Функция <code>string-length</code> возвращает число символов строкового аргумента. Если аргумент опущен, <code>string-length</code> возвращает длину строкового представления контекстного узла.</p>
      <p>Напомним, что длина строки не имеет ничего общего с количеством байт, которое требуется для ее представления. Разные формы кодирования используют разное количество байт для записи символов, внутренние представления строк также могут быть различными, но длина строки в любом случае — это число символов, которые ее составляют.</p>
      <subtitle>Примеры</subtitle>
      <p><code>string-length('Barnes and Noble') </code>&#8594;<code>16</code></p>
      <p><code>string-length('Barness#x20;&amp;amp;&amp;#32;Noble') </code>&#8594;<code> 14</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>normalize-space</emphasis></p>
      </title>
      <p><code><emphasis>string </emphasis><strong>normalize-space</strong>(<emphasis>string</emphasis>?)</code></p>
      <p>Функция <code>normalize-space</code> производит со своим строковым аргументом так называемую нормализацию пробельного пространства. Это означает, что в строке удаляются ведущие и заключающие пробельные символы, а все последовательности пробелов заменяются одним пробельным символом. Иными словами, функция удаляет "лишние" пробелы в строке.</p>
      <p>Если аргумент функции опущен, она выполняется со строковым значением контекстного узла.</p>
      <subtitle>Примеры</subtitle>
      <p><code>normalize-space(' А - В - С ') </code>&#8594;<code> 'А-В-С'</code></p>
      <p><code>normalize-space('А &amp;#х9; В &amp;#х9; С') &gt; 'A B C'</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>translate</emphasis></p>
      </title>
      <p><code><emphasis>string </emphasis><strong>translate</strong>(<emphasis>string</emphasis>, <emphasis>string</emphasis>, <emphasis>string</emphasis>)</code></p>
      <p>Функция <code>translate</code> производит замену символов первого своего строкового аргумента, которые присутствуют во втором аргументе на соответствующие символы третьего аргумента.</p>
      <subtitle>Пример</subtitle>
      <p><code>translate('abcdefgh', 'aceg', 'ACEG') </code>&#8594;<code> 'AbCdEfGh'</code></p>
      <p>Если некоторый символ повторяется во втором аргументе несколько раз, учитывается только первое его появление.</p>
      <subtitle>Пример</subtitle>
      <p><code>translate('abcdefgh', 'acaeaga', 'ACBECGD') </code>&#8594;<code> 'AbCdEfGh'</code></p>
      <p>Если второй аргумент длиннее третьего, символы, для которых нет соответствующей замены, удаляются из строки.</p>
      <subtitle>Пример</subtitle>
      <p><code>translate('a b-c=d+e|f/g\h', 'aceg-=+|/\', 'ACEG') </code>&#8594;<code> 'AbCdEfGh'</code></p>
      <p>Если третий аргумент длиннее второго, остаток строки игнорируется.</p>
      <subtitle>Пример</subtitle>
      <p><code>translate('abcdefgh', 'aceg', 'ACEGBDFH') </code>&#8594;<code> ' AbCdEfGh'</code></p>
      <p>Функцию <code>translate</code> можно использовать, например, для изменения регистра символов. Конечно, это будет работать только для тех языков, для которых такая функция будет записана, но и этого в большинстве случаев будет достаточно. В будущем предполагается включить в новые версии языка более мощные функции для работы с регистрами символов.</p>
      <subtitle>Пример</subtitle>
      <p>Для того чтобы изменять регистр слов русского языка, мы можем определить две переменные, <code>lowercase</code> и <code>uppercase</code>, которые будут содержать строчные и прописные символы основного русского алфавита (мы включили в него букву ё — строчную ("<code>ё</code>") и прописную ("<code>Ё</code>"), хотя в соответствии с Unicode она относится к расширениям). Мы также создадим два именованных шаблона, которые будут менять регистр символов строкового параметра <code>str</code>. Для удобства использования мы вынесем определения переменных и шаблонов во внешний модуль <code>ru.xsl</code>.</p>
      <subtitle>Листинг 6.6. Преобразование ru.xsl</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:variable</code></p>
      <p><code>  name="uppercase"</code></p>
      <p><code>  select="concat('&amp;#x410;&amp;#x411;&amp;#x412;&amp;#x413;',</code></p>
      <p><code>                 '&amp;#x414;&amp;#x415;&amp;#x401;&amp;#x416;&amp;#x417;',</code></p>
      <p><code>                 '&amp;#x418;&amp;#x419;&amp;#x41A;&amp;#x41B;',</code></p>
      <p><code>                 '&amp;#x41C;&amp;#x41D;&amp;#x41E;&amp;#x41F;',</code></p>
      <p><code>                 '&amp;#x420;&amp;#x421;&amp;#x422;&amp;#x423;',</code></p>
      <p><code>                 '&amp;#x424;&amp;#x425;&amp;#x426;&amp;#x427;',</code></p>
      <p><code>                 '&amp;#x428;&amp;#x429;&amp;#x42A;&amp;#x42B;',</code></p>
      <p><code>                 '&amp;#x42C;&amp;#x42D;&amp;#x42E;&amp;#x42F;')"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:variable</code></p>
      <p><code>  name="lowercase"</code></p>
      <p><code>  select="concat('&amp;#x430;&amp;#x431;&amp;#x432;&amp;#x433;',</code></p>
      <p><code>                 '&amp;#x434;&amp;#x435;&amp;#x451;&amp;#x436;&amp;#x417;',</code></p>
      <p><code>                 '&amp;#x438;&amp;#x439;&amp;#x43A;&amp;#x43B;',</code></p>
      <p><code>                 '&amp;#x43C;&amp;#x43D;&amp;#x43E;&amp;#x43F;',</code></p>
      <p><code>                 '&amp;#x440;&amp;#x441;&amp;#x442;&amp;#x443;',</code></p>
      <p><code>                 '&amp;#x444;&amp;#x445;&amp;#x446;&amp;#x447;',</code></p>
      <p><code>                 '&amp;#x448;&amp;#x449;&amp;#x44A;&amp;#x44B;',</code></p>
      <p><code>                 '&amp;#x44C;&amp;#x44D;&amp;#x44E;&amp;#x44F;')"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template name="lower"&gt;</code></p>
      <p><code>  &lt;xsl:param name="str"/&gt;</code></p>
      <p><code>  &lt;xsl:value-of select="translate($str, $uppercase, $lowercase)"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template name="upper"&gt;</code></p>
      <p><code>  &lt;xsl:param name="str"/&gt;</code></p>
      <p><code>  &lt;xsl:value-of select="translate($str, $lowercase, $uppercase)"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <p>Использовать этот модуль можно, включив или импортировав его в основное преобразование элементами <code>xsl:include</code> или <code>xsl:import</code>. После этого в основном преобразовании будут доступны переменные <code>lowercase</code> и <code>uppercase</code>, которые можно будет использовать в функции <code>translate</code> и шаблоны с именами <code>lower</code> и <code>upper</code>.</p>
      <p>Использовать функцию <code>translate</code> с переменными <code>lowercase</code> и <code>uppercase</code> можно следующим образом:</p>
      <p><code>translate('Дом', $uppercase, $lowercase) </code>&#8594;<code> 'дом'</code></p>
      <p><code>translate('Дом', $lowercase, $uppercase) </code>&#8594;<code> 'ДОМ'</code></p>
      <p>Именованные шаблоны можно вызывать элементом <code>xsl:call-template</code>, передавая параметр при помощи <code>xsl:with-param</code>. Например, следующий фрагмент шаблона</p>
      <p><code>...</code></p>
      <p><code>&lt;xsl:call-template name="lower"&gt;</code></p>
      <p><code> &lt;xsl:with-param name="str" select="'Дом'"/&gt;</code></p>
      <p><code>&lt;/xsl:call-template</code>&gt;</p>
      <p><code>...</code></p>
      <p>создаст в выходящем дереве текстовый узел со значением "<code>дом</code>".</p>
     </section>
    </section>
    <section>
     <title>
      <p>Функции множеств узлов</p>
     </title>
     <section>
      <title>
       <p>Функции<emphasis> last</emphasis> и<emphasis> position</emphasis></p>
      </title>
      <p><code><emphasis>number </emphasis><strong>last</strong>()</code></p>
      <p><code><emphasis>number </emphasis><strong>position</strong>()</code></p>
      <p>Функция <code>last</code> возвращает текущий размер контекста — число, которое показывает, сколько узлов находится в обрабатываемом в данный момент множестве.</p>
      <p>Функция <code>position</code> возвращает позицию контекста — число, показывающее порядковый номер контекстного узла в обрабатываемом множестве.</p>
      <subtitle>Пример</subtitle>
      <p>В этом примере мы будем заменять все элементы элементами вида</p>
      <p><code>&lt;element name="..." position="..."&gt;</code></p>
      <p><code> ...</code></p>
      <p><code>&lt;/element&gt;</code></p>
      <p>где атрибут <code>name</code> будет содержать имя, a <code>position</code> — через дробь позицию элемента в контексте и размер контекста.</p>
      <subtitle>Листинг 6.7. Входящий документ</subtitle>
      <p><code>&lt;а&gt;</code></p>
      <p><code> &lt;b/&gt;</code></p>
      <p><code> &lt;c/&gt;</code></p>
      <p><code> &lt;d&gt;</code></p>
      <p><code>  &lt;e/&gt;</code></p>
      <p><code>  &lt;f/&gt;</code></p>
      <p><code> &lt;/d&gt;</code></p>
      <p><code>&lt;/a&gt;</code></p>
      <subtitle>Листинг 6.8. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:output indent="yes"/&gt;</code></p>
      <p><code> &lt;xsl:strip-space elements="*"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="*"&gt;</code></p>
      <p><code>  &lt;element name="{name()}" pos="{position()}/{last()}"&gt;</code></p>
      <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
      <p><code>  &lt;/element&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 6.9. Выходящий документ</subtitle>
      <p><code>&lt;element name="a" pos="1/1"&gt;</code></p>
      <p><code> &lt;element name="b" pos="1/3"/&gt;</code></p>
      <p><code> &lt;element name="c" pos="2/3"/&gt;</code></p>
      <p><code> &lt;element name="d" pos="3/3"&gt;</code></p>
      <p><code>  &lt;element name="e" pos="1/2"/&gt;</code></p>
      <p><code>  &lt;element name="f" pos="2/2"/&gt;</code></p>
      <p><code> &lt;/element&gt;</code></p>
      <p><code>&lt;/element&gt;</code></p>
      <p>Отметим, что если бы мы не удаляли лишние пробельные символы во входящем документе при помощи элемента <code>xsl:strip-space</code>, в контексте преобразования учитывались бы также и текстовые узлы, которые им соответствуют. Выходящий документ без этого элемента имел бы следующий вид:</p>
      <p><code>&lt;element name="a" pos="1/1"&gt;</code></p>
      <p><code> &lt;element name="b" pos="2/7"/&gt;</code></p>
      <p><code> &lt;element name="c" pos="4/7"/&gt;</code></p>
      <p><code> &lt;element name="d" pos="6/7"&gt;</code></p>
      <p><code>  &lt;element name="e" pos="2/5"/&gt;</code></p>
      <p><code>  &lt;element name="f" pos="4/5"/&gt;</code></p>
      <p><code> &lt;/element&gt;</code></p>
      <p><code>&lt;/element&gt;</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>count</emphasis></p>
      </title>
      <p><code><emphasis>number </emphasis><strong>count</strong>(<emphasis>node-set</emphasis>)</code></p>
      <p>Функция <code>count</code> возвращает число узлов, которое входит во множество, переданное ей в качестве аргумента.</p>
      <subtitle>Пример</subtitle>
      <p>Для того чтобы подсчитать количество всех элементов второго уровня, можно воспользоваться выражением <code>count(/*/*)</code>. Например, для входящего документа из примера к функциям <code>last</code> и <code>position</code> (листинг 6.7) это выражение примет значение <code>3</code>.</p>
      <p>Приведем несколько других примеров, используя тот же документ.</p>
      <p>Покажем, что дерево документа на листинге 6.7 имеет ровно один корневой узел:</p>
      <p><code>count(/) </code>&#8594;<code> 1</code></p>
      <p>и ровно один элемент, находящийся в корне:</p>
      <p><code>count(/*) </code><strong>&#8594;</strong><code> 1</code></p>
      <p>Подсчитаем количество текстовых узлов, принадлежащих элементу <code>a</code> (это те самые пробельные текстовые узлы, которые были удалены элементом <code>xsl:strip-space</code>):</p>
      <p><code>count(/a/text()) </code>&#8594;<code> 4</code></p>
      <p>Подсчитаем общее количество элементов в документе:</p>
      <p><code>count(//*) </code>&#8594;<code> 6</code></p>
     </section>
     <section>
      <title>
       <p>Функции <emphasis>local-name</emphasis>, <emphasis>namespace-uri</emphasis> и <emphasis>name</emphasis></p>
      </title>
      <p><code><emphasis>string </emphasis><strong>local-name</strong>(<emphasis>node-set</emphasis>?)</code></p>
      <p><code><emphasis>string </emphasis><strong>namespace-uri</strong>(<emphasis>node-set</emphasis>?)</code></p>
      <p><code><emphasis>string </emphasis><strong>name</strong>(<emphasis>node-set</emphasis>?)</code></p>
      <p>Функция <code>local-name</code> возвращает локальную часть имени первого в порядке просмотра документа узла множества, переданного ей в качестве аргумента. Эта функция выполняется следующим образом.</p>
      <p>&#9633; Если аргумент опущен, то значением функции по умолчанию является множество, содержащее единственный контекстный узел. Иными словами, функция возвратит локальную часть расширенного имени контекстного узла (если она существует).</p>
      <p>&#9633; Если аргументом является пустое множество, функция возвращает пустую строку.</p>
      <p>&#9633; Если первый в порядке просмотра документа узел переданного множества не имеет расширенного имени, функция возвращает пустую строку.</p>
      <p>&#9633; В противном случае функция возвращает локальную часть расширенного имени первого в порядке просмотра документа узла переданного множества.</p>
      <p>Функция <code>namespace-uri</code> работает совершенно аналогично функции <code>local-name</code> за тем исключением, что возвращает не локальную часть расширенного имени, a URI пространства имен этого узла. Эта функция выполняется следующим образом.</p>
      <p>&#9633; Если аргумент опущен, его значением по умолчанию является множество, содержащее единственный контекстный узел.</p>
      <p>&#9633; Если аргументом является пустое множество, функция возвращает пустую строку.</p>
      <p>&#9633; Если первый в порядке просмотра документа узел переданного множества не имеет расширенного имени, функция возвращает пустую строку.</p>
      <p>&#9633; Если первый в порядке просмотра документа узел переданного множества не принадлежит никакому пространству имен, функция возвращает пустую строку.</p>
      <p>&#9633; В противном случае функция возвращает URI пространства имен первого в порядке просмотра документа узла переданного множества.</p>
      <p>Функция <code>name</code> возвратит имя вида <code>QName</code>, которое будет соответствовать расширенному имени первого в порядке просмотра документа узла переданного ей множества.</p>
      <p>Это имя должно соответствовать расширенному имени узла, то есть должны совпадать локальные части и пространства имен. Вместе с тем, это вовсе не означает, что префиксы также будут совпадать. Например, если в элементе определены несколько префиксов для одного пространства, функция <code>name</code> может использовать любой из них.</p>
      <subtitle>Пример</subtitle>
      <p>Для следующего элемента</p>
      <p><code>&lt;a:body</code></p>
      <p><code> xmlns:a="http://www.a.com"</code></p>
      <p><code> xmlns:b="http://www.a.com"</code></p>
      <p><code> xmlns:c="http://www.a.com"/&gt;</code></p>
      <p>функция <code>name</code> может вернуть <code>a:body</code>, <code>b:body</code> или <code>c:body</code>.</p>
      <p>Большинство процессоров все же возвращает префикс, с которым узел был объявлен.</p>
      <p>Так же как <code>local-name</code> и <code>namespace-uri</code>, функция name имеет следующие особенности использования.</p>
      <p>&#9633; Если аргумент опущен, то его значением по умолчанию является множество, содержащее единственный контекстный узел.</p>
      <p>&#9633; Если аргументом является пустое множество, то функция возвращает пустую строку.</p>
      <p>&#9633; Если первый в порядке просмотра документа узел переданного множества не имеет расширенного имени, то функция возвращает пустую строку.</p>
      <p>&#9633; В противном случае функция возвращает имя вида <code>QName</code>, соответствующее расширенному имени первого в порядке просмотра документа узла переданного множества.</p>
      <subtitle>Пример</subtitle>
      <p>Мы можем видоизменить преобразование, приведенное в примере к функциям <code>last</code> и <code>position</code> (листинг 6.7), чтобы генерируемые элементы содержали информацию об имени, пространстве имен и локальной части имени элементов.</p>
      <subtitle>Листинг 6.10. Входящий документ</subtitle>
      <p><code>&lt;a:a</code></p>
      <p><code> xmlns:a="http://www.a.com"</code></p>
      <p><code> xmlns:b="http://www.b.com"&gt;</code></p>
      <p><code> &lt;b:b&gt;</code></p>
      <p><code>  &lt;c/&gt;</code></p>
      <p><code> &lt;/b:b&gt;</code></p>
      <p><code>&lt;/a:a&gt;</code></p>
      <subtitle>Листинг 6.11. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http: //www.w3.org/1999/XSL/Transform"</code></p>
      <p><code> xmlns:a="http://www.a.com"</code></p>
      <p><code> xmlns:b="http://www.b.com"&gt;</code></p>
      <p><code> &lt;xsl:output indent="yes"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="*"&gt;</code></p>
      <p><code>  &lt;element</code></p>
      <p><code>   name="{name()}"</code></p>
      <p><code>   namespace-uri="{namespace-uri()}"</code></p>
      <p><code>   local-name="{local-name()}"&gt;</code></p>
      <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
      <p><code>  &lt;/element&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 6.12. Выходящий документ</subtitle>
      <p><code>&lt;element</code></p>
      <p><code> xmlns:a="http://www.a.com"</code></p>
      <p><code> xmlns:b="http://www.b.com"</code></p>
      <p><code> name="a:a"</code></p>
      <p><code> namespace-uri="http://www.a.com"</code></p>
      <p><code> local-name="a"&gt;</code></p>
      <p><code> &lt;element name="b:b"</code></p>
      <p><code>  namespace-uri="http://www.b.com" </code></p>
      <p><code>  local-name="b"&gt;</code></p>
      <p><code>  &lt;element name="c"</code></p>
      <p><code>   namespace-uri=""</code></p>
      <p><code>   local-name="c"/&gt;</code></p>
      <p><code> &lt;/element&gt;</code></p>
      <p><code>&lt;/element&gt;</code></p>
     </section>
     <section>
      <title>
       <p>Функция <emphasis>id</emphasis></p>
      </title>
      <p><code><emphasis>node-set </emphasis><strong>id</strong>(<emphasis>object</emphasis>)</code></p>
      <p>Мы уже встречались с функцией <code>id</code>, когда говорили об уникальных атрибутах элементов и еще раз — когда разбирали паттерны. Функция <code>id</code> позволяет обращаться к элементам по значениями их уникальных атрибутов.</p>
      <p>Функция <code>id</code> выполняется по-разному в зависимости от того, какой тип данных ей передается.</p>
      <p>&#9633; Если аргументом функции является строка, она рассматривается как набор идентификаторов, разделенных пробелами. В результирующее множество узлов войдут узлы тех элементов текущего документа, значения уникальных атрибутов которых входят в набор идентификаторов, определяемый строковым аргументом.</p>
      <p>&#9633; Если аргументом функции является множество узлов, результатом ее выполнения будет объединение результатов функции <code>id</code>, примененной к строковому значению каждого из узлов множества.</p>
      <p>&#9633; Если аргументом функции является объект другого типа, аргумент вначале преобразуется в строку и функция <code>id</code> выполняется как со строковым параметром.</p>
      <subtitle>Пример</subtitle>
      <p>Предположим, что мы используем XML для того, чтобы описать граф — множество вершин, соединенных дугами (рис. 6.11).</p>
      <image l:href="#img_57.png"/>
      <p>Рис. 6.11. Изображение графа, который мы будем описывать в XML</p>
      <p>Каждой вершине будет соответствовать элемент <code>vertex</code>. Для того чтобы описать все связи, мы дадим каждой вершине уникальное имя, которое будет записано в ее <code>ID</code>-атрибуте <code>name</code>. Имена вершин, с которыми она соединена, будут перечислены в атрибуте <code>connects</code> типа <code>IDREFS</code>.</p>
      <p>Документ, описывающий этот граф, может выглядеть следующим образом.</p>
      <subtitle>Листинг 6.13. Документ gemini.xsl</subtitle>
      <p><code>&lt;!DOCTYPE vertices SYSTEM "gemini.dtd"&gt;</code></p>
      <p><code>&lt;vertices&gt;</code></p>
      <p><code> &lt;vertex name="alpha" connects="tau"/&gt;</code></p>
      <p><code> &lt;vertex name="beta" connects="upsilon"/&gt;</code></p>
      <p><code> &lt;vertex name="gamma" connects="zeta"/&gt;</code></p>
      <p><code> &lt;vertex name="delta" connects="zeta lambda upsilon"/&gt;</code></p>
      <p><code> &lt;vertex name="epsilon" connects="nu mu tau"/&gt;</code></p>
      <p><code> &lt;vertex name="zeta" connects="delta gamma"/&gt;</code></p>
      <p><code> &lt;vertex name="theta" connects="tau"/&gt;</code></p>
      <p><code> &lt;vertex name="iota" connects="tau upsilon"/&gt;</code></p>
      <p><code> &lt;vertex name="kappa" connects="upsilon"/&gt;</code></p>
      <p><code> &lt;vertex name="lambda" connects="delta xi"/&gt;</code></p>
      <p><code> &lt;vertex name="mu" connects="epsilon"/&gt;</code></p>
      <p><code> &lt;vertex name="nu" connects="epsilon"/&gt;</code></p>
      <p><code> &lt;vertex name="xi" connects="lambda"/&gt;</code></p>
      <p><code> &lt;vertex name="tau" connects="alpha theta iota epsilon"/&gt;</code></p>
      <p><code> &lt;vertex name="upsilon" connects="beta iota kappa delta"/&gt;</code></p>
      <p><code>&lt;/vertices&gt;</code></p>
      <p>Декларация типа документа вынесена во внешний файл <code>gemini.dtd</code>.</p>
      <subtitle>Листинг 6.14. Файл gemini.dtd</subtitle>
      <p><code>&lt;!ELEMENT vertices (vertex*)&gt;</code></p>
      <p><code>&lt;!ELEMENT vertex EMPTY&gt;</code></p>
      <p><code>&lt;!ATTLIST vertex</code></p>
      <p><code> name ID #REQUIRED</code></p>
      <p><code> connects IDREFS #REQUIRED&gt;</code></p>
      <p>При обработке этого документа функция <code>id</code> будет очень полезна для выбора элементов соединенных вершин. Действительно, функция <code>id</code>, которой будет передано значение атрибута <code>connects</code> (в котором через пробелы перечислены вершины, смежные данной), возвратит множество, состоящее из элементов с перечисленными уникальными идентификаторами. Так, например, функция <code>id('tau upsilon')</code> возвратит множество, состоящее из двух элементов с атрибутами name, равными <code>tau</code> и <code>upsilon</code> соответственно.</p>
      <p>Более того, функция <code>id</code> может быть вычислена и от множества узлов. В этом случае ее значением будет объединение множеств, полученных в результате выполнения функции от строкового значения каждого узла переданного множества. Например, <code>id(id('tau upsilon')/@connects)</code> возвратит множество, состоящее из вершин с именами <code>alpha</code>, <code>beta</code>, <code>delta</code>, <code>epsilon</code>, <code>theta</code>, <code>iota</code> и <code>kappa</code> — множество вершин, смежных с вершинами tau и upsilon.</p>
      <p>Приведем пример преобразования, которое в каждый элемент <code>vertex</code> добавляет комментарий, в котором перечислены имена вершин, достижимых из текущей, не более чем за два шага.</p>
      <p>Для того чтобы найти множество вершин, достижимых за один шаг (иначе говоря, смежных), мы воспользуемся выражением вида <code>id(@connects)</code>, для выборки множества вершин, достижимых из текущей за два шага — выражением <code>id(id(@connects)/@connects)</code>. Таким образом, множество вершин, достижимых не более чем за два шага, будет вычисляться как</p>
      <p><code>id(@connects)|id(id(@connects)/@connects)</code></p>
      <subtitle>Листинг 6.15. Преобразование gemini.xsl</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:output doctype-system="gemini.dtd"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="vertices"&gt;</code></p>
      <p><code>  &lt;xsl:copy&gt;</code></p>
      <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
      <p><code>  &lt;/xsl:copy&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="vertex"&gt;</code></p>
      <p><code>  &lt;vertex name="{@name}" connects="{@connects}"&gt;</code></p>
      <p><code>   &lt;xsl:comment&gt;</code></p>
      <p><code>    &lt;xsl:for-each select="id(@connects)|id(id@connects)/@connects)"&gt;</code></p>
      <p><code>     &lt;xsl:text&gt; &lt;/xsl:text&gt;</code></p>
      <p><code>     &lt;xsl:value-of select="@name"/&gt;</code></p>
      <p><code>    &lt;/xsl:for-each&gt;</code></p>
      <p><code>   &lt;/xsl:comment&gt;</code></p>
      <p><code>  &lt;/vertex&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 6.16. Выходящий документ</subtitle>
      <p><code>&lt;!DOCTYPE vertices SYSTEM "gemini.dtd"&gt;</code></p>
      <p><code>&lt;vertices&gt;</code></p>
      <p><code> &lt;vertex name="alpha" connects="tau"&gt;</code></p>
      <p><code>  &lt;!-- alpha epsilon theta iota tau--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="beta" connects="upsilon"&gt;</code></p>
      <p><code>  &lt;!-- beta delta iota kappa upsilon--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="gamma" connects="zeta"&gt;</code></p>
      <p><code>  &lt;!-- gamma delta zeta--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="delta" connects="zeta lambda upsilon"&gt;</code></p>
      <p><code>  &lt;!-- beta gamma delta zeta iota kappa lambda xi upsilon--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="epsilon" connects="nu mu tau"&gt;</code></p>
      <p><code>  &lt;!-- alpha epsilon theta iota mu nu tau--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="zeta" connects="delta gamma"&gt;</code></p>
      <p><code>  &lt;!-- gamma delta zeta lambda upsilon--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="theta" connects="tau"&gt;</code></p>
      <p><code>  &lt;!-- alpha epsilon theta iota tau--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="iota" connects="tau upsilon"&gt;</code></p>
      <p><code>  &lt;!-- alpha beta delta epsilon theta iota kappa tau upsilon--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="kappa" connects="upsilon"&gt;</code></p>
      <p><code>  &lt;!-- beta delta iota kappa upsilon--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="lambda" connects="delta xi"&gt;</code></p>
      <p><code>  &lt;!-- delta zeta lambda xi upsilon--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="mu" connects="epsilon"&gt;</code></p>
      <p><code>  &lt;!-- epsilon mu nu tau--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="nu" connects="epsilon"&gt;</code></p>
      <p><code>  &lt;!-- epsilon mu nu tau--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="xi" connects="lambda"&gt;</code></p>
      <p><code>  &lt;!-- delta lambda xi--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="tau" connects="alpha theta iota epsilon"&gt;</code></p>
      <p><code>  &lt;!-- alpha epsilon theta iota mu nu tau upsilon--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code> &lt;vertex name="upsilon" connects="beta iota kappa delta"&gt;</code></p>
      <p><code>  &lt;!-- beta delta zeta iota kappa lambda tau upsilon--&gt;</code></p>
      <p><code> &lt;/vertex&gt;</code></p>
      <p><code>&lt;/vertices&gt;</code></p>
     </section>
    </section>
   </section>
   <section>
    <title>
     <p>Базовые продукции XPath</p>
    </title>
    <section>
     <p>В этом разделе мы приведем базовые синтаксические правила языка XPath. Со многими из них мы уже встречались в правилах более высокого уровня, некоторые определены в спецификации для того, чтобы облегчить реализацию лексического разбора XPath-выражений в различных процессорах.</p>
     <p>Литералы — это строковые значения, заключенные в одинарные или двойные кавычки. В литералах нельзя использовать символ кавычек, в которые они заключены. Кроме этого, поскольку XPath-выражения чаще всего используются в атрибутах элементов, в них нельзя использовать символы "<code>&lt;</code>" и "<code>&amp;</code>" — они должны заменяться на сущности. Литералам соответствует продукция <code>Literal</code>, определяемая в виде:</p>
     <p><code>[XP29] Literal ::= '"' [^"]* '"' | "'" [^']* "'"</code></p>
     <p>XPath использует десятичную систему счисления. Наборы цифр, соответствующие правилу <code>Digits</code>, могут состоять из цифр от <code>0</code> до <code>9</code>:</p>
     <p><code>[XP31] Digits ::= [0-9]+</code></p>
     <p>Число в XPath состоит из последовательности цифр, которые могут быть разделены точкой, причем точка может стоять как в начале числа (<code>.5</code>), так и в конце (<code>5.</code>). Числу соответствует EBNF-правило <code>Number</code>:</p>
     <p><code>[XP30] Number ::= Digits ('.' Digits?)? | '.' Digits</code></p>
     <p>Оператору умножения соответствует символ "<code>*</code>" и синтаксическое правило <code>MultiplyOperator</code>:</p>
     <p><code>[XP34] MultiplyOperator ::= '*'</code></p>
     <p>Именам переменных, которые используются в XPath, предшествует символ "<code>$</code>". Сами же имена должны удовлетворять продукции <code>QName</code>, которую мы рассматривали <emphasis>в разделе "Расширенные имена"</emphasis>.</p>
     <p><code>[XP36] VariableReference ::= '$' QName</code></p>
     <p>Продукция <code>NodeType</code>, использованная в тесте узла (<emphasis>см. раздел "Тесты узлов" данной главы, продукция </emphasis><code><emphasis>[XP7]</emphasis></code>), определяет типы узлов, которые можно проверить при тесте — <code>comment</code> (комментарий), <code>text</code> (текстовый узел), <code>processing-instruction</code> (узел инструкции по обработке) и <code>node</code> (узел любого типа). <code>NodeType</code> записывается следующим образом:</p>
     <p><code>[XP38] NodeType ::= 'comment'</code></p>
     <p><code>                    | 'text'</code></p>
     <p><code>                    | 'processing-instruction'</code></p>
     <p><code>                    | 'node'</code></p>
     <p>Другая конструкция, <code>NameTest</code>, которая также используется в тесте узла, проверяет узлы базового типа оси на соответствие определенному имени. EBNF-правило <code>NameTest</code> имеет следующий синтаксис:</p>
     <p><code>[ХР37] NameTest ::= '*' | NCName ':' '*' | QName</code></p>
     <p>Имя функции в XPath может быть любым корректным XML-именем за исключением тех имен, которые используются для обозначения типов узлов. Правило <code>FunctionName</code> имеет вид:</p>
     <p><code>[XP35] FunctionName ::= QName - NodeType</code></p>
     <p>В целях удобочитаемости, в выражениях можно использовать пробельное пространство. Ему соответствует EBNF-правило <code>ExprWhiteSpace</code>:</p>
     <p><code>[XP39] ExprWhitespace ::= S</code></p>
    </section>
    <section>
     <title>
      <p>Разбор XPath-выражений</p>
     </title>
     <p>Хотя синтаксис языка XPath укладывается в тридцать с небольшим синтаксических правил, реализация интерпретатора XPath-выражений может быть довольно непростой задачей. Для того чтобы хоть как-то упростить ее, в XPath определяются так называемые токены выражения (англ. expression token). Токены — это единицы, из которых состоит выражение. Будучи сами очень простыми, они выстраиваются в более сложные конструкции, образуя, в итоге, выражения.</p>
     <p>Примером токенов являются операторы, которым соответствуют продукции <code>Operator</code> и <code>OperatorName</code>:</p>
     <p><code>[XP33] OperatorName ::= 'and' | 'or' | 'mod* | 'div'</code></p>
     <p><code>[XP32] Operator     ::= OperatorName</code></p>
     <p><code>                        | MultiplyOperator</code></p>
     <p><code>                        | '/' | '//' | '|' | '+' | '-'</code></p>
     <p><code>                        | '=' | '!=' | '&lt;' | '&gt;' | '&lt;=' | '&gt;='</code></p>
     <p>Продукция самого токена выражения имеет вид:</p>
     <p><code>[ХР28] ExprToken ::= '(' | ')' | '[' | ']'</code></p>
     <p><code>                     | ' . ' | ' .. ' | '@' | ' | ':: '</code></p>
     <p><code>                     | NameTest</code></p>
     <p><code>                     | NodeType</code></p>
     <p><code>                     | Operator</code></p>
     <p><code>                     | FunctionName</code></p>
     <p><code>                     | AxisName</code></p>
     <p><code>                     | Literal</code></p>
     <p><code>                     | Number</code></p>
     <p><code>                     | VariableReference</code></p>
     <p>При разборе XPath-выражения оно сначала разбивается на отдельные токены, а затем из них организуются более сложные структуры. При разбивке выражения на отдельные токены, следует всегда выбирать токен с самым длинным строковым представлением.</p>
     <p>Помимо этого, для того чтобы грамматика XPath-выражений была однозначной, в спецификации языка приводятся следующие правила разбора.</p>
     <p>&#9633; Если текущему токену предшествует другой токен, причем этот предшествующий токен не является символом <code>@</code>, <code>::</code>, <code>(</code>, <code>[</code> или нетерминалом <code>Operator</code>, то текущий токен, являющийся символом <code>*</code>, должен восприниматься как знак умножения, а токен, являющийся <code>NCName</code>, — как нетерминал <code>OperatorName</code>.</p>
     <p>&#9633; Если за текущим токеном вида <code>NCName</code> следует открывающая круглая скобка (символ "<code>(</code>"), токен должен восприниматься или как имя функции (<code>FunctionName</code>), или как тип узла (<code>NodeType</code>).</p>
     <p>&#9633; Если за текущим токеном вида <code>NCName</code> следуют символы "<code>::</code>", токен должен восприниматься как имя оси навигации (<code>AxisName</code>).</p>
     <p>&#9633; Если ничего из вышеперечисленного не выполняется, токен не должен восприниматься, как <code>MultiplyOperator</code>, <code>OperatorName</code>, <code>NodeType</code>, <code>FunctionName</code> или <code>AxisName</code>.</p>
     <p>Мы привели эти правила в точности так, как они описаны в спецификации языка XPath. Их довольно непросто понять в такой формулировке, поэтому мы попытаемся объяснить их другими словами.</p>
     <p>&#9633; Символ <code>*</code> является знаком умножения (<code>MultiplyOperator</code>) тогда и только тогда, когда ему предшествует токен, но этот токен не является токеном <code>@</code>, <code>::</code>, <code>(</code>, <code>[</code> или <code>Operator</code>.</p>
     <p>&#9633; Токен <code>NCName</code> представляет имя оператора (<code>OperatorName</code>) тогда и только тогда, когда ему предшествует токен, но этот токен не является токеном <code>::</code>, <code>(</code>, <code>[</code> или <code>Operator</code>.</p>
     <p>&#9633; Токен <code>NCName</code> является именем функции (<code>FunctionName</code>) или типом узла (<code>NodeType</code>) тогда и только тогда, когда за ним следует символ "<code>(</code>".</p>
     <p>&#9633; Токен <code>NCName</code> является именем оси навигации (<code>AxisName</code>) тогда и только тогда, когда за ним следуют символы "<code>::</code>".</p>
    </section>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 7</p>
    <p>Основные элементы XSLT</p>
   </title>
   <section>
    <title>
     <p>Основные и дополнительные элементы</p>
    </title>
    <p>Все элементы XSLT можно разделить на две группы: элементы основные и элементы дополнительные. Это разделение очень условно, ничего подобного в спецификации языка XSLT нет, однако, мы будем им пользоваться, считая основными элементами те элементы XSLT, которые непосредственно отвечают за создание узлов выходящего дерева или обеспечивают контроль над этим процессом. К дополнительным элементам мы будем относить все остальные элементы XSLT.</p>
    <p>Таким образом, множество основных элементов будет включать в себя следующее:</p>
    <p>&#9633; <code>xsl:element</code> — создание в выходящем дереве узла элемента;</p>
    <p>&#9633; <code>xsl:attribute</code> — создание в выходящем дереве узла атрибута;</p>
    <p>&#9633; <code>xsl:attribute-set</code> — определение именованного набора атрибутов;</p>
    <p>&#9633; <code>xsl:text</code> — создание текстового узла;</p>
    <p>&#9633; <code>xsl:value-of</code> — создание текстового узла по результатам вычисления выражения;</p>
    <p>&#9633; <code>xsl:comment</code> — создание узла комментария;</p>
    <p>&#9633; <code>xsl:processing-instruction</code> — создание узла инструкции по обработке;</p>
    <p>&#9633; <code>xsl:copy</code> — копирование текущего узла вместе с его узлами пространств имен;</p>
    <p>&#9633; x<code>sl:copy-of</code> — копирование результата вычисления выражения;</p>
    <p>&#9633; <code>xsl:if</code> — условная обработка;</p>
    <p>&#9633; <code>xsl:choose</code>, <code>xsl:when</code> и <code>xsl:otherwise</code> — выбор одной из нескольких альтернатив согласно некоторым условиям;</p>
    <p>&#9633; <code>xsl:for-each</code> — итеративная обработка множества узлов.</p>
   </section>
   <section>
    <title>
     <p>Создание узлов элементов</p>
    </title>
    <section>
     <p>В четвертой главе мы уже разобрали один из способов создания в выходящем документе узлов элементов, а именно — использование литеральных элементов результата, которые в неизменном виде копируются процессором в выходящее дерево. Этот способ прост, понятен и удобен, однако есть две основные проблемы, которые он не может решить.</p>
     <p>&#9633; Что, если в выходящем документе требуется создать элемент с заранее неизвестным (например, вычисляемым во время выполнения) именем?</p>
     <p>&#9633; Как создать элемент, принадлежащий пространству имен, известному обрабатывающему процессору?</p>
     <p>Поясним на примерах суть и той и другой проблемы.</p>
     <p>Представим себе входящий документ вида</p>
     <p><code>&lt;element name="a"&gt;</code></p>
     <p><code> &lt;element name="b"/&gt;</code></p>
     <p><code>&lt;/element&gt;</code></p>
     <p>который нужно преобразовать во что-нибудь наподобие</p>
     <p><code>&lt;а&gt;</code></p>
     <p><code> &lt;b/&gt;</code></p>
     <p><code>&lt;/а&gt;</code></p>
     <p>Совершенно очевидно, что литеральными элементами тут не обойдешься — мы не знаем заранее имена элементов выходящего документа, ибо они определяются значениями атрибутов входящего.</p>
     <p>Представим теперь, что нам в XSLT-преобразовании необходимо сгенерировать другое XSLT-преобразование. Скажем из элемента вида</p>
     <p><code>&lt;remove element="a"/&gt;</code></p>
     <p>нужно получить шаблон</p>
     <p><code>&lt;xsl:template match="a"/&gt;</code></p>
     <p>Беда в том, что литеральные элементы не могут быть использованы для создания, скажем, элемента <code>xsl:template</code> по той причине, что любой элемент с локальной частью имени <code>template</code>, принадлежащий пространству имен XSLT будет рассматриваться процессором, как элемент самого преобразования. Очевидно, что</p>
     <p><code>&lt;xsl:template match="remove"&gt;</code></p>
     <p><code> &lt;xsl:template match="{@element}"/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>будет некорректным определением. He поможет и смена префикса, ведь принадлежность пространству имен определяется не им.</p>
     <p>Для того чтобы решить эти проблемы (главным образом, первую), XSLT предоставляет возможность создавать узлы элементов при помощи элемента <code>xsl:element</code>.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:element</emphasis></p>
     </title>
     <p>Синтаксическая конструкция этого элемента задается следующим образом:</p>
     <p><code>&lt;xsl:element</code></p>
     <p><code> <strong>name</strong>="{<emphasis>имя</emphasis>}"</code></p>
     <p><code> namespace="{<emphasis>пространство имен</emphasis>}</code></p>
     <p><code> "use-attribute-sets="<emphasis>имена</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:element&gt;</code></p>
     <p>Здесь обязательный атрибут <code>name</code> указывает имя создаваемого элемента. Этот атрибут может содержать шаблон значения, а значит, имя элемента может быть вычислено во время выполнения.</p>
     <p>Атрибут <code>namespace</code> указывает URI пространства имен создаваемого элемента. Точно так же, как и name, этот атрибут может содержать шаблон значения, что позволяет вычислять пространство имен создаваемого элемента при помощи выражений.</p>
     <p>Атрибут <code>use-attribute-sets</code> перечисляет имена наборов атрибутов, которые должны быть включены в создаваемый элемент.</p>
     <p>Содержимым <code>xsl:element</code> является шаблон, который выполняется процессором и затем включается в создаваемый элемент.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, мы хотим поменять имя каждого элемента на значение его первого атрибута и наоборот.</p>
     <subtitle>Листинг 7.1. Входящий документ</subtitle>
     <p><code>&lt;fire on="babylon"/&gt;</code></p>
     <subtitle>Листинг 7.2. Шаблон, заменяющий имя элемента значением атрибута</subtitle>
     <p><code>&lt;xsl:template match="*"&gt;</code></p>
     <p><code> &lt;xsl:element name="{@*}"&gt;</code></p>
     <p><code>  &lt;xsl:attribute name="{name(@*)}"&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="name()"/&gt;</code></p>
     <p><code>  &lt;/xsl:attribute&gt;</code></p>
     <p><code> &lt;/xsl:element&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <subtitle>Листинг 7.3. Выходящий документ</subtitle>
     <p><code>&lt;babylon on="fire"/&gt;</code></p>
     <p>В этом примере код <code>&lt;xsl:element name="{@*}"&gt;...&lt;/xsl:element&gt;</code> создает элемент, именем которого становится значение выражения <code>@*</code>, указанного в виде шаблона значения атрибута <code>name</code>. Это выражение выбирает множество, состоящее из узлов атрибутов текущего элемента, а если привести его к строке, в результате получится текстовое значение первого атрибута элемента.</p>
     <p>Подобным образом выбирается имя атрибута создаваемого элемента и его значение.</p>
     <p>Вычисленное значение атрибута <code>name</code> может задавать и расширенное имя элемента, то есть иметь форму <code><emphasis>префикс</emphasis>:<emphasis>имя</emphasis></code>. В этом случае элемент будет создаваться в том пространстве имен, которое соответствует указанному префиксу, например</p>
     <p><code>&lt;xsl:element name="xsl:template"/&gt;</code></p>
     <p>создаст элемент вида</p>
     <p><code>&lt;xsl:template xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/&gt;</code></p>
     <p>Заметим, что элемент вида</p>
     <p><code>&lt;xsl:element name="{concat{'xsl',':','template')}"/&gt;</code></p>
     <p>даст тот же результат.</p>
     <p>Другим способом указания пространства имен при использовании элемента <code>xsl:element</code> является использование атрибута <code>namespace</code>. Например, для предыдущего случая мы могли бы записать</p>
     <p><code>&lt;xsl:element</code></p>
     <p><code> name="template"</code></p>
     <p><code> namespace="http://www.w3.org/1999/XSL/Transform"/&gt;</code></p>
     <p>и получить в итоге</p>
     <p><code>&lt;template xmlns="http://www.w3.org/1999/XSL/Transform"/&gt;</code></p>
     <p>что эквивалентно результату предыдущего примера, хоть и различается внешне.</p>
     <p>Атрибут <code>namespace</code> тоже может быть сконструирован на этапе выполнения, например:</p>
     <p><code>&lt;xsl:element</code></p>
     <p><code> name="template"</code></p>
     <p><code> namespace="{concat('http://www.w3.org/', 2001 - 2, '/XSL/Transform')}"/&gt;</code></p>
     <p>что также даст элемент <code>template</code>, принадлежащий пространству имен XSLT.</p>
     <p>Для того чтобы разобраться в приоритетах атрибутов <code>name</code> и <code>namespace</code> на определение пространства имен, приведем несколько правил, которые пояснят этот процесс.</p>
     <p>&#9633; Если в элементе <code>xsl:element</code> определен атрибут <code>namespace</code>, то создаваемый элемент будет принадлежать пространству имен с URI, который будет значением этого атрибута. Если значением атрибута <code>namespace</code> будет пустая строка, создаваемый элемент будет принадлежать нулевому пространству имен. Как правило, процессоры используют префикс, указанный в имени атрибутом <code>name</code>, но, вместе с тем, они <emphasis>не обязаны</emphasis> так делать. Поэтому в общем случае следует ожидать, что префикс может быть любым.</p>
     <p>&#9633; Если в элементе <code>xsl:element</code> не определен атрибут <code>namespace</code>, но имя, заданное в атрибуте name имеет префикс, то создаваемый элемент будет принадлежать соответствующему этому префиксу пространству имен. Однако и в этом случае не гарантируется, что префикс создаваемого элемента будет таким, каким он был задан в атрибуте <code>name</code>.</p>
     <p>&#9633; В случае, если в элементе <code>xsl:element</code> не определен атрибут <code>namespace</code> и имя, заданное в атрибуте name не имеет префикса, создаваемый элемент будет принадлежать пространству имен, которое действует для создающего элемента <code>xsl:element</code> по умолчанию.</p>
     <p>Повторим еще раз, что во всех трех случаях сказать что-либо достоверно о префиксе создаваемого элемента нельзя — префикс с точки зрения пространств имен не является значащей частью имени элемента. Вместе с тем, на практике процессоры, как правило, используют префикс, указанный в атрибуте <code>name</code>, или не используют префикс вообще, если префикс в <code>name</code> указан не был.</p>
     <p>Приведем несколько примеров.</p>
     <p>Для начала покажем, что, согласно первому правилу, атрибут <code>namespace</code> имеет наивысший приоритет при определении пространства имен выходящего элемента. Рассмотрим следующее преобразование.</p>
     <subtitle>Листинг 7.4.</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code>&lt;xsl:element</code></p>
     <p><code> name="xsl:html"</code></p>
     <p><code> namespace="http://www.w3.org/1999/xhtml"/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>В выделенном элементе <code>xsl:element</code> пространство имен создаваемого элемента указано вроде бы два раза: в виде значения атрибута <code>namespace</code> и в виде префикса имени ("<code>xsl</code>"). Результат будет выглядеть следующим образом:</p>
     <p><code>&lt;xsl:html xmlns:xsl="http://www.w3.org/1999/xhtml"/&gt;</code></p>
     <p>Процессор использовал пространство имен, указанное в атрибуте <code>namespace</code>, локальную часть имени, заданного атрибутом name ("<code>html</code>"), а также префикс (только префикс, но не связанное с ним пространство имен) этого имени ("<code>xsl</code>").</p>
     <p>В свою очередь конструкция вида</p>
     <p><code>&lt;xsl:element name="xsl:html" namespace=""/&gt;</code></p>
     <p>создаст элемент</p>
     <p><code>&lt;xsl:html xmlns:xsl=""&gt;&lt;/xsl:html&gt;</code></p>
     <p>что на самом деле эквивалентно просто <code>&lt;html/&gt;</code>.</p>
     <p>Таким образом, атрибут <code>namespace</code> наиболее приоритетен для определения пространства имен создаваемого элемента. Обратимся теперь к случаю, когда этот атрибут опущен в <code>xsl:element</code>. Объявление вида</p>
     <p><code>&lt;xsl:element name="xsl:html"/&gt;</code></p>
     <p>создаст элемент</p>
     <p><code>&lt;xsl:html xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/&gt;</code></p>
     <p>Как видим, отсутствие <code>namespace</code> и <code>namespace=""</code> — не одно и то же.</p>
     <p>Рассмотрим теперь случай, когда нет ни атрибута <code>namespace</code>, ни префикса в <code>name</code>:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;xsl:element name="html"/&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результатом этого преобразования будет документ, состоящий из одного пустого элемента <code>html</code>:</p>
     <p><code>&lt;html/&gt;</code></p>
     <p>Мы специально привели все преобразование целиком, чтобы показать, что выходящий элемент будет принадлежать нулевому пространству имен тогда и только тогда, когда для него не было объявлено пространства имен по умолчанию. Попробуем посмотреть, что получится, если пространство имен по умолчанию будет объявлено:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/" xmlns="http://www.w3.org/1999/xhtml"&gt;</code></p>
     <p><code>  &lt;xsl:element name="html"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результатом в этот раз будет элемент с локальной частью имени "<code>html</code>", принадлежащий пространству имен с URI "<code>http://www.w3.org/1999/xhtml</code>":</p>
     <p><code>&lt;html xmlns="http://www.w3.org/1999/xhtml" /&gt;</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Создание узлов атрибутов</p>
    </title>
    <section>
     <title>
      <p>Элемент<emphasis> xsl:attribute</emphasis></p>
     </title>
     <p>Этот элемент задается конструкцией вида:</p>
     <p><code>&lt;xsl:attribute</code></p>
     <p><code> <strong>name</strong>="{<emphasis>имя</emphasis>}"</code></p>
     <p><code> namespace="{<emphasis>пространство имен</emphasis>}"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:attribute&gt;</code></p>
     <p>Использование элементов <code>xsl:attribute</code> и <code>xsl:element</code> во многом аналогично. Обязательный атрибут name указывает имя, а атрибут <code>namespace</code> — URI пространства имен создаваемого атрибута, причем процесс вычисления расширенного имени атрибута практически идентичен этому в процедуре вычисления имени элемента, который был приведен при разборе <code>xsl:element</code>.</p>
     <p>Показаний к применению <code>xsl:attribute</code> несколько больше, чем для <code>xsl:element</code>. В частности, <code>xsl:attribute</code> следует использовать, если:</p>
     <p>&#9633; требуется создать атрибут с не известным заранее именем или пространством имен;</p>
     <p>&#9633; требуется создать атрибут в пространстве имен, которое является для процессора значащим (например, в пространстве имен XSLT);</p>
     <p>&#9633; требуется создать атрибут, вычисление значения которого не может быть реализовано одним или несколькими XPath-выражениями (например, условный вывод атрибута).</p>
     <p>Приведем некоторые примеры.</p>
     <p>Покажем, как преобразовать структуру вида</p>
     <p><code>&lt;element name="record"&gt;</code></p>
     <p><code> &lt;attribute name="fieldcount" value="12"/&gt;</code></p>
     <p><code> &lt;attribute name="title" value="Aggregation"/&gt;</code></p>
     <p><code>&lt;/element&gt;</code></p>
     <p>в элемент</p>
     <p><code>&lt;record fieldcount="12" title="Aggregation"/&gt;</code></p>
     <p>Для достижения цели воспользуемся следующим преобразованием.</p>
     <subtitle>Листинг 7.5. Создание атрибутов при помощи xsl:attribute</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="element"&gt;</code></p>
     <p><code>  &lt;xsl:element name="{@name}"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="attribute"/&gt;</code></p>
     <p><code>  &lt;/xsl:element&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="attribute"&gt;</code></p>
     <p><code>  &lt;xsl:attribute name="{@name}"&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="@value"/&gt;</code></p>
     <p><code>  &lt;/xsl:attribute&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Элемент <code>xsl:attribute</code> не может использоваться где угодно: узлы атрибутов должны создаваться только как дочерние узлы узлов элементов. Более того, узлы атрибутов должны создаваться до создания дочерних узлов других типов — текста, элементов и так далее. Таким образом, <code>xsl:attribute</code> может быть использован в содержимом любого из следующих родителей:</p>
     <p>&#9633; литерального элемента результата;</p>
     <p>&#9633; элемента <code>xsl:element</code>;</p>
     <p>&#9633; элемента <code>xsl:copy</code> в случае, если текущий, копируемый узел является элементом;</p>
     <p>&#9633; элемента <code>xsl:attribute-set</code> в случае определения именованного набора атрибутов.</p>
     <p>При этом, как было показано в предыдущем примере, <code>xsl:attribute</code> не обязан использоваться только в качестве их непосредственного дочернего элемента. Главное, чтобы атрибуты создавались в элементах и только в элементах.</p>
     <p>Элемент <code>xsl:attribute</code> также не может использоваться для генерации объявлений пространств имен. В соответствии с технической рекомендацией XSLT, <code>xsl:attribute</code> не может создавать атрибуты, имена которых имеют префикс <code>xmlns</code>.</p>
     <p>Если атрибут создается в элементе, который уже имеет атрибут с таким же именем, старый атрибут будет переопределен новым значением.</p>
     <p>Рассмотрим пример.</p>
     <subtitle>Листинг 7.6. Фрагмент шаблона</subtitle>
     <p><code>&lt;а href="http://www.aaa.com"&gt;</code></p>
     <p><code> &lt;xsl:attribute name="href"&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;http://www.bbb.com&lt;/xsl:text&gt;</code></p>
     <p><code> &lt;/xsl:attribute&gt;</code></p>
     <p><code>&lt;/a&gt;</code></p>
     <subtitle>Листинг 7.7. Результат</subtitle>
     <p><code>&lt;a href="http://www.bbb.com"/&gt;</code></p>
     <p>Поскольку атрибут может содержать только текст, результатом выполнения содержимого <code>xsl:attribute</code> тоже должны быть только текстовые узлы. Процессор в лучшем случае проигнорирует нетекстовые узлы, в худшем выведет сообщение об ошибке, прервав дальнейшую обработку, так что следует очень внимательно относиться к содержимому <code>xsl:attribute</code>.</p>
     <p>Текстовое значение атрибута может задаваться не только символьными данными, Оно может генерироваться также элементами XSLT, такими, как, например, <code>xsl:text</code> и <code>xsl:value-of</code>. То есть вполне корректным будет следующее определение:</p>
     <p><code>&lt;xsl:attribute name="href"&gt;</code></p>
     <p><code> &lt;xsl:text&gt;http://&lt;/xsl:text&gt;</code></p>
     <p><code> &lt;xsl:value-of select="concat('www', '.', 'bbb')"/&gt;</code></p>
     <p><code> &lt;xsl:text&gt;.com&lt;/xsl:text&gt;</code></p>
     <p><code>&lt;/xsl:attribute&gt;</code></p>
     <p>В том случае, если текстовое значение атрибута содержит символы перевода строки, при генерации атрибута они будут заменены сущностями, то есть определение</p>
     <p><code>&lt;xsl:attribute name="href"&gt;а¶</code></p>
     <p><code> b&lt;/xsl:attribute&gt;</code></p>
     <p>создаст атрибут с именем "<code>href</code>" и значением "<code>a&amp;#xA;b</code>":</p>
     <p><code>&lt;а href="a&amp;#xA;b"/&gt;</code></p>
     <p>Техническая рекомендация объясняет такую ситуацию следующим образом: в соответствии со стандартом языка XML, символы перевода строки должны нормализоваться в значениях атрибутов пробелами, сущности же нормализовать не нужно. Но если бы символ перевода строки нормализовался в XSLT при выводе пробелом, то определения</p>
     <p><code>&lt;xsl:attribute name="href"&gt;a&#9633;b&lt;/xsl:attribute&gt;</code></p>
     <p>и</p>
     <p><code>&lt;xsl:attribute name="href"&gt;a¶</code></p>
     <p><code>b&lt;/xsl:attribute&gt;</code></p>
     <p>были бы эквивалентны, что не отражает реального положения вещей. Для того чтобы исправить эту несуразицу, символ перевода строки при выводе в атрибуте нормализуется в XSLT символьной сущностью (<code>&amp;#xA;</code> или <code>&amp;#10;</code>).</p>
     <p>Подводя итог, перечислим в краткой форме основные особенности обращения с <code>xsl:attribute</code>.</p>
     <p>&#9633; Атрибуты могут создаваться <emphasis>только в узлах элементов</emphasis>. Если атрибут создается в узле, который не является узлом элемента, процессор может либо выдать ошибку, либо проигнорировать создаваемый атрибут.</p>
     <p>&#9633; Атрибуты могут содержать <emphasis>только текстовые узлы</emphasis>. Процессор может либо выдать ошибку, либо проигнорировать нетекстовые узлы.</p>
     <p>&#9633; Узлы атрибутов <emphasis>должны быть первыми узлами</emphasis>, которые создаются в элементах. XSLT не разрешает создавать атрибуты после того, как в элемент включены дочерние узлы других типов.</p>
     <p>&#9633; В случае, когда документ преобразуется в другой XML-документ, символы перевода строки в элементе заменяются символьными сущностями.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Именованные наборы атрибутов</p>
    </title>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:attribute-set</emphasis></p>
     </title>
     <p>Синтаксис элемента определяется следующей конструкцией:</p>
     <p><code>&lt;xsl:attribute-set</code></p>
     <p><code> <strong>name</strong>="<emphasis>имя</emphasis>"</code></p>
     <p><code> use-attribute-sets="<emphasis>имена</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: несколько элементов xsl:attribute --&gt;</code></p>
     <p><code>&lt;/xsl:attribute-set&gt;</code></p>
     <p>Для того чтобы упростить создание в элементах целых наборов атрибутов, можно заранее определить их в элементе <code>xsl:attribute-set</code>. Обязательный атрибут <code>name</code> задает имя набора атрибутов. Элемент <code>xsl:attribute-set</code> содержит последовательность, состоящую из нуля или более элементов <code>xsl:attribute</code>.</p>
     <p>Именованные наборы атрибутов можно использовать, указывая их имена в значении атрибута <code>use-attribute-sets</code>, который может присутствовать в элементах <code>xsl:element</code>, <code>xsl:copy</code> и <code>xsl:attribute-set</code>, а также в литеральных результирующих элементах. В атрибуте <code>use-attribute-sets</code> через пробел перечисляются имена наборов атрибутов, которые должны быть использованы в данном элементе.</p>
     <p>Включение набора атрибутов в элемент равносильно простому копированию элементов <code>xsl:attribute</code>, определенных в соответствующих элементах <code>xsl:attribute-set</code>.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что во входящем документе нам нужно вывести структуру, состоящую из элементов с именем <code>element</code>, атрибут <code>name</code> которых равен имени, атрибут <code>attr-count</code> — количеству атрибутов, а атрибут <code>node-count</code> — количеству дочерних узлов соответствующего элемента.</p>
     <subtitle>Листинг 7.8. Входящий документ</subtitle>
     <p><code>&lt;a b="1" c="2"&gt;</code></p>
     <p><code> &lt;d e="3" f="4" g="5"/&gt;</code></p>
     <p><code>&lt;/a&gt;</code></p>
     <subtitle>Листинг 7.9. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> &lt;xsl:output indent="yes"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:attribute-set name="attrs"&gt;</code></p>
     <p><code>  &lt;xsl:attribute name="attr-count"&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="count(@*)"/&gt;</code></p>
     <p><code>  &lt;/xsl:attribute&gt;</code></p>
     <p><code> &lt;/xsl:attribute-set&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:attribute-set name="elements"&gt;</code></p>
     <p><code>  &lt;xsl:attribute name="name"&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="name()"/&gt;</code></p>
     <p><code>  &lt;/xsl:attribute&gt;</code></p>
     <p><code>  &lt;xsl:attribute name="node-count"&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="count(*)"/&gt;</code></p>
     <p><code>  &lt;/xsl:attribute&gt;</code></p>
     <p><code> &lt;/xsl:attribute-set&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="*"&gt;</code></p>
     <p><code>  &lt;xsl:element name="element"</code></p>
     <p><code>   use-attribute-sets="elements attrs"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="*"/&gt;</code></p>
     <p><code>  &lt;/xsl:element&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 7.10. Выходящий документ</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
     <p><code>&lt;element name="a" node-count="1" attr-count="2"&gt;</code></p>
     <p><code> &lt;element name="d" node-count="0" attr-count="3"/&gt;</code></p>
     <p><code>&lt;/element&gt;</code></p>
     <p>В этом преобразовании определение элемента</p>
     <p><code>&lt;xsl:element name="element"</code></p>
     <p><code> use-attribute-sets="elements attrs"&gt;</code></p>
     <p><code> &lt;xsl:apply-templates select="*"/&gt;</code></p>
     <p><code>&lt;/xsl:element&gt;</code></p>
     <p>равносильно определению</p>
     <p><code>&lt;xsl:element name="element"&gt;</code></p>
     <p><code> &lt;xsl:attribute name="name"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="name()"/&gt;</code></p>
     <p><code> &lt;/xsl:attribute&gt;</code></p>
     <p><code> &lt;xsl:attribute name="node-count"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="count(*)"/&gt;</code></p>
     <p><code> &lt;/xsl:attribute&gt;</code></p>
     <p><code> &lt;xsl:attribute name="attr-count"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="count(@*)"/&gt;</code></p>
     <p><code> &lt;/xsl:attribute&gt;</code></p>
     <p><code> &lt;xsl:apply-templates select="*"/&gt;</code></p>
     <p><code>&lt;/xsl:element&gt;</code></p>
     <p>Как уже было сказано, элемент <code>xsl:attribute-set</code> может также использовать другие наборы атрибутов при помощи <code>use-attribute-sets</code>. Например, в предыдущем преобразовании набор атрибутов <code>elements</code> мог быть определен как:</p>
     <p><code>&lt;xsl:attribute-set name="elements"</code></p>
     <p><code> use-attribute-sets="attrs"&gt;</code></p>
     <p><code> &lt;xsl:attribute name="name"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="name()"/&gt;</code></p>
     <p><code> &lt;/xsl:attribute&gt;</code></p>
     <p><code> &lt;xsl:attribute name="node-count"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="count(*)"/&gt;</code></p>
     <p><code> &lt;/xsl:attribute&gt;</code></p>
     <p><code>&lt;/xsl:attribute-set&gt;</code></p>
     <p>Тогда для достижения того же результата элемент с именем <code>element</code> мог быть создан с использованием только одного набора атрибутов:</p>
     <p><code>&lt;xsl:element name="element"</code></p>
     <p><code> use-attribute-sets="elements"&gt;</code></p>
     <p><code> &lt;xsl:apply-templates select="*"/&gt;</code></p>
     <p><code>&lt;/xsl:element&gt;</code></p>
     <p>Именованный набор атрибутов не может прямо или косвенно (посредством других наборов атрибутов) использовать в значении <code>use-attribute-sets</code> себя самого. Такая ситуация породила бы бесконечный цикл. Вообще, не рекомендуется выстраивать сложную иерархию именованных наборов атрибутов, поскольку это может сильно усложнить обработку и снизить эффективность преобразования, хотя, естественно, все зависит от конкретного случая.</p>
    </section>
    <section>
     <title>
      <p>Атрибут <emphasis>xsl:use-attribute-sets</emphasis></p>
     </title>
     <p>Мы упомянули о том, что именованные наборы атрибутов используются в элементах посредством атрибута <code>xsl:use-attribute-sets</code>. Разберем более детально, где этот атрибут может применяться, и какие функции он при этом выполняет. Для удобства эти данные сведены в табл. 7.1.</p>
     <empty-line/>
     <p><emphasis><strong>Таблица 7.1</strong>. Использование атрибута </emphasis><code><emphasis>xsl:use-attribute-sets</emphasis></code></p>
     <table>
      <tr>
       <th align="left">Родительский элемент</th>
       <th align="left">Особенности использования</th>
      </tr>
      <tr>
       <td align="left"><code>xsl:attribute-set</code></td>
       <td align="left">Включает в определяемый набор атрибутов атрибуты из перечисленных наборов</td>
      </tr>
      <tr>
       <td align="left"><code>xsl:element</code></td>
       <td align="left">Включает в создаваемый элемент атрибуты из перечисленных наборов. Включение эквивалентно текстовому включению — значения атрибутов вычисляются в контексте создающего элемента <code>xsl:element</code></td>
      </tr>
      <tr>
       <td align="left"><code>xsl:copy</code></td>
       <td align="left">Включает в копируемый элемент атрибуты из перечисленных наборов. Принцип действия— как в случае с <code>xsl:element</code>. Копируемый узел должен быть элементом</td>
      </tr>
      <tr>
       <td align="left">Литеральный результирующий элемент</td>
       <td align="left">Принцип действия такой же, как и в случае с <code>xsl:element</code>. В случае совпадения имен, значения атрибутов из набора будут переопределять значения атрибутов самого элемента. При использовании в литеральном элементе, атрибут <code>xsl:use-attribute-sets</code> должен быть обязательным образом объявлен принадлежащим пространству имен XSLT. Как правило, это делается указанием префикса <code>xsl</code></td>
      </tr>
     </table>
    </section>
   </section>
   <section>
    <title>
     <p>Создание текстовых узлов</p>
    </title>
    <section>
     <p>Шаблон преобразования может содержать текстовые узлы, которые при выполнении шаблона после обработки пробельных символов будут попросту скопированы в результирующее дерево. Таким образом, для того, чтобы вывести в выходящий документ некоторый текст, можно просто включить его в шаблон преобразования.</p>
     <p>Рассмотрим пример.</p>
     <subtitle>Листинг 7.11. Входящий документ</subtitle>
     <p><code>&lt;answer&gt;No!&lt;/answer&gt;</code></p>
     <subtitle>Листинг 7.12. Шаблон преобразования</subtitle>
     <p><code>&lt;xsl:template match="answer"&gt;</code></p>
     <p><code> The answer was &amp;quot;&lt;xsl:value-of select="text()"/&gt;&amp;quot;.</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <subtitle>Листинг 7.13. Созданный текст</subtitle>
     <p><code>The answer was "No!".</code></p>
     <p>Текстовые узлы могут также быть созданы элементами <code>xsl:text</code> и <code>xsl:value-of</code>. Элемент <code>xsl:text</code> используется для создания текстовых узлов, содержащих пробельные и специальные символы, в то время как элемент <code>xsl:value-of</code> выводит в выходящее дерево строковый результат вычисления выражений.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:text</emphasis></p>
     </title>
     <p>Синтаксис данного элемента представлен ниже:</p>
     <p><code>&lt;xsl:text</code></p>
     <p><code> disable-output-escaping="yes" | "no"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: символьные данные --&gt;</code></p>
     <p><code>&lt;/xsl:text&gt;</code></p>
     <p>Элемент <code>xsl:text</code> служит для того, чтобы создавать в выходящем документе текстовые узлы. При этом <code>xsl:text</code> имеет следующие особенности.</p>
     <p>&#9633; Преобразования будут сохранять пробельные символы, находящиеся в элементе <code>xsl:text</code>. То есть, для того чтобы вывести в выходящий документ пробельный символ, например такой, как символ перевода строки, достаточно написать</p>
     <p><code>&lt;xsl:text&gt;&amp;#10;&lt;/xsl:text&gt;</code></p>
     <p>&#9633; Элемент <code>xsl:text</code> имеет атрибут <code>disable-output-escaping</code>, который позволяет избежать замены в выходящем документе специальных символов на символьные или встроенные сущности. Например, для того, чтобы вывести символ "<code>&lt;</code>" можно указать в преобразовании</p>
     <p><code>&lt;xsl:text disable-output-escaping="yes"&gt;&amp;lt;&lt;/xsl:text&gt;</code></p>
     <p>В остальных случаях символьные данные, включенные в элемент <code>xsl:text</code>, ведут себя так же, как и вне <code>xsl:text</code>.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:value-of</emphasis></p>
     </title>
     <p>Этот элемент является одним из наиболее часто используемых в XSLT. Он служит для вычисления значений выражений.</p>
     <p>Синтаксическая конструкция элемента следующая:</p>
     <p><code>&lt;xsl:value-of</code></p>
     <p><code> <strong>select</strong>="<emphasis>выражение</emphasis>"</code></p>
     <p><code> disable-output-escaping="yes" | "no"/&gt;</code></p>
     <p>В обязательном атрибуте <code>select</code> этого элемента задается выражение, которое вычисляется процессором, затем преобразовывается в строку и выводится в результирующем дереве в виде текстового узла. Процессор не станет создавать текстовый узел, если результатом вычисления выражения была пустая строка. В целях оптимизации дерева, соседствующие текстовые узлы будут объединены в один.</p>
     <p>Элемент <code>xsl:value-of</code> очень похож на элемент <code>xsl:copy-of</code>, только в отличие от последнего он сначала преобразовывает вычисленное выражение к строковому виду, а уж затем выводит его в выходящий документ. Иными словами, выражение</p>
     <p><code>&lt;xsl:value-of select="<emphasis>выражение</emphasis>"/&gt;</code></p>
     <p>равносильно</p>
     <p><code>&lt;xsl:copy-of select="string{<emphasis>выражение</emphasis>}"/&gt;</code></p>
     <p>Соответственно, преобразование различных типов данных в строковый тип производится точно так же, как если бы мы использовали для этой цели функцию <code>string</code>.</p>
     <subtitle>Пример</subtitle>
     <p>Для составления таблицы умножения можно воспользоваться следующим преобразованием.</p>
     <subtitle>Листинг 7.14. Входящий документ</subtitle>
     <p><code>&lt;numbers&gt;</code></p>
     <p><code> &lt;number&gt;1&lt;/number&gt;</code></p>
     <p><code> &lt;number&gt;2&lt;/number&gt;</code></p>
     <p><code> &lt;number&gt;3&lt;/number&gt;</code></p>
     <p><code> &lt;number&gt;4&lt;/number&gt;</code></p>
     <p><code> &lt;number&gt;5&lt;/number&gt;</code></p>
     <p><code> &lt;number&gt;6&lt;/number&gt;</code></p>
     <p><code> &lt;number&gt;7&lt;/number&gt;</code></p>
     <p><code> &lt;number&gt;8&lt;/number&gt;</code></p>
     <p><code> &lt;number&gt;9&lt;/number&gt;</code></p>
     <p><code>&lt;/numbers&gt;</code></p>
     <subtitle>Листинг 7.15. Преобразование, создающее таблицу умножения</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:output method="text"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="numbers"&gt;</code></p>
     <p><code>  &lt;xsl:variable name="numbers" select="number"/&gt;</code></p>
     <p><code>  &lt;xsl:for-each select="$numbers"&gt;</code></p>
     <p><code>   &lt;xsl:variable name="a" select="."/&gt;</code></p>
     <p><code>   &lt;xsl:for-each select="$numbers"&gt;</code></p>
     <p><code>    &lt;xsl:variable name="b" select="."/&gt;</code></p>
     <p><code>    &lt;!-- Если результат произведения меньше 10, добавляем пробел --&gt;</code></p>
     <p><code>    &lt;xsl:if test="$a * $b &amp;lt; 10"&gt;</code></p>
     <p><code>     &lt;xsl:text&gt; &lt;/xsl:text&gt;</code></p>
     <p><code>    &lt;/xsl:if&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="$a*$b"/&gt;</code></p>
     <p><code>    &lt;xsl:text&gt; &lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;/xsl:for-each&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;/xsl:for-each&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 7.16. Выходящий документ</subtitle>
     <p><code>1  2  3  4  5  6  7  8  9</code></p>
     <p><code>2  4  6  8 10 12 14 16 18</code></p>
     <p><code>3  6  9 12 15 18 21 24 27</code></p>
     <p><code>4  8 12 16 20 24 28 32 36</code></p>
     <p><code>5 10 15 20 25 30 35 40 45</code></p>
     <p><code>6 12 18 24 30 36 42 48 54</code></p>
     <p><code>7 14 21 28 35 42 49 56 63</code></p>
     <p><code>8 16 24 32 40 48 56 64 72</code></p>
     <p><code>9 18 27 36 45 54 63 72 81</code></p>
     <p>В данном случае элемент <code>xsl:value-of</code> используется для вычисления произведения переменных <code>a</code> и <code>b</code>. Численный результат преобразуется в строку и выводится в выходящий документ в виде текста.</p>
     <p>Равно, как и <code>xsl:text</code>, элемент <code>xsl:value-of</code> может иметь атрибут <code>disable-output-escaping</code>, полезный для вывода специальных символов, которые в противном случае были бы заменены сущностями.</p>
     <subtitle>Пример</subtitle>
     <p>Результатом выполнения элемента</p>
     <p><code>&lt;xsl:value-of select="concat('Divide ', '&amp;amp;', ' impera')"/&gt;</code></p>
     <p>будет текстовый узел</p>
     <p><code>Divide &amp;amp; impera</code></p>
     <p>Чтобы придать амперсанту более привычный вид, мы можем использовать атрибут <code>disable-output-escaping</code>:</p>
     <p><code>&lt;xsl:value-of</code></p>
     <p><code>select="concat('Divide ', '&amp;amp;', ' impera')"</code></p>
     <p><code>disable-output-escaping="yes"/&gt;</code></p>
     <p>Результатом выполнения этого шаблона уже будет текст:</p>
     <p><code>Divide &amp; impera</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Создание узлов комментариев и инструкций по обработке</p>
    </title>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:comment</emphasis></p>
     </title>
     <p>Этот элемент задается конструкцией вида:</p>
     <p><code>&lt;xsl:comment&gt;</code></p>
     <p><code>&lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:comment&gt;</code></p>
     <p>Элемент <code>xsl:comment</code> создает в результирующем дереве узел комментария. Текстом комментария становится результат выполнения шаблона, который содержится в элементе <code>xsl:comment</code>.</p>
     <p>Точно так же как и в случае с <code>xsl:processing-instruction</code>, результат выполнения шаблона должен содержать только текстовые узлы. Узлы других типов будут либо проигнорированы, либо вызовут ошибку.</p>
     <p>В соответствии с синтаксисом XML, комментарий в XML не может содержать двух знаков "<code>-</code>" последовательно ("<code>--</code>") и оканчиваться на "<code>-</code>". Поэтому наличие таких последовательностей символов в тексте комментария будет являться в XSLT ошибкой. Для того чтобы избежать некорректного синтаксиса, процессор может разделять два последовательных минуса пробелом (заменять "<code>--</code>" на "<code>- -</code>") или добавлять пробел после завершающего минуса комментария.</p>
     <subtitle>Пример</subtitle>
     <p>Элемент:</p>
     <p><code>&lt;xsl:comment&gt;&amp;#xA; | Please remove this later&amp;#xA; +&lt;/xsl:comment&gt;</code></p>
     <p>создаст комментарий:</p>
     <p><code>&lt;!--</code></p>
     <p><code> | Please remove this later</code></p>
     <p><code> +--&gt;</code></p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:processing-instruction</emphasis></p>
     </title>
     <p>Синтаксис элемента представлен ниже:</p>
     <p><code>&lt;xsl:processing-instruction</code></p>
     <p><code> <strong>name</strong>="{<emphasis>имя</emphasis>}"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:processing-instruction&gt;</code></p>
     <p>Элемент <code>xsl:processing-instruction</code> создает в результирующем дереве узел инструкции по обработке. Обязательный атрибут name определяет имя целевого приложения, которому будет адресована инструкция по обработке. В этом атрибуте может быть указан шаблон значения атрибута.</p>
     <subtitle>Пример</subtitle>
     <p>Элемент:</p>
     <p><code>&lt;xsl:processing-instruction name="servlet"&gt;</code></p>
     <p><code> &lt;xsl:text&gt;links="follow" session-timeout="7200000"&lt;/xsl:text&gt;</code></p>
     <p><code>&lt;/xsl:processing-instruction&gt;</code></p>
     <p>создаст в выходящем документе инструкцию по обработке вида:</p>
     <p><code>&lt;?servlet links="follow" session-timeout="7200000"?&gt;</code></p>
     <p>Содержимым создаваемой инструкции по обработке является результат выполнения шаблона, содержащегося внутри элемента <code>xsl:processing- instruction</code>. Этот результат должен содержать только текстовые узлы, в противном случае процессор может либо выдать ошибку, либо проигнорировать нетекстовые узлы вместе с их содержимым.</p>
     <p>Инструкция по обработке не может содержать последовательности символов "<code>?&gt;</code>", поскольку это было бы некорректно с точки зрения синтаксиса XML.</p>
     <p>В случае, если результат выполнения шаблона содержит такую комбинацию, процессор может либо выдать ошибку, либо разделить символы "<code>?</code>" и "<code>&gt;</code>" пробелом:"<code>? &gt;</code>".</p>
     <p>Имя инструкции по обработке, должно быть корректным XML-именем (но не равным при этом "<code>xml</code>" в любом регистре символов). Например, следующее определение будет совершенно корректным:</p>
     <p><code>&lt;xsl:processing-instruction name="_"&gt;</code></p>
     <p><code> &lt;xsl:text&gt;logout _&lt;/xsl:text&gt;</code></p>
     <p><code>&lt;/xsl:processing-instruction&gt;</code></p>
     <p>В результате получится следующая инструкция: <code>&lt;?_ logout _?&gt;</code></p>
     <p>Для того чтобы создать в выходящем XML-документе инструкцию <code>xml-stylesheet</code>, которая используется для связывания документов со стилями и преобразованиями, можно воспользоваться следующим определением:</p>
     <p><code>&lt;xsl:processing-instruction name="xml-stylesheet"&gt;</code></p>
     <p><code> &lt;xsl:text&gt;href="style.xsl" type="text/xsl"&lt;/xsl:text&gt;</code></p>
     <p><code>&lt;/xsl:processing-instruction&gt;</code></p>
     <p>Результирующий документ будет содержать инструкцию по обработке в виде:</p>
     <p><code>&lt;?xml-stylesheet href="style.xsl" type="text/xsl"?&gt;</code></p>
     <p>Элемент <code>xsl:processing-instruction</code> не может создать декларацию XML, несмотря на то, что с точки зрения синтаксиса (но не семантики) она имеет форму инструкции по обработке. Для вывода XML-декларации следует использовать элемент <code>xsl:output</code>.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Копирование узлов</p>
    </title>
    <section>
     <p>Преобразование может включать в себя не только создание новых, но и копирование существующих узлов. Для этого можно использовать элементы <code>xsl:copy</code> и <code>xsl:copy-of</code>, использование которых будет подробно разобрано ниже.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:copy</emphasis></p>
     </title>
     <p>Ниже представлена синтаксическая конструкция этого элемента:</p>
     <p><code>&lt;xsl:copy</code></p>
     <p><code> use-attribute-sets = "<emphasis>наборы атрибутов</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:copy&gt;</code></p>
     <p>Элемент <code>xsl:copy</code> создает копию текущего узла вне зависимости от его типа. Вместе с текущим узлом в выходящее дерево копируются только узлы пространств имен, ассоциированные с ним. Дочерние узлы и узлы атрибутов в выходящий документ не копируются.</p>
     <p>Если <code>xsl:copy</code> используется для копирования корневого узла или узда элемента, в выходящем документе процессор создает дочерний фрагмент дерева, являющийся результатом выполнения шаблона, содержащегося в <code>xsl:copy</code>.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что в каждый элемент преобразовываемого документа нам нужно добавить атрибут <code>element-count</code> со значением, равным количеству его дочерних элементов, а все остальные узлы оставить, как есть.</p>
     <subtitle>Листинг 7.17. Входящий документ</subtitle>
     <p><code>&lt;а&gt; text</code></p>
     <p><code> &lt;b attr="value"/&gt;</code></p>
     <p><code> &lt;c/&gt;</code></p>
     <p><code> &lt;d&gt;</code></p>
     <p><code>  text</code></p>
     <p><code>  &lt;e/&gt;</code></p>
     <p><code> &lt;/d&gt;</code></p>
     <p><code>&lt;/a&gt;</code></p>
     <subtitle>Листинг 7.18. Шаблон преобразования</subtitle>
     <p><code>&lt;xsl:template match="@*|node()"&gt;</code></p>
     <p><code> &lt;xsl:copy&gt;</code></p>
     <p><code>  &lt;xsl:attribute name="element-count"&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="count(*) "/&gt;</code></p>
     <p><code>  &lt;/xsl:attribute&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code> &lt;/xsl:copy&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <subtitle>Листинг 7.19. Выходящий элемент</subtitle>
     <p><code>&lt;a element-count="3"&gt;</code></p>
     <p><code> text</code></p>
     <p><code> &lt;b element-count="0" attr="value"/&gt;</code></p>
     <p><code> &lt;c element-count="0"/&gt;</code></p>
     <p><code> &lt;d element-count="1"&gt;</code></p>
     <p><code>  text</code></p>
     <p><code>  &lt;e element-count="0"/&gt;</code></p>
     <p><code> &lt;/d&gt;</code></p>
     <p><code>&lt;/a&gt;</code></p>
     <p>Если <code>xsl:copy</code> используется для создания в выходящем документе копии узла элемента, в него при помощи атрибута <code>use-attribute-sets</code> могут быть также включены именованные наборы атрибутов (<emphasis>см. раздел "Именованные наборы атрибутов" данной главы</emphasis>).</p>
     <subtitle>Пример</subtitle>
     <p>Предыдущее преобразование может быть переписано в виде</p>
     <p><code>&lt;xsl:attribute-set name="elements"&gt;</code></p>
     <p><code> &lt;xsl:attribute name="element-count"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="count(*)"/&gt;</code></p>
     <p><code> &lt;/xsl:attribute&gt;</code></p>
     <p><code>&lt;/xsl:attribute-set&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:template match="@*|node()"&gt;</code></p>
     <p><code> &lt;xsl:copy use-attribute-sets="elements"&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code> &lt;/xsl:copy&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Результат преобразования будет абсолютно идентичен выходящему документу, полученному в предыдущем примере.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:copy-of</emphasis></p>
     </title>
     <p>Синтаксис элемента несложен:</p>
     <p><code>&lt;xsl:copy-of</code></p>
     <p><code> <strong>select</strong>="<emphasis>выражение</emphasis>"/&gt;</code></p>
     <p>Использование элемента <code>xsl:copy-of</code> полностью аналогично использованию элемента <code>xsl:value</code>-of за тем исключением, что <code>xsl:copy-of</code> при выводе значения выражения преобразует его к строке не во всех случаях. Поведение <code>xsl:copy-of</code> зависит от того, какой тип данных возвращает выражение.</p>
     <p>&#9633; Если результат вычисления имеет булевый, числовой или строковый тип, то <code>xsl:copy-of</code> выводит его в виде текстового узла. В этом случае поведение <code>xsl:copy-of</code> абсолютно не отличается от поведения элемента <code>xsl:value-of</code>.</p>
     <p>&#9633; Если результатом вычисления выражения является множество узлов (node-set), то <code>xsl:copy-of</code> копирует в выходящий документ все узлы в порядке просмотра документа вместе с их потомками.</p>
     <p>&#9633; Если результатом вычисления является результирующий фрагмент дерева, то он копируется в выходящий документ в неизмененном виде.</p>
     <p>Рассмотрим пример.</p>
     <subtitle>Листинг 7.20. Входящий документ</subtitle>
     <p><code>&lt;values&gt;</code></p>
     <p><code> &lt;boolean&gt;false&lt;/boolean&gt;</code></p>
     <p><code> &lt;string&gt;text&lt;/string&gt;</code></p>
     <p><code> &lt;number&gt;3.14&lt;/number&gt;</code></p>
     <p><code> &lt;node-set&gt;</code></p>
     <p><code>  &lt;item&gt;10&lt;/item&gt;</code></p>
     <p><code>  &lt;item&gt;20&lt;/item&gt;</code></p>
     <p><code>  &lt;item&gt;30&lt;/item&gt;</code></p>
     <p><code> &lt;/node-set&gt;</code></p>
     <p><code> &lt;tree&gt;</code></p>
     <p><code>  text</code></p>
     <p><code>  &lt;root&gt;</code></p>
     <p><code>   text</code></p>
     <p><code>   &lt;branch&gt;</code></p>
     <p><code>    text</code></p>
     <p><code>    &lt;leaf/&gt;</code></p>
     <p><code>    &lt;leaf/&gt;</code></p>
     <p><code>   &lt;/branch&gt;</code></p>
     <p><code>   &lt;leaf/&gt;</code></p>
     <p><code>  &lt;/root&gt;</code></p>
     <p><code> &lt;/tree&gt;</code></p>
     <p><code>&lt;/values&gt;</code></p>
     <subtitle>Листинг 7.21. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:variable name="boolean" select="values/boolean='true'"/&gt;</code></p>
     <p><code>  &lt;xsl:variable name="string" select="string(values/string)"/&gt;</code></p>
     <p><code>  &lt;xsl:variable name="number" select="number(values/number)"/&gt;</code></p>
     <p><code>  &lt;xsl:variable name="node-set" select="values/node-set/*"/&gt;</code></p>
     <p><code>  &lt;xsl:variable name="tree"&gt;</code></p>
     <p><code>   &lt;xsl:copy-of select="values/tree/*"/&gt;</code></p>
     <p><code>  &lt;/xsl:variable&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;xsl:text&gt;&amp;#10;Value-of boolean:&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="$boolean"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#10;Copy-of boolean:&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$boolean"/&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;xsl:text&gt;&amp;#10;Value-of string:&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="$string"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#10;Copy-of string:&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$string"/&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;xsl:text&gt;&amp;#10;Value-of number:&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="$number"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#10;Copy-of number:&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$number"/&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;xsl:text&gt;&amp;#10;Value-of node-set:&lt;/xsl:text&gt; </code></p>
     <p><code>  &lt;xsl:value-of select="$node-set"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#10;Copy-of node-set:&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$node-set"/&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;xsl:text&gt;&amp;#10;Value-of tree:&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="$tree"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#10;Copy-of tree:&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$tree"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 7.22. Выходящий документ</subtitle>
     <p><code>Value-of boolean:false</code></p>
     <p><code>Copy-of boolean:false</code></p>
     <p><code>Value-of string:text</code></p>
     <p><code>Copy-of string:text</code></p>
     <p><code>Value-of number:3.14</code></p>
     <p><code>Copy-of number:3.14</code></p>
     <p><code>Value-of node-set:10</code></p>
     <p><code>Copy-of node-set:&lt;item&gt;10&lt;/item&gt;&lt;item&gt;20&lt;/item&gt;&lt;item&gt;30&lt;/item&gt;</code></p>
     <p><code>Value-of tree:</code></p>
     <p><code>  text</code></p>
     <empty-line/>
     <p><code>   text</code></p>
     <empty-line/>
     <p><code>Copy-of tree:&lt;root&gt;</code></p>
     <p><code>  text</code></p>
     <p><code>  &lt;branch&gt;</code></p>
     <p><code>   text</code></p>
     <p><code>   &lt;leaf/&gt;</code></p>
     <p><code>   &lt;leaf/&gt;</code></p>
     <p><code>  &lt;/branch&gt;</code></p>
     <p><code>  &lt;leaf/&gt;</code></p>
     <p><code> &lt;/root&gt;</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Условная обработка</p>
    </title>
    <section>
     <p>В XSLT имеются две инструкции, которые поддерживают условную обработку — <code>xsl:if</code> и <code>xsl:choose</code>. Инструкция <code>xsl:if</code> позволяет создавать простые условия типа "если-то", в то время как <code>xsl:choose</code> создает более сложную конструкцию для выбора одной из нескольких имеющихся возможностей в зависимости от выполнения тех или иных условий.</p>
    </section>
    <section>
     <title>
      <p>Элемент xsl:if</p>
     </title>
     <p>Синтаксис элемента следующий:</p>
     <p><code>&lt;xsl:if</code></p>
     <p><code> <strong>test</strong>="<emphasis>выражение</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:if&gt;</code></p>
     <p>Элемент <code>xsl:if</code> является простейшим условным оператором в XSLT. Выражение, содержащееся в обязательном атрибуте <code>test</code>, вычисляется и приводится к булевому типу. В том и только том случае, если выражение имеет значение <code>true</code>, процессор выполняет шаблон, содержащийся в <code>xsl:if</code>.</p>
     <p>Вследствие того, что атрибуты в XML не могут содержать некоторые специальные символы (такие как "<code>&lt;</code>" и "<code>&amp;</code>"), их необходимо заменять символьными сущностями. В особенности это касается сравнения чисел типа "меньше"; объявление вида</p>
     <p><code>&lt;xsl:if test="a &lt; b"/&gt;</code></p>
     <p>будет с точки зрения синтаксиса XML некорректным. Вместо него следует использовать эквивалентное объявление</p>
     <p><code>&lt;xsl:if test="a &amp;lt; b"/&gt;</code></p>
     <p>Следует заметить, что символ "больше" ("<code>&gt;</code>") заменять сущностью необязательно. Однако из соображений единообразия принято заменять и его.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, мы преобразовываем список названий</p>
     <p><code>&lt;list active="Bravo"&gt;</code></p>
     <p><code> &lt;item&gt;Alpha&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;Bravo&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;Charlie&lt;/item&gt;</code></p>
     <p><code>&lt;/list&gt;</code></p>
     <p>во фрагмент HTML-кода, в котором каждый элемент <code>item</code> должен быть преобразован в соответствующий элемент <code>option</code>, а значение, выбранное во входящем документе атрибутом <code>active</code> элемента <code>list</code>, должно быть помечено булевым атрибутом <code>selected</code>.</p>
     <subtitle>Листинг 7.23. Шаблон преобразования, использующий элемент xsl:if</subtitle>
     <p><code>&lt;xsl:template match="item"&gt;</code></p>
     <p><code> &lt;option&gt;</code></p>
     <p><code>  &lt;!--</code></p>
     <p><code>   | Если текстовое значение элемента равно</code></p>
     <p><code>   | значению атрибута active его родительского элемента</code></p>
     <p><code>   +--&gt;</code></p>
     <p><code>  &lt;xsl:if test=". = ../@active"&gt;</code></p>
     <p><code>   &lt;!-- To выводим атрибут selected --&gt;</code></p>
     <p><code>   &lt;xsl:attribute name="selected"&gt;selected&lt;/xsl:attribute&gt;</code></p>
     <p><code>  &lt;/xsl:if&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code> &lt;/option&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Результат:</p>
     <p><code>&lt;option&gt;Alpha&lt;/option&gt;</code></p>
     <p><code>&lt;option selected&gt;Bravo&lt;/option&gt;</code></p>
     <p><code>&lt;option&gt;Charlie&lt;/option&gt;</code></p>
     <cite>
      <subtitle>Примечание</subtitle>
      <p>В данном преобразовании использовался метод вывода "<code>html</code>". Подробнее о методах вывода выходящего документа <emphasis>см. раздел "Контроль вывода документа" 8 главы</emphasis>.</p>
     </cite>
     <p>К сожалению, элемент <code>xsl:if</code> в XSLT не может реализовать конструкцию if-then-else (англ. если-то-иначе). Условные выражения такого вида реализуются при помощи элементов <code>xsl:choose</code>, <code>xsl:when</code> и <code>xsl:otherwise</code>.</p>
    </section>
    <section>
     <title>
      <p>Элементы xsl:choose, xsl:when, xsl:otherwise</p>
     </title>
     <p>Ниже даны синтаксические конструкции этих элементов:</p>
     <p><code>&lt;xsl:choose&gt;</code></p>
     <p><code> &lt;!--</code></p>
     <p><code>  | Содержимое: один или более элемент xsl:when, опциональный</code></p>
     <p><code>  | элемент xsl:otherwise</code></p>
     <p><code>  +--&gt;</code></p>
     <p><code>&lt;/xsl:choose&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:when</code></p>
     <p><code> <strong>test</strong>="<emphasis>выражение</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:when&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:otherwise&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:otherwise&gt;</code></p>
     <p>Элемент <code>xsl:choose</code> содержит один или несколько элементов <code>xsl:when</code> и необязательный элемент <code>xsl:otherwise</code>. При обработке <code>xsl:choose</code> процессор поочередно вычисляет выражения, содержащиеся в атрибутах <code>test</code> элементов <code>xsl:when</code>, приводит их к булевому типу и выполняет содержимое первого (и только первого) элемента, тестовое выражение которого будет равно <code>true</code>. В случае если ни одно из тестовых выражений не обратилось в "истину" и в <code>xsl:choose</code> присутствует <code>xsl:otherwise</code>, процессор выполнит содержимое этого элемента.</p>
     <p>Элементы <code>xsl:choose</code>, <code>xsl:when</code> и <code>xsl:otherwise</code> можно совместно использовать для получения конструкции типа if-then-else. Условие вида "если выражение <code><emphasis>A</emphasis></code> истинно, то выполнить действие <code><emphasis>B</emphasis></code> иначе выполнить действие <code><emphasis>C</emphasis></code>", которое в других языках программирования может быть записано, к примеру, как</p>
     <p><code>если</code></p>
     <p><code> верно <emphasis>условиеА</emphasis></code></p>
     <p><code>то</code></p>
     <p><code> выполнить <emphasis>шаблонB</emphasis></code></p>
     <p><code>иначе</code></p>
     <p><code> выполнить <emphasis>шаблонC</emphasis></code></p>
     <p>в XSLT может быть определено следующим образом:</p>
     <p><code>&lt;xsl:choose&gt;</code></p>
     <p><code> &lt;xsl:when test="<emphasis>условиеА</emphasis>"&gt;</code></p>
     <p><code><emphasis>  шаблонB</emphasis></code></p>
     <p><code> &lt;/xsl:when&gt;</code></p>
     <p><code> &lt;xsl:otherwise&gt;</code></p>
     <p><code>  шаблонC</code></p>
     <p><code> &lt;/xsl:otherwise&gt;</code></p>
     <p><code>&lt;/xsl:choose&gt;</code></p>
     <p>Вместе с тем, условие вида "если — то — иначе" это не все, на что способен элемент <code>xsl:choose</code>. Возможность указывать несколько элементов <code>xsl:when</code> позволяет записывать более сложные условия выбора вида:</p>
     <p><code>если</code></p>
     <p><code> верно <emphasis>условие1</emphasis></code></p>
     <p><code>то</code></p>
     <p><code> выполнить <emphasis>шаблон1</emphasis></code></p>
     <p><code>иначе если</code></p>
     <p><code> верно <emphasis>условие2</emphasis></code></p>
     <p><code>то</code></p>
     <p><code> выполнить <emphasis>шаблон2</emphasis></code></p>
     <p><code> ...</code></p>
     <p><code>иначе если</code></p>
     <p><code> верно <emphasis>условиеN</emphasis></code></p>
     <p><code>то</code></p>
     <p><code> выполнить <emphasis>шаблонN</emphasis></code></p>
     <p><code>иначе</code></p>
     <p><code> выполнить <emphasis>шаблонМ</emphasis></code></p>
     <p>Такой множественный условный переход совершенно прозрачно оформляется в виде следующей <code>xsl:choose</code>-конструкции:</p>
     <p><code>&lt;xsl:choose&gt;</code></p>
     <p><code> &lt;xsl:when test="<emphasis>условие1</emphasis>"&gt;</code></p>
     <p><code><emphasis>  шаблон1</emphasis></code></p>
     <p><code> &lt;/xsl:when&gt;</code></p>
     <p><code> &lt;xsl:when test="<emphasis>условие2</emphasis>"&gt;</code></p>
     <p><code><emphasis>  шаблон2</emphasis></code></p>
     <p><code> &lt;/xsl:when&gt;</code></p>
     <p><code> &lt;!-- ... --&gt;</code></p>
     <p><code> &lt;xsl:when test="<emphasis>условиеN</emphasis>"&gt;</code></p>
     <p><code><emphasis>  шаблонN</emphasis></code></p>
     <p><code> &lt;/xsl:when&gt;</code></p>
     <p><code> &lt;xsl:otherwise&gt;</code></p>
     <p><code><emphasis>  шаблонМ</emphasis></code></p>
     <p><code> &lt;/xsl:otherwise&gt;</code></p>
     <p><code>&lt;/xsl:choose&gt;</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Циклическая обработка</p>
    </title>
    <section>
     <title>
      <p>Элемент<emphasis> xsl:for-each</emphasis></p>
     </title>
     <p>Конструкция этого элемента такова:</p>
     <p><code>&lt;xsl:for-each</code></p>
     <p><code> <strong>select</strong>="<emphasis>выражение</emphasis>"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: несколько элементов xsl:sort, шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:for-each&gt;</code></p>
     <p>Элемент <code>xsl:for-each</code> используется для создания в выходящем документе повторяемых частей структуры. Обязательный атрибут <code>select</code> указывает выражение, результатом вычисления которого должно быть множество узлов. Шаблон, содержащийся в <code>xsl:for-each</code>, будет выполнен процессором для каждого узла этого множества.</p>
     <subtitle>Пример</subtitle>
     <p>Мы можем использовать <code>xsl:for-each</code> для того, чтобы создать список гипертекстовых ссылок для документа вида.</p>
     <subtitle>Листинг 7.24. Входящий документ</subtitle>
     <p><code>&lt;html&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;title&gt;I'm just a simple page...&lt;/title&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code> &lt;body&gt;</code></p>
     <p><code>  Please visit &lt;a href="http://www.aaa.com"&gt;this link&lt;/a&gt;.</code></p>
     <p><code>  Or &lt;a href="http://www.bbb.com"&gt;this one&lt;/a&gt;.</code></p>
     <p><code>  Or visit &lt;a href="http://www.ccc.com"&gt;this site&lt;/a&gt;.</code></p>
     <p><code>  Or click &lt;a href="http://www.ddd.com"&gt;here&lt;/a&gt;.</code></p>
     <p><code> &lt;/body&gt;</code></p>
     <p><code>&lt;/html&gt;</code></p>
     <p>Будем считать, что в этом документе элементы гипертекстовых ссылок а являются потомками элемента <code>body</code>, который находится в элементе <code>html</code>.</p>
     <subtitle>Листинг 7.25. Шаблон преобразования</subtitle>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;links&gt;</code></p>
     <p><code>  &lt;xsl:for-each select="/html/body//a"&gt;</code></p>
     <p><code>   &lt;a href="{@href}"&gt;</code></p>
     <p><code>    &lt;xsl:value-of select = "@href"/&gt;</code></p>
     <p><code>   &lt;/a&gt;</code></p>
     <p><code>  &lt;/xsl:for-each&gt;</code></p>
     <p><code> &lt;/links&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <subtitle>Листинг 7.26. Результат преобразования</subtitle>
     <p><code>&lt;links&gt;</code></p>
     <p><code> &lt;a href="http://www.aaa.com"&gt;http://www.aaa.com&lt;/a&gt;</code></p>
     <p><code> &lt;a href="http://www.bbb.com"&gt;http://www.bbb.com&lt;/a&gt;</code></p>
     <p><code> &lt;a href="http://www.ccc.com"&gt;http://www.ccc.com&lt;/a&gt;</code></p>
     <p><code> &lt;a href="http://www.ddd.com"&gt;http://www.ddd.com&lt;/a&gt;</code></p>
     <p><code>&lt;/links&gt;</code></p>
     <p>Элемент <code>xsl:for-each</code> изменяет контекст преобразования. Множество узлов, возвращаемое выражением в атрибуте <code>select</code>, становится текущим множеством узлов, а узел, шаблон для которого выполняется в данный момент, становится текущим узлом.</p>
     <p>Как мы знаем, множества узлов в XSLT не имеют внутреннего порядка. Однако, обработка узлов в <code>xsl:for-each</code> будет происходить в так называемом порядке просмотра документа, который зависит от того, какое выражение использовалось для вычисления обрабатываемого множества. Порядок обработки множества узлов в <code>xsl:for-each</code> может быть также изменен элементами <code>xsl:sort</code>, которые могут присутствовать в <code>xsl:for-each</code>. Элемент <code>xsl:sort</code> задает сортировку обрабатываемого множества узлов, изменяя, таким образом, порядок просмотра, что часто бывает очень полезно.</p>
    </section>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 8</p>
    <p>Дополнительные элементы и функции языка XSLT</p>
   </title>
   <section>
    <title>
     <p>Дополнительные элементы и функции</p>
    </title>
    <p>В этой главе разбираются дополнительные элементы и функции языка XSLT, которые выполняют в преобразованиях различные задачи, непосредственно не связанные с созданием узлов выходящего документа. Дополнительные элементы и функции XSLT расширяют возможности преобразования, предоставляя разного рода вспомогательный сервис.</p>
    <p>К дополнительным элементам XSLT мы отнесем следующие:</p>
    <p>&#9633; <code>xsl:preserve-space</code> и <code>xsl:strip-space</code> — работа с пробельными символами;</p>
    <p>&#9633; <code>xsl:message</code> — сообщения процессора;</p>
    <p>&#9633; <code>xsl:sort</code> — сортировка множеств перед обработкой;</p>
    <p>&#9633; <code>xsl:namespace-alias</code> — определение псевдонимов пространств имен;</p>
    <p>&#9633; <code>xsl:key</code> — определение ключей;</p>
    <p>&#9633; <code>xsl:number</code> — нумерация;</p>
    <p>&#9633; <code>xsl:decimal-format</code> — определение десятичного формата;</p>
    <p>&#9633; <code>xsl:output</code> — контроль сериализации.</p>
    <p>В XSLT также определяются дополнительные функции, расширяющие базовую библиотеку функций XPath:</p>
    <p>&#9633; <code>key</code> — использование ключей;</p>
    <p>&#9633; <code>format-number</code> — форматирование чисел;</p>
    <p>&#9633; <code>document</code> — обращение к внешним документам;</p>
    <p>&#9633; <code>current</code> — обращение к текущему узлу преобразования;</p>
    <p>&#9633; <code>unparsed-entity-uri</code> — получение URI неразбираемой сущности по ее имени;</p>
    <p>&#9633; <code>generate-id</code> — генерация уникального идентификатора узла документа;</p>
    <p>&#9633; <code>system-property</code> — получение информации о свойствах системы, окружения.</p>
   </section>
   <section>
    <title>
     <p>Обработка пробельных символов</p>
    </title>
    <section>
     <p>В XSLT выделяются четыре пробельных символа, обработка которых несколько отличается от обработки других символов. Их Unicode-коды и описания сведены в табл. 8.1.</p>
     <empty-line/>
     <p><emphasis><strong>Таблица 8.1</strong>. Unicode-коды пробельных символов</emphasis></p>
     <table>
      <tr>
       <th colspan="2" align="left">Unicode-коды</th>
       <th rowspan="2" align="left">Описание</th>
      </tr>
      <tr>
       <th align="left">Десятичный</th>
       <th align="left">Шестнадцатеричный</th>
       <th/>
      </tr>
      <tr>
       <td align="left"><code>#9</code></td>
       <td align="left"><code>#x9</code></td>
       <td align="left">Горизонтальная табуляция</td>
      </tr>
      <tr>
       <td align="left"><code>#10</code></td>
       <td align="left"><code>#xA</code></td>
       <td align="left">Перевод строки</td>
      </tr>
      <tr>
       <td align="left"><code>#13</code></td>
       <td align="left"><code>#xD</code></td>
       <td align="left">Возврат каретки</td>
      </tr>
      <tr>
       <td align="left"><code>#32</code></td>
       <td align="left"><code>#x20</code></td>
       <td align="left">Пробел</td>
      </tr>
     </table>
     <p>Отличие обработки пробельных символов заключается в том, что после разбора и создания логической модели для входящего документа и для самого преобразования, узлы, которые содержат только пробельные символы, будут удалены из дерева.</p>
     <subtitle>Пример</subtitle>
     <p>Рассмотрим шаблон преобразования, содержащий пробельные символы ("<code>&#9633;</code>" обозначает пробел, а "<code>¶</code>" — перевод строки).</p>
     <subtitle>Листинг 8.1. Шаблон преобразования с пробельными символами</subtitle>
     <p><code>&lt;xsl:template match="/"&gt;¶</code></p>
     <p><code>¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&lt;a&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;b/&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;/a&gt;¶</code></p>
     <p><code>¶</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Поскольку текстовые узлы этого шаблона содержат только пробельные символы, они будут удалены из дерева преобразования, и результат будет иметь вид:</p>
     <p><code>&lt;a&gt;&lt;b/&gt;&lt;/a&gt;</code></p>
     <p>Вообще, текстовый узел будет сохранен при выполнении хотя бы одного из следующих условий.</p>
     <p>&#9633; Он содержит хотя бы один непробельный символ.</p>
     <p>&#9633; Он принадлежит элементу, в котором сохранение пробельных символов задано средствами XML, а именно атрибутом <code>xml:space</code> со значением <code>preserve</code>.</p>
     <p>&#9633; Он принадлежит элементу, имя которого включено во множество имен элементов, для которых нужно сохранять пробельные символы.</p>
     <p>Во всех остальных случаях текстовый узел будет удален.</p>
     <p>Продемонстрируем все три случая сохранения текстового узла на примерах.</p>
     <p>Первый случай довольно прост. Шаблон</p>
     <p><code>&lt;xsl:template match="/"&gt;¶</code></p>
     <p><code>¶</code></p>
     <p><code>&#9633;&#9633;&lt;a/&gt;¶</code></p>
     <p><code>¶</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>создаст в выходящем документе фрагмент</p>
     <p><code>&lt;а/&gt;</code></p>
     <p>безо всяких пробельных символов, в то время как шаблон</p>
     <p><code>&lt;xsl:template match="/"&gt;¶</code></p>
     <p><code>¶</code></p>
     <p><code>&#9633;&#9633;|&lt;a/&gt;|¶</code></p>
     <p><code>¶</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>создаст фрагмент вида</p>
     <p><code>¶</code></p>
     <p><code>¶</code></p>
     <p><code>&#9633;&#9633;|&lt;a/&gt;|¶</code></p>
     <p><code>¶</code></p>
     <p>Различие двух этих шаблонов в том, что в первом текстовые узлы содержат текст "<code>¶ ¶ &#9633;&#9633;</code>" и "<code>¶ ¶ </code>" соответственно, а во втором — "<code>¶ ¶ &#9633;&#9633;|</code>" и "<code>| ¶ ¶</code>". Текстовые узлы второго шаблона не будут удалены, поскольку они содержат непробельные символы (символы "<code>|</code>").</p>
     <p>Второй случай сохранения текстовых узлов основан на использовании возможностей XML по управлению пробельными символами. Если в элементе задан атрибут <code>xml:space</code> со значением <code>"preserve"</code>, обрабатывающее программное обеспечение должно сохранять в нем и в его потомках пробельные символы. Единственным исключением из этого правила может быть опять же атрибут <code>xml:space</code>, заданный в элементе-потомке со значением <code>"default"</code>.</p>
     <subtitle>Пример</subtitle>
     <p>Шаблон</p>
     <p><code>&lt;xsl:template match="/"&gt;¶</code></p>
     <p><code>&#9633;&#9633;&lt;а&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;b&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;c&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;d/&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;/c&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;/b&gt;¶</code></p>
     <p><code>&#9633;&#9633;&lt;/a&gt;¶</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>создаст в выходящем документе фрагмент вида:</p>
     <p><code>&lt;a&gt;&lt;b&gt;&lt;c&gt;&lt;d/&gt;&lt;/c&gt;&lt;/b&gt;&lt;/a&gt;</code></p>
     <p>Если же шаблон будет определен в виде:</p>
     <p><code>&lt;xsl:template match="/"&gt;¶</code></p>
     <p><code>&#9633;&#9633;&lt;а xml:space="preserve"&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;b&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;c xml:space="default"&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;d/&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;/c&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;/b&gt;¶</code></p>
     <p><code>&#9633;&#9633;&lt;/a&gt;¶</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>то в выходящем фрагменте в элементах <code>а</code> и <code>b</code> пробельные символы будут сохранены, а в элементах <code>с</code> и <code>d</code> — удалены:</p>
     <p><code>&lt;а xml:space="preserve"&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;b&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;c xml: space="default"&gt;&lt;d/&gt;&lt;/c&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;/b&gt;¶</code></p>
     <p><code>&#9633;&#9633;&lt;/а&gt;</code></p>
     <p>В третьем случае сохранение пробельных символов текстового узла зависит от того, принадлежит ли имя родительского элемента особому множеству, называемому множеством имен элементов, для которых следует сохранять пробельные символы или, для краткости, сохраняющее множество.</p>
     <p>Для преобразований сохраняющее множество состоит из единственного элемента <code>xsl:text</code>, то есть единственный элемент в преобразовании, для которого пробельные текстовые узлы не будут удаляться, — это элемент <code>xsl:text</code>. Поэтому его часто используют для вывода в выходящем документе пробельных символов.</p>
     <p>Для входящих документов сохраняющее множество состоит из имен всех элементов. То есть по умолчанию преобразования сохраняют все пробельные текстовые узлы. Для изменения сохраняющего множества элементов входящего документа используются элементы <code>xsl:preserve-space</code> и <code>xsl:strip-space</code>.</p>
    </section>
    <section>
     <title>
      <p>Элементы <emphasis>xsl:preserve-space</emphasis> и <emphasis>xsl:strip-space</emphasis></p>
     </title>
     <p>Синтаксические конструкции этих элементов очень похожи:</p>
     <p><code>&lt;xsl:preserve-space</code></p>
     <p><code> <strong>elements</strong>="<emphasis>токены</emphasis>"/&gt;</code></p>
     <empty-line/>
     <p><code>&lt;xsl:strip-space</code></p>
     <p><code> <strong>elements</strong>="<emphasis>токены</emphasis>"/&gt;</code></p>
     <p>Элемент <code>xsl:preserve-space</code> добавляет, a <code>xsl:strip-space</code> удаляет имя элемента из сохраняющего множества входящего документа.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, нам нужно сохранять пробельные символы во всех элементах <code>d</code> и удалять их в элементах <code>с</code>. Тогда в преобразовании достаточно указать</p>
     <p><code>&lt;xsl:preserve-space elements="d"/&gt;</code></p>
     <p><code>&lt;xsl:strip-space elements="c"/&gt;</code></p>
     <p>Вообще, обязательные атрибуты elements элементов <code>xsl:strip-space</code> и <code>xsl:preserve-space</code> содержат не сами имена элементов, а так называемые проверки имен. Проверка имени имеет три варианта синтаксиса.</p>
     <p>&#9633; Синтаксис <code>"*"</code> используется для выбора произвольных имен. Ей будут соответствовать любые имена элементов.</p>
     <p>&#9633; Синтаксис <code>"<emphasis>имя</emphasis>"</code> используется для выбора элементов с заданным именем. К примеру, проверке имени <code>"d"</code> будут соответствовать все элементы с именем "<code>d</code>".</p>
     <p>&#9633; Синтаксис <code>"<emphasis>префикс</emphasis>:*"</code> используется для выбора всех элементов в данном пространстве имен. К примеру, если в документе определен префикс пространства имен <code>upr</code> в виде атрибута <code>xmlns:upr="http://www.upr.com"</code>, проверке имени <code>"upr:*"</code> будут соответствовать все элементы пространства имен, определяемого идентификатором <code>"http://www.upr.com"</code>.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что нам необходимо сохранить пробельные символы в элементе с именем <code>с</code> и удалить их в элементе <code>e</code> и элементах, принадлежащих пространству имен, определяемому идентификатором "<code>urn:d</code>".</p>
     <subtitle>Листинг 8.2. Входящий документ</subtitle>
     <p><code>&lt;а xmlns:d="urn:d"&gt;¶</code></p>
     <p><code>&#9633;&#9633;&lt;d:b&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;c&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;/e&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;/c&gt;¶</code></p>
     <p><code>&#9633;&#9633;&lt;/d:b&gt;¶</code></p>
     <p><code>&lt;/a&gt;</code></p>
     <subtitle>Листинг 8.3. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:preserve-space elements="c"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:strip-space elements="e t:*"</code></p>
     <p><code>  xmlns:t="urn:d"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="/"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 8.4. Выходящий документ</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;a xmlns:d="urn:d"&gt;¶</code></p>
     <p><code>&#9633;&#9633;&lt;d:b&gt;&lt;c&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&#9633;&#9633;&lt;e/&gt;¶</code></p>
     <p><code>&#9633;&#9633;&#9633;&#9633;&lt;/c&gt;&lt;/d:b&gt;¶</code></p>
     <p><code>&lt;/a&gt;</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Сообщения процессора</p>
    </title>
    <section>
     <p>По большому счету, мы не можем контролировать процесс преобразования. Процессор может сам выбирать, как и в какой последовательности он будет выполнять те или иные шаблоны — таковы особенности декларативного программирования. Вместе с тем мы все-таки можем получить кое-какую информацию о ходе преобразования, используя механизм, называемый в XSLT сообщениями.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:message</emphasis></p>
     </title>
     <p>Синтаксис этого элемента дан ниже:</p>
     <p><code>&lt;xsl:message</code></p>
     <p><code> terminate="yes" | "no"&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:message&gt;</code></p>
     <p>Элемент <code>xsl:message</code> указывает процессору на то, что он должен вывести сообщение, которое является результатом обработки шаблона, содержащегося в этом элементе. Механизм вывода сообщения зависит от реализации того или иного процессора и может быть различным — от вывода текста сообщения на экран до вызова внешнего модуля для обработки сообщения.</p>
     <subtitle>Пример</subtitle>
     <p>Иногда в процессе отладки преобразования бывает полезно выводить сообщения о том, какой элемент обрабатывается в данный момент.</p>
     <subtitle>Листинг 8.5. Входящий документ</subtitle>
     <p><code>&lt;a&gt;&lt;b&gt;&lt;c&gt;&lt;d/&gt;&lt;/c&gt;&lt;/b&gt;&lt;/a&gt;</code></p>
     <subtitle>Листинг 8.6. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="*"&gt;</code></p>
     <p><code>  &lt;element name="{name()}"&gt;</code></p>
     <p><code>   &lt;xsl:message&gt;</code></p>
     <p><code>    &lt;xsl:text&gt;Processing element &lt;/xsl:text&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="name()"/&gt;</code></p>
     <p><code>    &lt;xsl:if test="parent::*"&gt;</code></p>
     <p><code>     &lt;xsl:text&gt; which has a parent element &lt;/xsl:text&gt;</code></p>
     <p><code>     &lt;xsl:value-of select="name(..)"/&gt;</code></p>
     <p><code>    &lt;/xsl:if&gt;</code></p>
     <p><code>    &lt;xsl:text&gt;.&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;/xsl:message&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/element&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 8.7. Выходящий документ</subtitle>
     <p><code>&lt;element name="a"&gt;</code></p>
     <p><code> &lt;element name="b"&gt;</code></p>
     <p><code>  &lt;element name="c"&gt;</code></p>
     <p><code>   &lt;element name="d"/&gt;</code></p>
     <p><code>  &lt;/element&gt;</code></p>
     <p><code> &lt;/element&gt;</code></p>
     <p><code>&lt;/element&gt;</code></p>
     <subtitle>Листинг 8.8. Сообщения процессора</subtitle>
     <p><code>Processing element a.</code></p>
     <p><code>Processing element b which has a parent element a.</code></p>
     <p><code>Processing element с which has a parent element b.</code></p>
     <p><code>Processing element d which has a parent element c.</code></p>
     <p>Атрибут <code>terminate</code> указывает на то, должен ли процессор прекратить дальнейшую обработку документа или нет. Значением этого атрибута по умолчанию является <code>"no"</code>, что означает, что процессор должен просто вывести сообщения и продолжать дальнейшее выполнение шаблона. Если же в <code>xsl:message</code> указано <code>terminate="yes"</code>, то процессор, выведя сообщение, прервет обработку. Этот прием может использоваться, например, для того, чтобы проверять входящие документы на соответствие определенной схеме.</p>
     <subtitle>Пример</subtitle>
     <p>При помощи <code>xsl:message</code> мы можем запретить обработку документов, которые не имеют в корне элемент с именем <code>"html"</code> в любом регистре символов.</p>
     <subtitle>Листинг 8.9. Шаблон преобразования</subtitle>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;xsl:if test="translate(name(*),'html','HTML')!='HTML'"&gt;</code></p>
     <p><code>  &lt;xsl:message terminate="yes"&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;Document has no root HTML element.&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code> &lt;/xsl:if&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Если мы будем обрабатывать документ вида</p>
     <p><code>&lt;hTmL&gt;</code></p>
     <p><code> &lt;body/&gt;</code></p>
     <p><code>&lt;/hTmL&gt;</code></p>
     <p>обработка не будет прервана, в то время как преобразование документа</p>
     <p><code>&lt;ht-ml&gt;</code></p>
     <p><code> &lt;body/&gt;</code></p>
     <p><code>&lt;/ht-ml&gt;</code></p>
     <p>будет прервано сообщением:</p>
     <p><code>Document has no root HTML element:</code></p>
     <p><code>Processing terminated using xsl:message</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Сортировка</p>
    </title>
    <section>
     <p>При преобразовании документа элементами <code>xsl:for-each</code> и <code>xsl:apply-templates</code>, выбранные узлы по умолчанию обрабатываются в порядке просмотра документа, который зависит от выражения, использованного в атрибуте <code>select</code> этих элементов. XSLT позволяет изменять этот порядок посредством использования механизма сортировки.</p>
     <p>Элементы <code>xsl:for-each</code> и <code>xsl:apply-templates</code> могут содержать один или несколько элементов <code>xsl:sort</code>, которые позволяют предварительно сортировать обрабатываемое множество узлов.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:sort</emphasis></p>
     </title>
     <p>Синтаксис этого элемента определяется в XSLT как:</p>
     <p><code>&lt;xsl:sort</code></p>
     <p><code> <strong>select</strong> = "<emphasis>выражение</emphasis>"</code></p>
     <p><code> lang = "<emphasis>язык</emphasis>"</code></p>
     <p><code> data-type = "text" | "number" | <emphasis>"имя"</emphasis></code></p>
     <p><code> order = "ascending" | "descending"</code></p>
     <p><code> case-order = "upper-first" | "lower-first" /&gt;</code></p>
     <p>В случае если <code>xsl:for-each</code> и <code>xsl:apply-templates</code> содержат элементы <code>xsl:sort</code>, обработка множества узлов должна производиться не в порядке просмотра документа, а в порядке, который определяется ключами, вычисленными при помощи <code>xsl:sort</code>. Первый элемент <code>xsl:sort</code>, присутствующий в родительском элементе, определяет первичный ключ сортировки, второй элемент — вторичный ключ, и так далее.</p>
     <p>Элемент <code>xsl:sort</code> обладает атрибутом <code>select</code>, значением которого является выражение, называемое также ключевым выражением. Это выражение вычисляется для каждого узла обрабатываемого множества, преобразуется в строку и затем используется как значение ключа при сортировке. По умолчанию значением этого атрибута является <code>"."</code>, что означает, что в качестве значения ключа для каждого узла используется его строковое значение.</p>
     <p>После этих вычислений узлы обрабатываемого множества сортируются по полученным строковым значениям своих ключей и обрабатываются в новом порядке. Если ключи некоторых узлов совпадают, они могут быть в дальнейшем отсортированы вторичными и так далее ключами.</p>
     <p>Элемент <code>xsl:sort</code> может иметь следующие необязательные атрибуты, которые указывают некоторые параметры сортировки.</p>
     <p>&#9633; Атрибут <code>order</code> определяет порядок, в котором узлы должны сортироваться по своим ключам. Этот атрибут может принимать только два значения — <code>"ascending"</code>, указывающее на восходящий порядок сортировки, и <code>"descending"</code>, указывающее на нисходящий порядок. Значением по умолчанию является <code>"ascending"</code>, то есть восходящий порядок.</p>
     <p>&#9633; Атрибут <code>lang</code> определяет язык ключей сортировки. Дело в том, что в разных языках символы алфавита могут иметь различный порядок, что, соответственно, должно учитываться при сортировке. Атрибут <code>lang</code> в XSLT может иметь те же самые значения, что и атрибут <code>xml:lang</code> (например: <code>"en"</code>, <code>"en-us"</code>, <code>"ru"</code> и т.д.). Если значение этого атрибута не определено, процессор может либо определять язык исходя из параметров системы, либо сортировать строки исходя из порядка кодов символов Unicode.</p>
     <p>&#9633; Атрибут <code>data-type</code> определяет тип данных, который несут строковые значения ключей. Техническая рекомендация XSLT разрешает этому атрибуту иметь следующие значения:</p>
     <p> • <code>"text"</code> — ключи должны быть отсортированы в лексикографическом порядке исходя из языка, определенного атрибутом <code>lang</code> или параметрами системы;</p>
     <p> • <code>"number"</code> — ключи должны сравниваться в численном виде. Если строковое значение ключа не является числом, оно будет преобразовано к не-числу (<code>NaN</code>), и, поскольку нечисловые значения неупорядочены, соответствующий узел может появиться в отсортированном множестве где угодно;</p>
     <p> • <code>"<emphasis>имя</emphasis>"</code> — в целях расширяемости XSLT также позволяет указывать в качестве типа данных произвольное имя. В этом случае реализация сортировки полностью зависит от процессора;</p>
     <p> • значением атрибута <code>data-type</code> по умолчанию является <code>"text"</code>.</p>
     <p>&#9633; Атрибут <code>case-order</code> указывает на порядок сортировки символов разных регистров. Значениями этого атрибута могут быть <code>"upper-first"</code>, что означает, что заглавные символы должны идти первыми, или <code>"lower-first"</code>, что означает, что первыми должны быть строчные символы. К примеру, строки <code>"ночь"</code>, <code>"Улица"</code>, <code>"фонарь"</code>, <code>"Аптека"</code>, <code>"НОЧЬ"</code>, <code>"Фонарь"</code> при использовании <code>case-order="upper-first"</code> будут иметь порядок <code>"Аптека"</code>, <code>"НОЧЬ"</code>, <code>"ночь"</code>, <code>"Фонарь"</code>, <code>"фонарь"</code>, <code>"улица"</code>. При использовании <code>case-order="lower-first"</code> те же строки будут идти в порядке <code>"Аптека"</code>, <code>"ночь"</code>, <code>"НОЧЬ"</code>, <code>"фонарь"</code>, <code>"Фонарь"</code>, <code>"улица"</code>. Значение <code>case-order</code> по умолчанию зависит от процессора и языка сортировки. В большинстве случаев заглавные буквы идут первыми.</p>
     <p>Как можно видеть, элемент <code>xsl:sort</code> определяет сортировку достаточно гибко, но вместе с тем не следует забывать, что эти возможности могут быть реализованы в процессорах далеко не полностью. Поэтому одна и та же сортировка может быть выполнена в разных процессорах по-разному.</p>
     <p>Приведем простой пример сортировки имен и фамилий.</p>
     <p>Рассмотрим пример.</p>
     <subtitle>Листинг 8.10. Входящий документ</subtitle>
     <p><code>&lt;list&gt;</code></p>
     <p><code> &lt;person&gt;</code></p>
     <p><code>  &lt;name&gt;William&lt;/name&gt;</code></p>
     <p><code>  &lt;surname&gt;Gibson&lt;/surname&gt;</code></p>
     <p><code> &lt;/person&gt;</code></p>
     <p><code> &lt;person&gt;</code></p>
     <p><code>  &lt;name&gt;William&lt;/name&gt;</code></p>
     <p><code>  &lt;surname&gt;Blake&lt;/surname&gt;</code></p>
     <p><code> &lt;/person&gt;</code></p>
     <p><code> &lt;person&gt;</code></p>
     <p><code>  &lt;name&gt;John&lt;/name&gt;</code></p>
     <p><code>  &lt;surname&gt;Fowles&lt;/surname&gt;</code></p>
     <p><code> &lt;/person&gt;</code></p>
     <p><code>&lt;/list&gt;</code></p>
     <p>Отсортируем этот список сначала по именам в убывающем, а затем по фамилиям в возрастающем порядке.</p>
     <p><code>&lt;xsl:template match="list"&gt;</code></p>
     <p><code> &lt;xsl:copy&gt;</code></p>
     <p><code>  &lt;xsl:for-each select="person"&gt;</code></p>
     <p><code>   &lt;xsl:sort select="name" order="descending"/&gt;</code></p>
     <p><code>   &lt;xsl:sort select="surname"/&gt;</code></p>
     <p><code>   &lt;xsl:copy-of select="."/&gt;</code></p>
     <p><code>  &lt;/xsl:for-each&gt;</code></p>
     <p><code> &lt;/xsl:copy&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <subtitle>Листинг 8.12. Выходящий документ</subtitle>
     <p><code>&lt;list&gt;</code></p>
     <p><code> &lt;person&gt;</code></p>
     <p><code>  &lt;name&gt;William&lt;/name&gt;</code></p>
     <p><code>  &lt;surname&gt;Blake&lt;/surname&gt;</code></p>
     <p><code> &lt;/person&gt;</code></p>
     <p><code> &lt;person&gt;</code></p>
     <p><code>  &lt;name&gt;William&lt;/name&gt;</code></p>
     <p><code>  &lt;surname&gt;Gibson&lt;/surname&gt;</code></p>
     <p><code> &lt;/person&gt;</code></p>
     <p><code> &lt;person&gt;</code></p>
     <p><code>  &lt;name&gt;John&lt;/name&gt;</code></p>
     <p><code>  &lt;surname&gt;Fowles&lt;/surname&gt;</code></p>
     <p><code> &lt;/person&gt;</code></p>
     <p><code>&lt;/list&gt;</code></p>
     <p>К сожалению, сортировкой нельзя управлять динамически. Все атрибуты элемента <code>xsl:sort</code> должны обладать фиксированными значениями.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Псевдонимы пространств имен</p>
    </title>
    <section>
     <p>Любопытным фактом является то, что XML-документ, являющийся результатом выполнения XSLT-преобразования, может и сам быть XSLT- преобразованием. Иными словами, преобразования могут генерироваться другими преобразованиями. В некоторых случаях такая возможность будет очень полезна, например, входящий XML-документ может описывать преобразование, которое нужно сгенерировать.</p>
     <subtitle>Листинг 8.13. XML-документ, описывающий требуемое преобразование</subtitle>
     <p><code>&lt;transform&gt;</code></p>
     <p><code> &lt;remove select="a"/&gt;</code></p>
     <p><code> &lt;replace select="b" with="B"/&gt;</code></p>
     <p><code> &lt;replace select="c" with="C"/&gt;</code></p>
     <p><code>&lt;/transform&gt;</code></p>
     <p>Приведенный выше документ описывает преобразование, которое должно удалять из входящего документа элементы <code>а</code>, а элементы <code>b</code> и <code>c </code>заменять элементами <code>B</code> и <code>C</code> соответственно. Такое преобразование может выглядеть следующим образом.</p>
     <subtitle>Листинг 8.14. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="a"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="b"&gt;</code></p>
     <p><code>  &lt;xsl:element name="B"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/xsl:element&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="c"&gt;</code></p>
     <p><code>  &lt;xsl:element name="C"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/xsl:element&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="@*|node()"&gt;</code></p>
     <p><code>  &lt;xsl:copy&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code>  &lt;/xsl:copy&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Преобразование, генерирующее такой код, не представляет особой сложности. Например, шаблон для обработки элемента replace может иметь следующий вид:</p>
     <p><code>&lt;xsl:template match="replace"&gt;</code></p>
     <p><code> &lt;xsl:element name="xsl:template"&gt;</code></p>
     <p><code>  &lt;xsl:attribute name="match"&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="@select"/&gt;</code></p>
     <p><code>  &lt;/xsl:attribute&gt;</code></p>
     <p><code>  &lt;xsl:element name="xsl:element"&gt;</code></p>
     <p><code>   &lt;xsl:attribute name="name"&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="@with"/&gt;</code></p>
     <p><code>   &lt;/xsl:attribute&gt;</code></p>
     <p><code>   &lt;xsl:element name="xsl:apply-templates"/&gt;</code></p>
     <p><code>  &lt;/xsl:element&gt; </code></p>
     <p><code> &lt;/xsl:element&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Шаблон этот выглядит очень громоздко, потому что мы не могли просто включить в него создаваемое правило: поскольку мы создаем элементы в пространстве имен XSLT, находясь в шаблоне, они воспринимались бы не как генерируемые, а как принадлежащие генерирующему преобразованию. Очевидно, что шаблон вида</p>
     <p><code>&lt;xsl:template match="replace"&gt;</code></p>
     <p><code> &lt;xsl:template match="{@select}"&gt;</code></p>
     <p><code>  &lt;xsl:element name="{@with}"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/xsl:element&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>был бы некорректен. По этой причине нам пришлось генерировать все инструкции при помощи <code>xsl:element</code> и <code>xsl:attribute</code>, что сделало шаблон громоздким и малопонятным.</p>
     <p>Если внимательно рассмотреть проблему, то окажется, что она состоит в том, что мы хотим в преобразовании использовать элементы одного пространства имен так, как если бы они относились к другому пространству.</p>
     <p>К счастью, XSLT предоставляет легкий и удобный способ для решения такого рода задачи: пространству имен можно назначить псевдоним при помощи элемента <code>xsl:namespace-alias</code>.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:namespace-alias</emphasis></p>
     </title>
     <p>Синтаксическая конструкция этого элемента выглядит следующим образом:</p>
     <p><code>&lt;xsl:namespace-alias</code></p>
     <p><code> <strong>stylesheet-prefiх</strong>="<emphasis>префикс</emphasis>" | "#default"</code></p>
     <p><code> <strong>result-prefix</strong>="<emphasis>префикс</emphasis>" | "#default"/&gt;</code></p>
     <p>Элемент <code>xsl:namespace-alias</code> назначает пространству имен выходящего документа пространство имен, которое будет подменять его в преобразовании, иначе говоря — псевдоним.</p>
     <p>Обязательный атрибут <code>result-prefix</code> указывает, какому пространству имен назначается псевдоним. Обязательный атрибут <code>stylesheet-prefix</code> указывает, какое пространство имен будет использоваться в качестве его псевдонима в преобразовании. Оба атрибута содержат префиксы пространств имен, которые, естественно, должны быть ранее объявлены в преобразовании.</p>
     <subtitle>Пример</subtitle>
     <p>Возвращаясь к генерации преобразования, мы можем изменить пространство имен генерируемых элементов так, чтобы они не воспринимались процессором как элементы XSLT. Для того чтобы в выходящем документе эти элементы все же принадлежали пространству имен XSLT, измененное пространство имен в преобразовании должно указываться как псевдоним этого пространства.</p>
     <subtitle>Листинг 8.15. Преобразование, использующее псевдонимы пространств имен</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:axsl="http://www.w3.org/1999/XSL/Transform/Alias"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:namespace-alias</code></p>
     <p><code>  stylesheet-prefix="axsl"</code></p>
     <p><code>  result-prefix="xsl"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="replace"&gt;</code></p>
     <p><code>  &lt;axsl:template match="{@select}"&gt;</code></p>
     <p><code>   &lt;axsl:element name="{@with}"&gt;</code></p>
     <p><code>    &lt;axsl:apply-templates/&gt;</code></p>
     <p><code>   &lt;/axsl:element&gt;</code></p>
     <p><code>  &lt;/axsl:template&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="remove"&gt;</code></p>
     <p><code>  &lt;axsl:template match="{@select}"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="transform"&gt;</code></p>
     <p><code>  &lt;axsl:stylesheet version="1.0"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>   &lt;axsl:template match="@*|node()"&gt;</code></p>
     <p><code>    &lt;axsl:copy&gt;</code></p>
     <p><code>     &lt;axsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code>    &lt;/axsl:copy&gt;</code></p>
     <p><code>   &lt;/axsl:template&gt;</code></p>
     <p><code>  &lt;/axsl:stylesheet&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>В этом преобразовании элемент <code>xsl:namespace-alias</code> указывает на то, что все элементы, принадлежащие в преобразовании пространству имен с URI</p>
     <p><code>http://www.w3.org/1999/XSL/Transform/Alias</code></p>
     <p>в выходящем документе должны принадлежать пространству имен с URI</p>
     <p><code>http://www.w3.org/1999/XSL/Transform</code></p>
     <p>то есть пространству имен XSLT.</p>
     <p>Результатом применения этого преобразования к документу из листинга 8.13 будет следующий документ.</p>
     <subtitle>Листинг 8.16. Выходящее преобразование</subtitle>
     <p><code>&lt;axsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:axsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;axsl:template match="a"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;axsl:template match="b"&gt;</code></p>
     <p><code>  &lt;axsl:element name="B"&gt;</code></p>
     <p><code>   &lt;axsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/axsl:element&gt;</code></p>
     <p><code> &lt;/axsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;axsl:template match="c"&gt;</code></p>
     <p><code>  &lt;axsl:element name="C"&gt;</code></p>
     <p><code>   &lt;axsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/axsl:element&gt;</code></p>
     <p><code> &lt;/axsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;axsl:template match="@*|node()"&gt;</code></p>
     <p><code>  &lt;axsl:copy&gt;</code></p>
     <p><code>   &lt;axsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code>  &lt;/axsl:copy&gt;</code></p>
     <p><code> &lt;/axsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/axsl:stylesheet&gt;</code></p>
     <p>В этом сгенерированном преобразовании элементы имеют префикс <code>axsl</code>, но при этом принадлежат пространству имен XSLT.</p>
     <p>Атрибуты <code>stylesheet-prefix</code> и <code>result-prefix</code> элемента <code>xsl:namespace-alias</code> могут иметь значения <code>"#default"</code>. Определение вида</p>
     <p><code>&lt;xsl:namespace-alias</code></p>
     <p><code> stylesheet-prefix="a"</code></p>
     <p><code> result-prefix="#default"/&gt;</code></p>
     <p>означает, что элементы, принадлежащие в преобразовании пространству имен <code>а</code>, в выходящем документе должны принадлежать пространству имен по умолчанию. Определение вида</p>
     <p><code>&lt;xsl:namespace-alias</code></p>
     <p><code> stylesheet-prefix="#default"</code></p>
     <p><code> result-prefix="a"/&gt;</code></p>
     <p>означает, что элементы, принадлежащие в преобразовании пространству имен по умолчанию, в выходящем документе должны принадлежать пространству имен <code>а</code>.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 8.17. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:a="urn:a"</code></p>
     <p><code> xmlns="urn:b"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:namespace-alias</code></p>
     <p><code>  stylesheet-prefix="#default"</code></p>
     <p><code>  result-prefix="a"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:namespace-alias</code></p>
     <p><code>  stylesheet-prefix="a"</code></p>
     <p><code>  result-prefix="#default"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="root"&gt;</code></p>
     <p><code>  &lt;result&gt;</code></p>
     <p><code>   &lt;a:element/&gt;</code></p>
     <p><code>  &lt;/result&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 8.18. Выходящий документ</subtitle>
     <p><code>&lt;result xmlns="urn:a" xmlns:a="urn:b"&gt;</code></p>
     <p><code> &lt;a:element/&gt;</code></p>
     <p><code>&lt;/result&gt;</code></p>
     <p>Результатом этого преобразования является то, что пространство имен с URI <code>"urn:а"</code> стало пространством имен по умолчанию, а пространство имен с URI <code>"urn:b"</code> изменило префикс на <code>а</code>.</p>
     <p>В преобразованиях можно объявлять несколько псевдонимов пространств имен при условии, что одно и то же пространство имен преобразования не должно быть объявлено элементами <code>xsl:namespace-alias</code> с одинаковым порядком импорта псевдонимом для различных пространств имен выходящего документа.</p>
     <subtitle>Пример</subtitle>
     <p>Если преобразование <code>a.xsl</code> содержит определение</p>
     <p><code>&lt;xsl:namespace-alias</code></p>
     <p><code> stylesheet-prefix="x"</code></p>
     <p><code> result-prefix="a"/&gt;</code></p>
     <p>а преобразование <code>b.xsl</code> — определение</p>
     <p><code>&lt;xsl:namespace-alias</code></p>
     <p><code> stylesheet-prefix="x"</code></p>
     <p><code> result-prefix="b"/&gt;</code></p>
     <p>где в обоих преобразованиях префикс <code>x</code> представляет одно пространство имен, а пространства имен <code>a</code> и <code>b</code> — разные, то преобразование <code>a.xsl</code> не сможет включать преобразование <code>b.xsl</code> и наоборот, потому что они будут иметь одинаковый порядок импорта и содержать элементы <code>xsl:namespace-alias</code>, назначающие разным пространствам имен одинаковые псевдонимы. В одном преобразовании такие псевдонимы также не имеют права встречаться. Если же подобное все же случилось, процессор может сигнализировать ошибку или использовать определение, которое было дано в преобразовании последним.</p>
     <p>Совсем иначе обстоит дело с импортированием. При импортировании определения старших в порядке импорта преобразований могут переопределять определения младших преобразований. Таким образом, если преобразование <code>a.xsl</code> будет импортировать преобразование <code>b.xsl</code>, пространство имен <code>x</code> будет назначено псевдонимом пространству имен <code>а</code> и наоборот.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Ключи</p>
    </title>
    <section>
     <p>Прежде чем мы приступим к разбору ключей, которые являются одной из самых мощных концепций языка XSLT, попробуем решить одну несложную задачку.</p>
     <subtitle>Листинг 8.19. Входящий документ</subtitle>
     <p><code>&lt;items&gt;</code></p>
     <p><code> &lt;item source="a" name="A"/&gt;</code></p>
     <p><code> &lt;item source="b" name="B"/&gt;</code></p>
     <p><code> &lt;item source="a" name="C"/&gt;</code></p>
     <p><code> &lt;item source="c" name="D"/&gt;</code></p>
     <p><code> &lt;item source="b" name="E"/&gt;</code></p>
     <p><code> &lt;item source="b" name="F"/&gt;</code></p>
     <p><code> &lt;item source="c" name="G"/&gt;</code></p>
     <p><code> &lt;item source="a" name="H"/&gt;</code></p>
     <p><code>&lt;/items&gt;</code></p>
     <p>Пусть входящий документ представляет собой список объектов (элементов <code>item</code>), каждый из которых имеет имя (атрибут <code>name</code>) и источник (атрибут <code>source</code>). Требуется сгруппировать объекты по своим источникам и получить документ приблизительно следующего вида.</p>
     <subtitle>Листинг 8.20. Требуемый результат</subtitle>
     <p><code>&lt;sources&gt;</code></p>
     <p><code> &lt;source name="a"&gt;</code></p>
     <p><code>  &lt;item source="a" name="A"/&gt;</code></p>
     <p><code>  &lt;item source="a" name="C"/&gt;</code></p>
     <p><code>  &lt;item source="a" name="H"/&gt;</code></p>
     <p><code> &lt;/source&gt;</code></p>
     <p><code> &lt;source name="b"&gt;</code></p>
     <p><code>  &lt;item source="b" name="B"/&gt;</code></p>
     <p><code>  &lt;item source="b" name="E"/&gt;</code></p>
     <p><code>  &lt;item source="b" name="F"/&gt;</code></p>
     <p><code> &lt;/source&gt;</code></p>
     <p><code> &lt;source name="c"&gt;</code></p>
     <p><code>  &lt;item source="c" name="D"/&gt;</code></p>
     <p><code>  &lt;item source="c" name="G"/&gt;</code></p>
     <p><code> &lt;/source&gt;</code></p>
     <p><code>&lt;/sources&gt;</code></p>
     <p>Первым шагом на пути решения этой задачи является формулировка в терминах XSLT предложения "сгруппировать объекты по своим источникам". Источник каждого объекта определяется его атрибутом <code>source</code>, значит множество объектов, принадлежащих одному источнику <code>"а"</code>, будет определяться путем выборки</p>
     <p><code>/items/item[@source='a']</code></p>
     <p>Тогда для каждого элемента <code>item</code> в его группу войдут элементы, которые будут выбраны выражением</p>
     <p><code>/items/item[@source=current()/@source]</code></p>
     <p>Попробуем использовать этот факт в следующем шаблоне:</p>
     <p><code>&lt;xsl:template match="item"&gt;</code></p>
     <p><code> &lt;source name="{@source}"&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="/items/item[@source=current()/@source]"/&gt;</code></p>
     <p><code> &lt;/source&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Как и ожидалось, при применении этого правила к элементам <code>item</code> для каждого из них будет создана группа, принадлежащая тому же источнику, — уже хороший результат, но в условии требуется создать по группе не для каждого объекта, а для каждого источника. Чтобы достичь этого, можно создавать группу только для первого объекта, принадлежащего ей. Провести такую проверку опять же несложно: объект будет первым в группе тогда и только тогда, когда ему не предшествуют другие, элементы <code>item</code>, принадлежащие тому же источнику. Иначе говоря, создаем группы только для тех элементов, для которых выражение</p>
     <p><code>preceding-sibling::item[@source-current()/@source]</code></p>
     <p>будет возвращать пустое множество.</p>
     <p>С небольшими добавлениями искомое преобразование целиком будет иметь вид.</p>
     <subtitle>Листинг 8.21. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="items"&gt;</code></p>
     <p><code>  &lt;sources&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/sources&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="item"&gt;</code></p>
     <p><code>  &lt;xsl:choose&gt;</code></p>
     <p><code>   &lt;xsl:when</code></p>
     <p><code>    test="preceding-sibling::item[@source=current()/@source]"/&gt;</code></p>
     <p><code>   &lt;xsl:otherwise&gt;</code></p>
     <p><code>    &lt;source name="{@source}"&gt;</code></p>
     <p><code>     &lt;xsl:copy-of select="self::node()</code></p>
     <p><code>      |following-sibling::item[@source=current()/@source]"/&gt;</code></p>
     <p><code>    &lt;/source&gt;</code></p>
     <p><code>   &lt;/xsl:otherwise&gt;</code></p>
     <p><code>  &lt;/xsl:choose&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Бесспорно, решение было несложным, но довольно громоздким. Самым же узким местом в этом преобразовании является обращение к элементам <code>item</code> источника текущего элемента посредством сравнения атрибутов <code>source</code>.</p>
     <p>Проблема совершенно стандартна для многих преобразований: нужно выбирать узлы по определенным признакам, причем делать это нужно как можно более эффективно. Хорошо, что в нашем документе было всего восемь элементов <code>item</code>, но представьте себе ситуацию, когда элементов <emphasis>действительно</emphasis> много.</p>
     <p>Проблема, которую мы подняли, достаточно серьезна. Она состоит в оптимизации поиска узлов с определенными свойствами в древовидно организованной структуре.</p>
     <p>Попробуем разобраться в смысле фразы "узел обладает определенными свойствами". Очевидно, это означает, что для этого узла выполняется некое логическое условие, иначе говоря, некий предикат обращается в "истину".</p>
     <p>Однако какого именно типа условия мы чаще всего проверяем? Анализируя различные классы задач, можно придти к выводу, что в большинстве случаев предикаты являются равенствами — выражениями, которые обращаются в "истину" тогда и только тогда, когда некоторый параметр узла, не зависящий от текущего контекста, равен определенному значению. В нашем примере смысл предиката на самом деле состоит не в том, чтобы проверить на истинность выражение <code>@source=current()/@source</code>, а в том, чтобы проверить на равенство <code>@source</code> и <code>current()/@source</code>.</p>
     <p>Если переформулировать это для общего случая, то нам нужно выбрать не те узлы, для которых истинно выражение <code>A=B</code>, скорее нужно выбрать те, для которых значение <code>A</code> равно значению <code>B</code>. Иначе говоря, узел будет идентифицироваться значением в своего свойства <code>A</code>. И если мы заранее вычислим значения свойств <code>A</code>, проблема поиска узлов в дереве сведется к классической проблеме поиска элементов множества (в нашем случае — узлов дерева) по определенным значениям ключей (в нашем случае — значениями свойств <code>A</code>).</p>
     <p>Чтобы пояснить это, вернемся к нашему примеру: мы ищем элементы <code>item</code> со значением атрибута <code>source</code>, равным заданному. Свойством, идентифицирующим эти элементы, в данном случае будут значения их атрибутов <code>source</code>, которые мы можем заранее вычислить и включить в табл. 8.2.</p>
     <empty-line/>
     <p><emphasis><strong>Таблица 8.2</strong>. Значения атрибута </emphasis><code><emphasis>source</emphasis></code><emphasis> элементов </emphasis><code><emphasis>item</emphasis></code></p>
     <table>
      <tr>
       <th align="left">Идентификатор (значение атрибута <code>source</code>)</th>
       <th align="left">Элемент <code>item</code></th>
      </tr>
      <tr>
       <td align="left"><code>a</code></td>
       <td align="left"><code>&lt;item source="a" name="A"/&gt;</code></td>
      </tr>
      <tr>
       <td align="left"><code>a</code></td>
       <td align="left"><code>&lt;item source="a" name="C"/&gt;</code></td>
      </tr>
      <tr>
       <td align="left"><code>a</code></td>
       <td align="left"><code>&lt;item source="a" name="H"/&gt;</code></td>
      </tr>
      <tr>
       <td align="left"><code>b</code></td>
       <td align="left"><code>&lt;item source="b" name="B"/&gt;</code></td>
      </tr>
      <tr>
       <td align="left"><code>b</code></td>
       <td align="left"><code>&lt;item source="b" name="E"/&gt;</code></td>
      </tr>
      <tr>
       <td align="left"><code>b</code></td>
       <td align="left"><code>&lt;item source="b" name="F"/&gt;</code></td>
      </tr>
      <tr>
       <td align="left"><code>с</code></td>
       <td align="left"><code>&lt;item source="c" name="D"/&gt;</code></td>
      </tr>
      <tr>
       <td align="left"><code>с</code></td>
       <td align="left"><code>&lt;item source="c" name="G"/&gt;</code></td>
      </tr>
     </table>
     <p>Таким образом, значение <code>"с"</code> идентифицирует объекты с именами <code>D</code> и <code>G</code>, а значение <code>"а"</code> — объекты с именами <code>A</code>, <code>C</code> и <code>H</code>, причем находить соответствующие элементы в таблице по их ключевому свойству не составляет никакого труда.</p>
     <p>Несмотря на то, что произведенные нами манипуляции чрезвычайно просты (и настолько же эффективны), процессор вряд ли в общем случае сможет сделать что-либо подобное сам, и потому очень важной является возможность явным образом выделять в XSLT-преобразованиях ключевые свойства множеств узлов.</p>
     <p>В этом разделе мы будем рассматривать две конструкции, позволяющие манипулировать множествами узлов посредством ключей — это элемент <code>xsl:key</code>, который определяет в преобразовании именованный ключ, и функция <code>key</code>, которая возвращает множество узлов, идентифицирующихся заданными значениями ключей.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:key</emphasis></p>
     </title>
     <p>Синтаксис элемента несложен:</p>
     <p><code>&lt;xsl:key</code></p>
     <p><code> <strong>name</strong>="<emphasis>имя</emphasis>"</code></p>
     <p><code> <strong>match</strong>="<emphasis>паттерн</emphasis>"</code></p>
     <p><code> <strong>use</strong>="<emphasis>выражение</emphasis>"/&gt;</code></p>
     <p>Элемент верхнего уровня <code>xsl:key</code> определяет в преобразовании ключ именем, заданным в значении атрибута <code>name</code>, значением которого для каждого узла документа, соответствующего паттерну <code>match</code>, будет результат вычисления выражения, заданного в атрибуте <code>use</code>. Ни атрибут <code>use</code>, ни атрибут <code>match</code> не могут содержать переменных.</p>
     <subtitle>Пример</subtitle>
     <p>В нашем примере элементы <code>item</code> идентифицируются значениями своих атрибутов <code>source</code>. Для их идентификации мы можем определить ключ с именем <code>src</code> следующим образом:</p>
     <p><code>&lt;xsl:key name="src" match="item" use="@source"/&gt;</code></p>
     <p>Следуя строгому определению, данному в спецификации языка, ключом называется тройка вида <code>(<emphasis>node</emphasis>, <emphasis>name</emphasis>, <emphasis>value</emphasis>)</code>, где <code><emphasis>node</emphasis></code> — узел, <code><emphasis>name</emphasis></code> — имя и <code><emphasis>value</emphasis></code> — строковое значение ключа. Тогда элементы <code>xsl:key</code>, включенные в преобразование, определяют множество всевозможных ключей обрабатываемого документа. Если этому множеству принадлежит ключ, состоящий из узла <code>x</code>, имени <code>у</code> и значения <code>z</code>, говорят, что узел <code>x</code> имеет ключ с именем <code>у</code> и значением <code>z</code> или что ключ <code>у</code> узла <code>x</code> равен <code>z</code>.</p>
     <subtitle>Пример</subtitle>
     <p>Ключ <code>src</code> из предыдущего примера определяет множество, которое состоит из следующих троек:</p>
     <p><code>(&lt;<emphasis>item name="A"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p><code>(&lt;<emphasis>item name="B"</emphasis>.../&gt;, 'src', 'b')</code></p>
     <p><code>(&lt;<emphasis>item name="C"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p><code>(&lt;<emphasis>item name="D"</emphasis>.../&gt;, 'src', 'c')</code></p>
     <p><code>...</code></p>
     <p><code>(&lt;<emphasis>item name="H"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p>В соответствии с нашими определениями мы можем сказать, что элемент</p>
     <p><code>&lt;item source="b" name="B"/&gt;</code></p>
     <p>имеет ключ с именем <code>"src"</code> и значением <code>"b"</code> или что ключ <code>"src"</code> элемента</p>
     <p><code>&lt;item source="a" name="H"/&gt;</code></p>
     <p>равен <code>"a"</code>.</p>
     <p>Для того чтобы обращаться к множествам узлов по значениям их ключей, в XSLT существует функция <code>key</code>, о которой мы сейчас и поговорим.</p>
    </section>
    <section>
     <title>
      <p>Функция<emphasis> key</emphasis></p>
     </title>
     <p>Ниже приведена синтаксическая конструкция данной функции:</p>
     <p><code><emphasis>node-set </emphasis><strong>key</strong>(<emphasis>string</emphasis>, <emphasis>object</emphasis>)</code></p>
     <p>Итак, элементы <code>xsl:key</code> нашего преобразования определили множество троек <code>(<emphasis>node</emphasis>, <emphasis>name</emphasis>, <emphasis>value</emphasis>)</code>. Функция <code>key(<emphasis>key-name</emphasis>, <emphasis>key-value</emphasis>)</code> выбирает все узлы x такие, что значение их ключа с именем <code><emphasis>key-name</emphasis></code> (первым аргументом функции) равно <code><emphasis>key-value</emphasis></code> (второму аргументу функции).</p>
     <subtitle>Пример</subtitle>
     <p>Значением выражения <code>key('src', 'a')</code> будет множество элементов <code>item</code> таких, что значение их ключа <code>"src"</code> будет равно <code>"а"</code>. Попросту говоря, это будет множество объектов источника <code>"а"</code>.</p>
     <p>Концепция ключей довольно проста, и существует великое множество аналогий в других языках программирования: от хэш-функций до ключей в реляционных таблицах баз данных. По всей вероятности, читателю уже встречалось что-либо подобное.</p>
     <p>Но не следует забывать, что язык XSLT — довольно нетрадиционный язык и с точки зрения синтаксиса, и с точки зрения модели данных. Как следствие, ключи в нем имеют довольно много скрытых нюансов, которые очень полезно знать и понимать. Мы попытаемся как можно более полно раскрыть все эти особенности.</p>
    </section>
    <section>
     <title>
      <p>Определение множества ключей</p>
     </title>
     <p>Не представляет особой сложности определение множества ключей в случае, если в определении они идентифицируются строковыми выражениями. Например, в следующем определении</p>
     <p><code>&lt;xsl:key name="src" match="item" use="string(@source)"/&gt;</code></p>
     <p>атрибут <code>use</code> показывает, что значением ключа <code>src</code> элемента <code>item</code> будет значение атрибута <code>source</code>. Но что можно сказать о следующем определении:</p>
     <p><code>&lt;xsl:key name="src" match="item" use="@*"/&gt;</code></p>
     <p>Очевидно, это уже гораздо более сложный, но, тем не менее, вполне реальный случай, не вписывающийся в определения, которые давались до сих пор. Мы говорили лишь о том, что множество ключей <emphasis>определяется</emphasis> элементами <code>xsl:key</code> преобразования, но <emphasis>как именно</emphasis> оно определяется — оставалось доселе загадкой. Восполним этот пробел, дав строгое определение множеству ключей.</p>
     <p>Узел <code>x</code> обладает ключом с именем <code>у</code> и строковым значением <code>z</code> тогда и только тогда, когда в преобразовании существует элемент <code>xsl:key</code> такой, что одновременно выполняются все нижеперечисленные условия:</p>
     <p>&#9633; узел <code>x</code> соответствует паттерну, указанному в его атрибуте <code>match</code>;</p>
     <p>&#9633; значение его атрибута <code>name</code> равно имени <code>y</code>;</p>
     <p>&#9633; результат <code>u</code> вычисления выражения, указанного в значении атрибута <code>use</code> в контексте текущего множества, состоящего из единственного узла <code>x</code>, удовлетворяет одному из следующих условий:</p>
     <p> • <code>u</code> является множеством узлов и <code>z</code> равно одному из их строковых значений;</p>
     <p> • <code>u</code> не является множеством узлов и <code>z</code> равно его строковому значению.</p>
     <p>Без сомнения, определение не из простых. Но как бы мы действовали, если бы физически создавали в памяти множество ключей? Ниже представлен один из возможных алгоритмов:</p>
     <p>&#9633; для каждого элемента <code>xsl:key</code> найти множество узлов документа, удовлетворяющих его паттерну <code>match</code> (множество <code>X</code>);</p>
     <p>&#9633; для каждого из найденных узлов (<code>x</code> &#8712; <code>X</code>) вычислить значение выражения атрибута <code>use</code> (значение <code>u(x)</code>);</p>
     <p>&#9633; если <code>u(x)</code> является множеством узлов (назовем его <code>U<sub>х</sub></code>), то для каждого <code>u<sub>xi</sub></code> &#8712; <code>U<sub>х</sub></code> создать ключ <code>(x, n, string(u<sub>xi</sub>))</code>, где <code>n</code> — имя ключа (значение атрибута <code>name</code> элемента <code>xsl:key</code>);</p>
     <p>&#9633; если <code>u(x)</code> является объектом другого типа (назовем его <code>u<sub>x</sub></code>), создать ключ <code>(x, n, string(u<sub>x</sub>))</code>.</p>
     <subtitle>Пример</subtitle>
     <p>Найдем множество ключей, создаваемое определением</p>
     <p><code>&lt;xsl:key name="src" match="item" use="@*"/&gt;</code></p>
     <p>Имена всех ключей будут одинаковы и равны <code>"src"</code>. Множество <code>x</code> узлов, удовлетворяющих паттерну <code>item</code>, будет содержать все элементы <code>item</code> обрабатываемого документа. Значением выражения, заданного в атрибуте use, будет множество всех узлов атрибутов каждого из элементов <code>item</code>. Таким образом, множество узлов будет иметь следующий вид:</p>
     <p><code>(&lt;<emphasis>item name="А"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p><code>(&lt;<emphasis>item name="А"</emphasis>.../&gt;, 'src', 'A')</code></p>
     <p><code>(&lt;<emphasis>item name="В"</emphasis>.../&gt;, 'src', 'b')</code></p>
     <p><code>(&lt;<emphasis>item name="В"</emphasis>.../&gt;, 'src', 'В')</code></p>
     <p><code>(&lt;<emphasis>item name="С"</emphasis>.../&gt;, 'src', 'а')</code></p>
     <p><code>(&lt;<emphasis>item name="С"</emphasis>.../&gt;, 'src', 'С')</code></p>
     <p><code>(&lt;<emphasis>item name="D"</emphasis>.../&gt;, 'src', 'с')</code></p>
     <p><code>(&lt;<emphasis>item name="D"</emphasis>.../&gt;, 'src', 'D')</code></p>
     <p><code>...</code></p>
     <p><code>(&lt;<emphasis>item name="H"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p><code>(&lt;<emphasis>item name="H"</emphasis>.../&gt;, 'src', 'H')</code></p>
     <p>В итоге функция <code>key('src', 'a')</code> будет возвращать объекты с именами <code>A</code>, <code>C</code> и <code>H</code>, а функция <code>key('src', 'A')</code> — единственный объект с именем <code>A</code> (поскольку ни у какого другого элемента <code>item</code> нет атрибута со значением <code>"A"</code>).</p>
     <p>Необходимо сделать следующее замечание: совершенно необязательно, чтобы процессор действительно физически создавал в памяти множества ключей. Это множество определяется чисто логически — чтобы было ясно, что же все-таки будет возвращать функция <code>key</code>. Процессоры могут вычислять значения ключей и искать узлы в документе и во время выполнения, не генерируя ничего заранее. Но большинство процессоров, как правило, все же создают в памяти определенные структуры для манипуляций с ключами. Это могут быть хэш-таблицы, списки, простые массивы или более сложные нелинейные структуры, упрощающие поиск, — важно другое. Важно то, что имея явное определение ключа в <code>xsl:key</code>, процессор может производить такую оптимизацию.</p>
    </section>
    <section>
     <title>
      <p>Использование нескольких ключей в одном преобразовании</p>
     </title>
     <p>В случае, когда к узлам в преобразовании нужно обращаться по значениям различных свойств, можно определить несколько ключей — каждый со своим именем. Например, если мы хотим в одном случае обращаться к объектам, принадлежащим одному источнику, а во втором — к объектам с определенными именами, мы можем определить в документе два ключа — один с именем <code>src</code>, второй — с именем <code>name</code>:</p>
     <p><code>&lt;xsl:key name="src" match="item" use="@source"/&gt;</code></p>
     <p><code>&lt;xsl:key name="name" match="item" use="@name"/&gt;</code></p>
     <p>Множество ключей, созданных этими двумя определениями, будет выглядеть следующим образом:</p>
     <p><code>(&lt;<emphasis>item name="А"</emphasis>.../&gt;, 'src', 'а')</code></p>
     <p><code>(&lt;<emphasis>item name="А"</emphasis>.../&gt;, 'name', 'А')</code></p>
     <p><code>(&lt;<emphasis>item name="В"</emphasis>.../&gt;, 'src', 'b')</code></p>
     <p><code>(&lt;<emphasis>item name="В"</emphasis>.../&gt;, 'name', 'В')</code></p>
     <p><code>(&lt;<emphasis>item name="C"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p><code>(&lt;<emphasis>item name="C"</emphasis>.../&gt;, 'name', 'С')</code></p>
     <p><code>(&lt;<emphasis>item name="D"</emphasis>.../&gt;, 'src', 'с')</code></p>
     <p><code>(&lt;<emphasis>item name="D"</emphasis>.../&gt;, 'name', 'D')</code></p>
     <p><code>...</code></p>
     <p><code>(&lt;<emphasis>item name="H"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p><code>(&lt;<emphasis>item name="H"</emphasis>.../&gt;, 'name', 'H')</code></p>
     <p>В этом случае функция <code>key('src', 'а')</code> возвратит объекты с именами <code>A</code>, <code>C</code> и <code>H</code>, а функция <code>key('name', 'а')</code> — объект с именем <code>А</code>.</p>
     <p>Имя ключа является расширенным именем. Оно может иметь объявленный префикс пространства имен, например</p>
     <p><code>&lt;xsl:key</code></p>
     <p><code> name="data:src"</code></p>
     <p><code> match="item"</code></p>
     <p><code> use="@source"</code></p>
     <p><code> xmlns:data="urn:user-data"/&gt;</code></p>
     <p>В этом случае функция <code>key(key-name, key-value)</code> будет возвращать узлы, значение ключа с расширенным именем <code>key-name</code> которых равно <code>key-value</code>. Совпадение расширенных имен определяется как обычно — по совпадению локальных частей и URI пространств имен.</p>
    </section>
    <section>
     <title>
      <p>Использование нескольких определений одного ключа</p>
     </title>
     <p>Процессор должен учитывать все определения ключей данного преобразования — даже если некоторые из них находятся во включенных или импортированных модулях. Порядок импорта элементов <code>xsl:key</code> не имеет значения: дело в том, что определения ключей с одинаковыми именами для одних и тех же узлов, но с разными значениями ключа не переопределяют, а дополняют друг друга.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что в нашем документе имеется несколько элементов <code>item</code>, в которых не указано значение атрибута <code>source</code>, но по умолчанию мы будем причислять их к источнику <code>а</code>. Соответствующие ключи будут определяться следующим образом:</p>
     <p><code>&lt;xsl:key name="src" match="item[@source]" use="@source"/&gt;</code></p>
     <p><code>&lt;xsl:key name="src" match="item[not(@source)]" use="'a'"/&gt;</code></p>
     <p>To есть для тех элементов <code>item</code>, у которых есть атрибут <code>source</code>, значением ключа будет значение этого атрибута, для тех же элементов, у которых атрибута <code>source</code> нет, его значением будет <code>"а"</code>.</p>
     <p>Для входящего документа вида</p>
     <p><code>&lt;items&gt;</code></p>
     <p><code> &lt;item source="a" name="A"/&gt;</code></p>
     <p><code> &lt;item source="b" name="B"/&gt;</code></p>
     <p><code> &lt;item source="a" name="C"/&gt;</code></p>
     <p><code> &lt;item source="c" name="D"/&gt;</code></p>
     <p><code> ...</code></p>
     <p><code> &lt;item source="a" name="H"/&gt;</code></p>
     <p><code> &lt;item name="I"/&gt;</code></p>
     <p><code> &lt;item name="J"/&gt;</code></p>
     <p><code> &lt;item name="K"/&gt;</code></p>
     <p><code>&lt;/items&gt;</code></p>
     <p>соответствующее множество ключей будет определяться следующим образом:</p>
     <p><code>(&lt;<emphasis>item name="А"</emphasis>.../&gt;, 'src', 'а')</code></p>
     <p><code>(&lt;<emphasis>item name="В"</emphasis>.../&gt;, 'src', 'b')</code></p>
     <p><code>(&lt;<emphasis>item name="С"</emphasis>.../&gt;, 'src', 'а')</code></p>
     <p><code>(&lt;<emphasis>item name="D"</emphasis>.../&gt;, 'src', 'c')</code></p>
     <p><code>...</code></p>
     <p><code>(&lt;<emphasis>item name="H"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p><code>(&lt;<emphasis>item name="I"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p><code>(&lt;<emphasis>item name="J"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p><code>(&lt;<emphasis>item name="K"</emphasis>.../&gt;, 'src', 'a')</code></p>
     <p>Функция <code>key('src', 'a')</code> возвратит объекты с именами <code>A</code>, <code>C</code>, <code>H</code>, <code>I</code>, <code>J </code>и <code>K</code>.</p>
     <p>То, что одни и те же узлы могут иметь разные значения одного ключа, является также очень удобным свойством. Например, два определения ключей, приведенные выше, можно дополнить третьим:</p>
     <p><code>&lt;xsl:key name="src" match="item[not(@source)]" use="'#default'"/&gt;</code></p>
     <p>Это определение позволит по значению <code>"#default"</code> обращаться к объектам, принадлежащим источнику по умолчанию.</p>
    </section>
    <section>
     <title>
      <p>Использование множеств узлов в функции<emphasis> key</emphasis></p>
     </title>
     <p>Функция <code>key</code> принимает на вход два аргумента: первым аргументом является строка, задающая имя ключа, в то время как вторым аргументом может быть объект любого типа. В том случае, если аргумент <code><emphasis>key-value</emphasis></code> в функции <code>key(<emphasis>key-name</emphasis>, <emphasis>key-value</emphasis>)</code> является множеством узлов, функция <code>key</code> возвратит все узлы, имеющие ключ <code><emphasis>key-name</emphasis></code> со значением, равным хотя бы одному из строковых значений узла множества <code><emphasis>key-value</emphasis></code>.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что источники объектов будут сгруппированы следующим образом:</p>
     <p><code>&lt;sources&gt;</code></p>
     <p><code> &lt;source name="a"/&gt;</code></p>
     <p><code> &lt;source name="c"/&gt;</code></p>
     <p><code>&lt;/source&gt;</code></p>
     <p>Для того чтобы вычислить множество элементов <code>item</code>, принадлежащих любому из источников данной группы, достаточно будет воспользоваться выражением вида</p>
     <p><code>key('src', sources/source/@name)</code></p>
     <p>Множество узлов, выбираемое путем <code>sources/source/@name</code>, будет содержать атрибуты <code>name</code> элементов <code>source</code>. Их строковые значения будут равны <code>а</code> и <code>с</code>, значит, наше выражение возвратит множество элементов <code>item</code>, значение атрибута <code>source</code> которых равно либо <code>а</code> либо <code>с</code>.</p>
    </section>
    <section>
     <title>
      <p>Использование ключей в нескольких документах</p>
     </title>
     <p>Ключи, определенные в преобразовании, могут использоваться для выбора узлов в различных обрабатываемых документах. Функция <code>key</code> возвращает узлы, которые принадлежат текущему документу, то есть документу, содержащему текущий узел. Значит, для того, чтобы выбирать узлы из внешнего документа, необходимо сделать текущим узлом один из узлов этого внешнего документа. Контекстный документ может быть легко изменен элементом <code>xsl:for-each</code>, например, для того, чтобы текущим документом стал документ <code>a.xml</code>, достаточно написать</p>
     <p><code>&lt;xsl:for-each select="document('а.xml')"&gt;</code></p>
     <p><code> &lt;!-- Теперь текущим документом стал документ а.xml --&gt;</code></p>
     <p><code>&lt;/xsl:for-each&gt;</code></p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что нам нужно выбрать объекты, принадлежащие источнику <code>a</code>, причем принадлежность объектов определена в двух внешних документах, <code>a.xml</code> и <code>b.xml</code>.</p>
     <subtitle>Листинг 8.22. Входящий документ</subtitle>
     <p><code>&lt;source name="a"/&gt;</code></p>
     <subtitle>Листинг 8.23. Документ a.xml</subtitle>
     <p><code>&lt;items&gt;</code></p>
     <p><code> &lt;item source="a" name="A"/&gt;</code></p>
     <p><code> &lt;item source="b" name="B"/&gt;</code></p>
     <p><code> &lt;item source="a" name="C"/&gt;</code></p>
     <p><code> &lt;item source="c" name="D"/&gt;</code></p>
     <p><code>&lt;/items&gt;</code></p>
     <subtitle>Листинг 8.24. Документ b.xml</subtitle>
     <p><code>&lt;items&gt;</code></p>
     <p><code> &lt;item source="b" name="E"/&gt;</code></p>
     <p><code> &lt;item source="b" name="F"/&gt;</code></p>
     <p><code> &lt;item source="c" name="G"/&gt;</code></p>
     <p><code> &lt;item source="a" name="H"/&gt;</code></p>
     <p><code>&lt;/items&gt;</code></p>
     <subtitle>Листинг 8.25. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:key name="src" match="item" use="@source"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="source"&gt;</code></p>
     <p><code>  &lt;xsl:variable name="name" select="@name"/&gt;</code></p>
     <p><code>  &lt;xsl:copy&gt;</code></p>
     <p><code>   &lt;xsl:for-each select="document('a.xml')|document('b.xml')"&gt;</code></p>
     <p><code>    &lt;xsl:copy-of select="key('src', $name)"/&gt;</code></p>
     <p><code>   &lt;/xsl:for-each&gt;</code></p>
     <p><code>  &lt;/xsl:copy&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 8.26. Выходящий документ</subtitle>
     <p><code>&lt;source&gt;</code></p>
     <p><code> &lt;item source="a" name="A"/&gt;</code></p>
     <p><code> &lt;item source="a" name="C"/&gt;</code></p>
     <p><code> &lt;item source="a" name="H"/&gt;</code></p>
     <p><code>&lt;/source&gt;</code></p>
    </section>
    <section>
     <title>
      <p>Составные ключи</p>
     </title>
     <p>В теории реляционных баз данных существует такое понятие, как составной ключ. Согласно определению К. Дж. Дейта [Дейт 1999], составной ключ — это "<emphasis>потенциальный ключ; состоящий из более чем одного атрибута</emphasis>".</p>
     <p>Хотя концепция ключей в XSLT сильно отличается от того, что называется ключом в реляционных БД, идея весьма и весьма интересна: использовать при обращении к множествам узлов не <emphasis>одно</emphasis> свойство, а некоторую их комбинацию.</p>
     <p>Главная проблема состоит в том, что значение ключа в XSLT всегда является строкой, одним из самых примитивных типов. И выбирать множества узлов можно только по одному строковому значению за один раз. Ничего похожего на <code>key(<emphasis>key-name</emphasis>, <emphasis>key-value-1</emphasis>, <emphasis>key-value-2</emphasis>, ...)</code> для выбора узлов, первое свойство которых равно <code><emphasis>key-value-1</emphasis></code>, второе — <code><emphasis>key-value-2</emphasis></code> и так далее, XSLT не предоставляет.</p>
     <p>Выход достаточно очевиден: если значение ключа не может <emphasis>быть</emphasis> сложной структурой, оно должно <emphasis>выражать</emphasis> сложную структуру. Иными словами, раз значением составного ключа может быть только строка, то эта строка должна состоять из нескольких частей.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что объекты с одинаковыми именами могут принадлежать различным источникам. Покажем, как с помощью ключей можно решить следующие задачи:</p>
     <p>&#9633; найти объект с определенным именем и источником;</p>
     <p>&#9633; найти объекты с определенным именем;</p>
     <p>&#9633; найти объекты с определенным источником.</p>
     <subtitle>Листинг 8.27. Входящий документ</subtitle>
     <p><code>&lt;items&gt;</code></p>
     <p><code> &lt;item source="a" name="A"/&gt;</code></p>
     <p><code> &lt;item source="b" name="B"/&gt;</code></p>
     <p><code> &lt;item source="b" name="E"/&gt;</code></p>
     <p><code> &lt;item source="b" name="F"/&gt;</code></p>
     <p><code> &lt;item source="a" name="C"/&gt;</code></p>
     <p><code> &lt;item source="c" name="G"/&gt;</code></p>
     <p><code> &lt;item source="a" name="H"/&gt;</code></p>
     <p><code> &lt;item source="a" name="B"/&gt;</code></p>
     <p><code> &lt;item source="b" name="G"/&gt;</code></p>
     <p><code> &lt;item source="c" name="H"/&gt;</code></p>
     <p><code> &lt;item source="c" name="C"/&gt;</code></p>
     <p><code> &lt;item source="c" name="D"/&gt;</code></p>
     <p><code> &lt;item source="b" name="A"/&gt;</code></p>
     <p><code> &lt;item source="a" name="B"/&gt;</code></p>
     <p><code> &lt;item source="c" name="D"/&gt;</code></p>
     <p><code> &lt;item source="c" name="E"/&gt;</code></p>
     <p><code> &lt;item source="a" name="F"/&gt;</code></p>
     <p><code>&lt;/items&gt;</code></p>
     <p>Для элементов <code>item</code> мы будем генерировать ключи, значения которых будут состоять из двух частей — источника и имени, разделенных символом "<code>-</code>". Для того чтобы решить одним ключом все три поставленные задачи, мы будем использовать для его определения три элемента <code>xsl:key</code>.</p>
     <subtitle>Листинг 8.28. Входящий документ</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:key name="src" match="item" use="concat(@source,'-')"/&gt;</code></p>
     <p><code> &lt;xsl:key name="src" match="item" use="concat('-', @name)"/&gt;</code></p>
     <p><code> &lt;xsl:key name="src" match="item" use="concat(@source, '-', @name)"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;result&gt;</code></p>
     <p><code>   &lt;items source="a" name="B"&gt;</code></p>
     <p><code>    &lt;xsl:copy-of select="key('src', 'a-B')"/&gt;</code></p>
     <p><code>   &lt;/items&gt;</code></p>
     <p><code>   &lt;items name="B"&gt;</code></p>
     <p><code>    &lt;xsl:copy-of select="key('src', '-B')"/&gt;</code></p>
     <p><code>   &lt;/items&gt;</code></p>
     <p><code>   &lt;items source="a"&gt;</code></p>
     <p><code>    &lt;xsl:copy-of select="key('src', 'a-')"/&gt;</code></p>
     <p><code>   &lt;/items&gt;</code></p>
     <p><code>  &lt;/result&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 8.29. Выходящий документ</subtitle>
     <p><code>&lt;result&gt;</code></p>
     <p><code> &lt;items source="a" name="B"&gt;</code></p>
     <p><code>  &lt;item source="a" name="B"/&gt;</code></p>
     <p><code>  &lt;item source="a" name="B"/&gt;</code></p>
     <p><code> &lt;/items&gt;</code></p>
     <p><code> &lt;items name="B"&gt;</code></p>
     <p><code>  &lt;item source="b" name="B"/&gt;</code></p>
     <p><code>  &lt;item source="a" name="B"/&gt;</code></p>
     <p><code>  &lt;item source="a" name="B"/&gt;</code></p>
     <p><code> &lt;/items&gt;</code></p>
     <p><code> &lt;items source="a"&gt;</code></p>
     <p><code>  &lt;item source="a" name="A"/&gt;</code></p>
     <p><code>  &lt;item source="a" name="C"/&gt;</code></p>
     <p><code>  &lt;item source="a" name="H"/&gt;</code></p>
     <p><code>  &lt;item source="a" name="B"/&gt;</code></p>
     <p><code>  &lt;item source="a" name="B"/&gt;</code></p>
     <p><code>  &lt;item source="a" name="F"/&gt;</code></p>
     <p><code> &lt;/items&gt;</code></p>
     <p><code>&lt;/result&gt;</code></p>
     <p>У приведенного здесь способа формирования ключа есть определенные ограничения: необходимо иметь априорную информацию о строковых значениях каждого из свойств, составляющих наш композитный ключ для того, чтобы корректно формировать его строковые представления. Например, если бы в приведенном выше документе имена объектов и источников могли бы содержать символ "<code>-</code>", было бы непонятно, к какому объекту относится составной ключ "<code>a-b-c</code>": к объекту с источником <code>a-b</code> и именем <code>с</code> или к объекту с источником <code>а</code> и именем <code>b-c</code>. К счастью, в большинстве случаев такая информация имеется, и генерировать составные ключи не очень сложно.</p>
    </section>
    <section>
     <title>
      <p>Функция <emphasis>key</emphasis> в паттернах</p>
     </title>
     <p>Разбирая синтаксические правила построения паттернов, мы встретились с особой формой паттерна, в котором могла использоваться функция <code>key</code>. Приведем еще раз эту продукцию:</p>
     <p><code>[PT3] IdKeyPattern ::= 'id' '(' Literal ')'</code></p>
     <p><code>                       | 'key' '(' Literal ',' Literal ')'</code></p>
     <p>Функция <code>key(<emphasis>key-name</emphasis>, <emphasis>key-value</emphasis>)</code> в паттерне будет соответствовать узлам, значение ключа <code>key-name</code> которых равняется или принадлежит объекту <code>key-value</code>. Это позволяет использовать возможности ключей при проверке узлов на соответствие образцу.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что нам нужно по-особому обработать объекты, принадлежащие источнику <code>а</code>. Для этого мы можем создать шаблон следующего вида.</p>
     <subtitle>Листинг 8.30. Шаблон, использующий функцию key в паттерне</subtitle>
     <p><code>&lt;xsl:template match="key('src', 'a')"&gt;</code></p>
     <p><code> &lt;!-- Содержимое шаблона --&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Этот шаблон будет применяться к любым узлам, имеющим ключ <code>src</code> со значением <code>а</code>.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Нумерация</p>
    </title>
    <section>
     <p>Нумерация, несомненно, является одной из самых естественных проблем, решаемых при помощи XSLT. Задача нумерации состоит в том, чтобы, исходя из позиции обрабатываемого узла в дереве документа, вычислить по заданным критериям его порядковый номер. В качестве примера такого рода задачи можно привести вывод номеров частей, разделов и глав книги, указание номеров элементов списка или строк таблицы.</p>
     <p>Для вычисления порядковых номеров узлов в дереве в XSLT существует несколько способов. В простых случаях для достижения цели бывает достаточно воспользоваться одним из следующих XPath-выражений.</p>
     <p>&#9633; Для того чтобы получить порядковый номер текущего узла в обрабатываемом множестве, можно использовать функцию <code>position</code>. Обратим внимание, что это будет позиция узла в обрабатываемом в данный момент множестве, а не в дереве исходящего документа.</p>
     <p>&#9633; Функция <code>count(preceding-sibling::*)+1</code> возвращает порядковый номер текущего элемента среди других элементов его родителя, иначе говоря, среди его братьев. Путь выборки <code>preceding-sibling::*</code> выбирает множество братских элементов, предшествующих текущему узлу, а функция <code>count</code> вычисляет их количество. Таким образом, значение <code>count(preceding-sibling::*)+1</code> будет равно <code>1</code> для первого элемента (поскольку ему другие элементы не предшествуют), <code>2</code> — для второго (ему предшествует один элемент) и так далее.</p>
     <p>&#9633; Для того чтобы учитывать при подсчете только определенные элементы, можно переписать предыдущее выражение в чуть более строгом виде. Например, выражение, считающее только элементы <code>chapter</code>, будет задаваться следующим образом: <code>(preceding-sibling::chapter) +1</code>.</p>
     <p>&#9633; Глубина текущего узла от корня дерева может быть вычислена выражением count(ancestor-or-self::node()). Это выражение будет возвращать <code>1</code> для корневого узла, <code>2</code> для элемента документа и так далее.</p>
     <p>Вычислять выражения и выводить вычисленные значения в результирующее дерево следует, как и обычно — при помощи элемента <code>xsl:value-of</code>.</p>
     <subtitle>Пример</subtitle>
     <p><code>&lt;xsl:value-of select="count(preceding-sibling::chapter)+1"/&gt;</code></p>
     <p>В более сложных ситуациях бывает необходимо подсчитывать узлы, находящиеся на разных уровнях вложенности или удовлетворяющие определенным условиям, начинать отсчет с заданной позиции в документе и использовать при вычислении номера сложные выражения. Использование XPath в таких случаях может быть очень неудобным — выражения будут слишком громоздкими и вычислять их придется в несколько этапов.</p>
     <p>Другим, несравненно более легким и удобным способом нумерации и индексирования узлов является использование элемента <code>xsl:number</code>.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:number</emphasis></p>
     </title>
     <section>
      <p>Синтаксис элемента описывается следующей конструкцией:</p>
      <p><code>&lt;xsl:number</code></p>
      <p><code> level="single"</code></p>
      <p><code>      | "multiple"</code></p>
      <p><code>      | "any"</code></p>
      <p><code> count="<emphasis>паттерн</emphasis>"</code></p>
      <p><code> from="<emphasis>паттерн</emphasis>"</code></p>
      <p><code> value="<emphasis>выражение</emphasis>"</code></p>
      <p><code> format="{<emphasis>строка</emphasis>}"</code></p>
      <p><code> lang="{<emphasis>токен</emphasis>}"</code></p>
      <p><code> letter-value={ "alphabetic"</code></p>
      <p><code>              | "traditional" }</code></p>
      <p><code> grouping-separator="{<emphasis>символ</emphasis>}"</code></p>
      <p><code> grouping-size="{<emphasis>число</emphasis>}"/&gt;</code></p>
      <p>Элемент <code>xsl:number</code> вычисляет номер узла в соответствии с заданными критериями, форматирует его и затем вставляет в результирующее дерево в виде текстового узла. То, что все это выполняется в одном элементе преобразования, имеет существенные преимущества по сравнению с использованием XPath-выражений: программа становится более простой и понятной, причем далеко не в ущерб функциональности.</p>
      <p>К сожалению, в этом случае, как и во многих других, универсальность использования повлекла за собой семантическую сложность. Несмотря на то, что <code>xsl:number</code> имеет всего девять атрибутов (причем ни один из них не является обязательным), мы посвятим их описанию значительное количество страниц. Пока же, чтобы сориентировать читателя, мы кратко перечислим назначения атрибутов <code>xsl:number</code>.</p>
      <p>&#9633; Атрибут <code>level</code> указывает, на каких уровнях дерева следует искать нумеруемые узлы.</p>
      <p>&#9633; Атрибут <code>count</code> указывает, какие именно узлы следует считать при вычислении номера.</p>
      <p>&#9633; Атрибут <code>from</code> указывает, в какой части документа будет производиться нумерация.</p>
      <p>&#9633; Атрибут <code>value</code> задает выражения, которые следует использовать для вычисления значения номера.</p>
      <p>&#9633; Атрибут <code>format</code> определяет, как номер будет форматироваться в строку.</p>
      <p>&#9633; Атрибут <code>lang</code> задает языковой контекст нумерации.</p>
      <p>&#9633; Атрибут <code>letter-value</code> определяет параметры буквенных методов нумерации.</p>
      <p>&#9633; Атрибут <code>grouping-separator</code> задает символ, разделяющий группы цифр в номере.</p>
      <p>&#9633; Атрибут <code>grouping-size</code> определяет количество цифр в одной группе.</p>
      <p>Выполнение элемента <code>xsl:number</code> можно условно разделить на два этапа — вычисление номера и его строковое форматирование. На этапе вычисления активными являются элементы <code>level</code>, <code>count</code>, <code>from</code> и <code>value</code>. Форматирование производится с учетом значений атрибутов <code>format</code>, <code>lang</code>, <code>letter-value</code>, <code>grouping-separator</code> и <code>grouping-size</code>. Результатом первого этапа является список номеров, который форматируется в текстовый узел на втором этапе.</p>
     </section>
     <section>
      <title>
       <p>Вычисление номеров</p>
      </title>
      <p>Пожалуй, самым простым для понимания (но не самым простым в использовании) способом вычисления номера является использование XPath-выражений. Этот способ практически идентичен использованию <code>xsl:value-of</code>, как было показано в начале этой главы. Единственным отличием <code>xsl:number</code> является то, что после вычисления номера он сначала форматируется, а потом уже вставляется в результирующее дерево в виде текстового узла.</p>
      <p>Результатом первого этапа форматирования при определенном атрибуте <code>value</code> является список, состоящий из числа, полученного в результате вычисления выражения, указанного в значении этого атрибута.</p>
      <subtitle>Пример</subtitle>
      <p>В этом и нескольких следующих примерах мы будем вычислять номера в одном и том же документе, который представлен в листинге 8.31.</p>
      <subtitle>Листинг 8.31. Входящий документ для примеров преобразований с использованием xsl:number</subtitle>
      <p><code>&lt;doc&gt;</code></p>
      <p><code> &lt;chapter title="First chapter"&gt;</code></p>
      <p><code>  &lt;section title="First section"&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 1&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 2&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 3&lt;/para&gt;</code></p>
      <p><code>  &lt;/section&gt;</code></p>
      <p><code>  &lt;section title="Second section"&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 4&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 5&lt;/para&gt;</code></p>
      <p><code>  &lt;/section&gt;</code></p>
      <p><code> &lt;/chapter&gt;</code></p>
      <p><code> &lt;chapter title="Second chapter"&gt;</code></p>
      <p><code>  &lt;section title="Third section"&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 6&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 7&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 8&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 9&lt;/para&gt;</code></p>
      <p><code>  &lt;/section&gt;</code></p>
      <p><code>  &lt;section title="Forth section"&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 10&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 11&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 12&lt;/para&gt;</code></p>
      <p><code>  &lt;/section&gt;</code></p>
      <p><code>  &lt;section title="Fifth section"&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 13&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 14&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 15&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 16&lt;/para&gt;</code></p>
      <p><code>  &lt;/section&gt;</code></p>
      <p><code> &lt;/chapter&gt;</code></p>
      <p><code> &lt;chapter title="Third chapter"&gt;</code></p>
      <p><code>  &lt;section title="Sixth section"&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 17&lt;/para&gt;</code></p>
      <p><code>   &lt;para&gt;paragraph 18&lt;/para&gt;</code></p>
      <p><code>  &lt;/section&gt;</code></p>
      <p><code> &lt;/chapter&gt;</code></p>
      <p><code>&lt;/doc&gt;</code></p>
      <p>В качестве первого примера приведем два шаблона, обрабатывающих элементы <code>chapter</code>: один с использованием <code>xsl:value-of</code>, а второй с использованием <code>xsl:number</code>.</p>
      <subtitle>Листинг 8.32. Вариант нумерующего шаблона с использованием xsl:value-of</subtitle>
      <p><code>&lt;xsl:template match="chapter"&gt;</code></p>
      <p><code> &lt;xsl:value-of select="position()"/&gt;</code></p>
      <p><code> &lt;xsl:text&gt;. &lt;/xsl:text&gt;</code></p>
      <p><code> &lt;xsl:value-of select="@title"/&gt;</code></p>
      <p><code> &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
      <p><code>&lt;/xsl:template&gt;</code></p>
      <subtitle>Листинг 8.33. Вариант нумерующего шаблона с использованием xsl:number</subtitle>
      <p><code>&lt;xsl:template match="chapter"&gt;</code></p>
      <p><code> &lt;xsl:number value="position()" format="1. "/&gt;</code></p>
      <p><code> &lt;xsl:value-of select="@title"/&gt;</code></p>
      <p><code> &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
      <p><code>&lt;/xsl:template&gt;</code></p>
      <p>Результат обоих шаблонов имеет следующий вид:</p>
      <p><code>1. First chapter</code></p>
      <p><code>2. Second chapter</code></p>
      <p><code>3. Third chapter</code></p>
      <p>Использование <code>xsl:number</code> даже в этом простом случае сэкономило одну строчку в коде. Однако, если бы вместо нумерации арабскими цифрами (<code>1</code>, <code>2</code>, <code>3</code> и т.д.) нужно было применить нумерацию римскими цифрами (<code>I</code>, <code>II</code>, <code>III</code> и т.д.), в преобразовании с <code>xsl:number</code> мы бы изменили всего один символ (вместо <code>format="1. "</code> указали бы <code>format="I. "</code>), в то время как в преобразовании с <code>xsl:value-of</code> пришлось бы писать сложную процедуру преобразования числа в римскую запись.</p>
      <p>В том случае, если атрибут <code>value</code> опущен, номера элементов вычисляются исходя из значений атрибутов <code>level</code>, <code>count</code> и <code>from</code>.</p>
      <p>Атрибут <code>level</code> имеет три варианта значений: <code>single</code>, <code>multiple</code> и <code>any</code>, значением по умолчанию является <code>single</code>. Процедура вычисления номеров существенным образом зависит от того, какой из этих вариантов используется — при методе <code>single</code> считаются элементы на одном уровне, при методе <code>multiple</code> — на нескольких уровнях и при методе <code>any</code> — на любых уровнях дерева. Алгоритм вычисления списка номеров в каждом из случаев не слишком сложен, но понять его только по формальному описанию довольно непросто. Поэтому каждый из методов будет дополнительно проиллюстрирован примерами вычисления.</p>
      <p>Атрибут <code>count</code> содержит паттерн, которому должны удовлетворять нумеруемые узлы. Узлы, не соответствующие этому образцу, просто не будут приниматься в расчет. Значением этого атрибута по умолчанию является паттерн, выбирающий узлы с тем же типом и именем, что и у текущего узла (если, конечно, у него есть имя).</p>
      <p>Атрибут <code>from</code> содержит паттерн, который определяет так называемую область нумерации, или область подсчета. При вычислении номера будут приниматься во внимание только те нумеруемые узлы, которые принадлежат этой области. По умолчанию областью подсчета является весь документ.</p>
      <subtitle>Метод <emphasis>single</emphasis></subtitle>
      <p>Метод <code>single</code> используется для того, чтобы вычислить номер узла, основываясь на его позиции среди узлов того же уровня. Нумерацию, в которой используется метод <code>single</code>, также называют одноуровневой нумерацией.</p>
      <p>Областью нумерации этого метода будет множество всех потомков ближайшего предка текущего узла, удовлетворяющего паттерну, указанному в атрибуте <code>from</code>.</p>
      <p>Вычисление номера производится в два шага.</p>
      <p>&#9633; На первом шаге находится узел уровня дерева. Узлом уровня будет узел, удовлетворяющий следующим условиям:</p>
      <p> • он является первым (то есть ближайшим к текущему) узлом, принадлежащим оси <code>ancestor-or-self</code> текущего узла;</p>
      <p> • он удовлетворяет паттерну <code>count</code>;</p>
      <p> • он принадлежит области подсчета;</p>
      <p> • если такого узла нет, список номеров будет пустым.</p>
      <p>&#9633; На втором шаге вычисляется номер узла уровня. Этот номер будет равен <code>1</code> плюс количество узлов, принадлежащих оси навигации <code>preceding-sibling</code> и удовлетворяющих паттерну <code>count</code>.</p>
      <p>Надо сказать, от атрибута <code>from</code> в методе <code>single</code> мало пользы. Единственный эффект, который можно от него получить, — это пустой список номеров в случае, если первый узел, принадлежащий оси <code>ancestor-or-self</code> и удовлетворяющий паттерну <code>count</code>, не будет иметь предка, соответствующего паттерну атрибута <code>from</code>.</p>
      <subtitle>Пример</subtitle>
      <p>Разберем функционирование одноуровневой нумерации в следующем шаблоне:</p>
      <p><code>&lt;xsl:template match="para"&gt;</code></p>
      <p><code> &lt;xsl:number format="     1." count="section"/&gt;</code></p>
      <p><code> &lt;xsl:number format="1." count="para"/&gt;</code></p>
      <p><code> &lt;xsl:value-of select="."/&gt;</code></p>
      <p><code> &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
      <p><code>&lt;/xsl:template&gt;</code></p>
      <p>Мы продемонстрируем вычисление номера одного из элементов <code>para</code> на схематическом изображении дерева обрабатываемого документа (рис. 8.1). Узел обрабатываемого элемента мы выделим полужирной линией, узел элемента <code>doc</code> пометим буквой <code>d</code>, узлы элементов <code>chapter</code> — буквой <code>с</code>, элементов <code>section</code> и para — буквами <code>s</code> и <code>p</code> соответственно.</p>
      <image l:href="#img_58.png"/>
      <p><strong>Рис. 8.1</strong>. Дерево обрабатываемого документа</p>
      <p>В качестве первого примера приведем вычисление номера элементом</p>
      <p><code>&lt;xsl:number format="     1." count="section"/&gt;</code></p>
      <p>На первом шаге нам нужно найти узел уровня дерева. Этим узлом будет первый элемент <code>section</code>, являющийся предком текущего узла. На рис. 8.2 он обведен пунктиром.</p>
      <image l:href="#img_59.png"/>
      <p><strong>Рис. 8.2</strong>. Первый шаг вычисления номера</p>
      <p>Номер этого элемента будет равен <code>1</code> плюс количество предшествующих ему братских элементов <code>section</code>. Это множество выделено пунктиром на рис. 8.3.</p>
      <image l:href="#img_60.png"/>
      <p><strong>Рис. 8.3</strong>. Второй шаг вычисления номера</p>
      <p>Выделенное множество содержит два узла. Таким образом, искомый номер будет равен <code>3</code>.</p>
      <p>Проведем такой же разбор для определения</p>
      <p><code>&lt;xsl:number format="1." count="para"/&gt;</code></p>
      <p>В этом случае паттерну, указанному в элементе <code>count</code> удовлетворяет сам текущий узел, значит, он и будет являться узлом уровня, как это показано на рис. 8.4.</p>
      <image l:href="#img_61.png"/>
      <p><strong>Рис. 8.4</strong>. Первый шаг вычисления номера</p>
      <p>Выделим множество элементов <code>para</code>, являющихся братьями узла уровня и предшествующих ему (рис. 8.5).</p>
      <image l:href="#img_62.png"/>
      <p><strong>Рис. 8.5</strong>. Второй шаг вычисления номера</p>
      <p>Выделенное множество содержит всего один узел, значит, искомый номер будет равен <code>2</code>.</p>
      <p>Таким образом, результатом обработки выделенного элемента <code>para</code> будет следующая строка:</p>
      <p><code>    3.2.paragraph 14</code></p>
      <subtitle>Метод <emphasis>multiple</emphasis></subtitle>
      <p>Метод <code>multiple</code> похож на метод <code>single</code>, но при этом он немного сложнее, поскольку вычисляет номера узлов сразу на нескольких уровнях дерева. Нумерацию с применением метода <code>multiple</code> называют также многоуровневой нумерацией.</p>
      <p>Область нумерации метода <code>multiple</code> определяется так же, как и в случае с методом <code>single</code>: учитываются только потомки ближайшего предка текущего узла, удовлетворяющего паттерну, указанному в атрибуте <code>from</code>.</p>
      <p>Вычисление списка номеров узлов выполняется в два этапа:</p>
      <p>&#9633; На первом этапе выбирается множество нумеруемых узлов, удовлетворяющее следующим условиям:</p>
      <p> • его узлы принадлежат оси навигации <code>ancestor-or-self</code> текущего узла;</p>
      <p> • его узлы соответствуют паттерну <code>count</code>;</p>
      <p> • его узлы принадлежат области подсчета.</p>
      <p>&#9633; На втором этапе для каждого узла нумеруемого множества вычисляется позиция среди собратьев. Позиция нумеруемого узла будет равна <code>1</code> плюс количество узлов, принадлежащих его оси навигации <code>preceding-sibling</code> и соответствующих паттерну <code>count</code>.</p>
      <subtitle>Пример</subtitle>
      <p>Для демонстрации вычисления номеров на нескольких уровнях дерева документа проследим за выполнением инструкции</p>
      <p><code>&lt;xsl:number</code></p>
      <p><code> format="     1.1."</code></p>
      <p><code> level="multiple"</code></p>
      <p><code> count="doc|chapter|para"</code></p>
      <p><code> from="doc"/&gt;</code></p>
      <p>при обработке того же элемента <code>para</code>.</p>
      <p>Прежде всего, надо определить область подсчета. Значением атрибута <code>from</code> является паттерн <code>doc</code>, значит, подсчет будет вестись среди всех потомков ближайшего к текущему элементу <code>para</code> предка, который является элементом <code>doc</code>. Это множество выделено на рис. 8.6 штрих-пунктирной линией.</p>
      <image l:href="#img_63.png"/>
      <p><strong>Рис. 8.6</strong>. Определение области подсчета</p>
      <p>Следующим шагом выберем узлы, принадлежащие оси навигации <code>ancestor-or-self</code> текущего узла para и удовлетворяющие паттерну <code>doc|chapter|para</code>. Это множество будет включать сам текущий элемент, а также его предки <code>chapter</code> и <code>doc</code>. На рис. 8.7 они обведены пунктиром.</p>
      <image l:href="#img_64.png"/>
      <p><strong>Рис. 8.7</strong>. Первый шаг вычисления номера</p>
      <p>Следующим шагом оставим только те из выбранных узлов, которые входят в область подсчета. Эти узлы обведены на рис. 8.8 пунктиром.</p>
      <image l:href="#img_65.png"/>
      <p><strong>Рис. 8.8</strong>. Второй шаг вычисления номера</p>
      <p>Мы получили множество узлов, состоящее всего из двух элементов — <code>chapter</code> и <code>para</code> вследствие того, что элемент <code>doc</code> был исключен как не входящий в область подсчета. Выделим множества пересчитываемых узлов, предшествующих нумеруемым элементам (рис. 8.9).</p>
      <image l:href="#img_66.png"/>
      <p><strong>Рис. 8.9</strong>. Третий шаг вычисления номера</p>
      <p>В этом примере элемент <code>chapter</code>, так же как и элемент <code>para</code>, будет иметь номер <code>2</code>. Соответственно, результатом выполнения инструкции <code>xsl:number</code> в этом случае будет строка</p>
      <p><code>     2.2.paragraph 14</code></p>
      <subtitle>Метод<emphasis> any</emphasis></subtitle>
      <p>Метод <code>any</code> используется для того, чтобы вычислить номер узла, основываясь на его позиции среди всех учитываемых узлов элемента.</p>
      <p>Областью нумерации этого метода будет множество всех узлов, следующих в порядке просмотра документа за первым предком текущего узла, который удовлетворяет паттерну, указанному в атрибуте <code>from</code>.</p>
      <p>Номер вычисляется как <code>1</code> плюс количество узлов области подсчета, удовлетворяющих паттерну <code>count</code> и предшествующих в порядке просмотра документа текущему узлу.</p>
      <subtitle>Пример</subtitle>
      <p>В качестве примера применения метода <code>any</code> вычислим порядковый номер элемента <code>para</code> среди всех элементов документа, начиная со второй главы. Инструкцию такого рода мы запишем в виде</p>
      <p><code>&lt;xsl:number</code></p>
      <p><code> format="     1."</code></p>
      <p><code> level="any"</code></p>
      <p><code> count="*"</code></p>
      <p><code> from="chapter[2]"/&gt;</code></p>
      <p>При ее выполнении мы сначала определим область, в которой будут подсчитываться узлы (обведены штрих-пунктирной линией на рис. 8.10).</p>
      <image l:href="#img_67.png"/>
      <empty-line/>
      <p><strong>Рис. 8.10</strong>. Определение области подсчета узлов</p>
      <p>Следующим шагом выделим подмножество области подсчета, предшествующее в порядке просмотра текущему узлу <code>para</code> (рис. 8.11).</p>
      <image l:href="#img_68.png"/>
      <p><strong>Рис. 8.11</strong>. Первый шаг вычисления номера</p>
      <p>Выделенное множество содержит 11 узлов, значит, искомый номер будет равен <code>12</code>.</p>
      <p>Перед тем, как перейти к рассмотрению способов форматирования номеров, приведем итоговый пример (листинг 8.34), в котором в шаблонах будут использоваться все три метода нумерации.</p>
      <subtitle>Листинг 8.34. Шаблон, использующий разные методы нумерации</subtitle>
      <p><code>&lt;xsl:stylesheet </code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"»</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="doc"&gt;</code></p>
      <p><code>  &lt;xsl:text&gt;Resulting document&amp;#xA;&lt;/xsl:text&gt;</code></p>
      <p><code>  &lt;xsl:text&gt;==================&amp;#xA;&lt;/xsl:text&gt;</code></p>
      <p><code>  &lt;xsl:apply-templates select="chapter"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="chapter"&gt;</code></p>
      <p><code>  &lt;xsl:number format="1. "/&gt;</code></p>
      <p><code>  &lt;xsl:value-of select="@title"/&gt;</code></p>
      <p><code>  &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
      <p><code>  &lt;xsl:apply-templates select="section"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="section"&gt;</code></p>
      <p><code>  &lt;xsl:number format="   1.1 "</code></p>
      <p><code>   level="multiple"</code></p>
      <p><code>   count="chapter|section"/&gt;</code></p>
      <p><code>  &lt;xsl:value-of select="@title"/&gt;</code></p>
      <p><code>  &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
      <p><code>  &lt;xsl:apply-templates select="para"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="para"&gt;</code></p>
      <p><code>  &lt;xsl:number</code></p>
      <p><code>   format="     a) "</code></p>
      <p><code>   level="any"</code></p>
      <p><code>   count="para"/&gt;</code></p>
      <p><code>  &lt;xsl:value-of select="."/&gt;</code></p>
      <p><code>  &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <p>Опишем словесно нумерацию, которая будет применяться в этом преобразовании.</p>
      <p>&#9633; Элементы <code>chapter</code> будут нумероваться в соответствии со своей позицией среди других элементов <code>chapter</code> того же уровня.</p>
      <p>&#9633; Элементы <code>section</code> будут нумероваться при помощи многоуровневой нумерации — номер будет состоять из номера элемента <code>chapter</code> и номера самого элемента <code>section</code>.</p>
      <p>&#9633; Элементы <code>para</code> будут нумероваться исходя из своей позиции среди всех остальных элементов <code>para</code> вне зависимости от того, на каких уровнях в документе они находятся.</p>
      <p>Результатом применения этого преобразования к документу, приведенному в листинге 8.31, будет следующий текст.</p>
      <subtitle>Листинг 8.35. Выходящий документ</subtitle>
      <p><code>Resulting document</code></p>
      <p><code>==================</code></p>
      <p><code>1. First chapter</code></p>
      <p><code>  1.1 First section</code></p>
      <p><code>     a) paragraph 1</code></p>
      <p><code>     b) paragraph 2</code></p>
      <p><code>     c) paragraph 3</code></p>
      <p><code>  1.2. Second section</code></p>
      <p><code>     d) paragraph 4</code></p>
      <p><code>     e) paragraph 5</code></p>
      <p><code>2. Second chapter</code></p>
      <p><code>  2.1 Third section</code></p>
      <p><code>     f) paragraph 6</code></p>
      <p><code>     g) paragraph 7</code></p>
      <p><code>     h) paragraph 8</code></p>
      <p><code>     i) paragraph 9</code></p>
      <p><code>  2.2 Forth section</code></p>
      <p><code>     j) paragraph 10</code></p>
      <p><code>     k) paragraph 11</code></p>
      <p><code>     l) paragraph 12</code></p>
      <p><code>  2.3 Fifth section</code></p>
      <p><code>     m) paragraph 13</code></p>
      <p><code>     n) paragraph 14</code></p>
      <p><code>     o) paragraph 15</code></p>
      <p><code>     p) paragraph 16</code></p>
      <p><code>3. Third chapter</code></p>
      <p><code>  3.1 Sixth section</code></p>
      <p><code>     q) paragraph 17</code></p>
      <p><code>     r) paragraph 18</code></p>
     </section>
     <section>
      <title>
       <p>Форматирование номеров</p>
      </title>
      <p>Возвращаясь немного назад, напомним, что результатом первого этапа выполнения <code>xsl:number</code> является список номеров, который может быть пустым или содержать одно или несколько чисел. Несложно увидеть, что количество номеров в этом списке будет зависеть от следующих условий.</p>
      <p>&#9633; Список номеров будет пустым, если в области нумерации не оказалось нумеруемых узлов.</p>
      <p>&#9633; Список номеров будет состоять не более чем из одного числа при использовании методов <code>single</code> и <code>any</code>.</p>
      <p>&#9633; Список номеров будет состоять из нуля или более чисел (по одному на каждый уровень нумерации) при использовании метода <code>multiple</code>.</p>
      <p>На этапе форматирования список номеров преобразуется в строку и вставляется результирующее дерево в виде текстового узла.</p>
      <p>Преобразование номеров из списка в строку имеет совершенно иной характер, нежели чем приведение числа к строковому типу. При форматировании номера нужно получить не просто строковое представление числа, здесь требуется сгенерировать значащий текстовый индекс, который совершенно необязательно должен иметь цифровую запись.</p>
      <p>Форматирование списка номеров производится в соответствии со значениями атрибутов <code>format</code>, <code>lang</code>, <code>letter-value</code>, <code>grouping-separator</code> и <code>grouping-size</code>, назначение и использование которых мы и будем разбирать в этом разделе.</p>
      <p>Основным атрибутом форматирования является атрибут <code>format</code>, который содержит последовательность форматирующих токенов. Каждый форматирующий токен состоит из букв и цифр; он определяет процедуру форматирования для каждого числа из списка форматируемых номеров. В значении атрибута <code>format</code> форматирующие токены отделяются друг от друга сочетаниями символов, которые не являются буквами и цифрами. Такие сочетания называются разделяющими последовательностями. При форматировании они остаются в строковом выражении номера без изменений.</p>
      <subtitle>Пример</subtitle>
      <p>В примере к методу <code>multiple</code> мы использовали следующий элемент <code>xsl:number</code>:</p>
      <p><code>&lt;xsl:number</code></p>
      <p><code> format="     1.1."</code></p>
      <p><code> level="multiple"</code></p>
      <p><code> count="doc|chapter|para"</code></p>
      <p><code> from="doc"/&gt;</code></p>
      <p>Разберем строение атрибута <code>format</code> этого элемента (на рис. 8.12 пробелы обозначены символами "<code>&#9633;</code>"):</p>
      <image l:href="#img_69.png"/>
      <p><strong>Рис. 8.12</strong>. Строение атрибута <code>format</code> элемента <code>xsl:number</code></p>
      <p>Список номеров в том примере состоял из номера элемента <code>chapter</code> (числа 2) и номера элемента <code>para</code> (тоже 2). Номер, генерируемый элементом <code>xsl:number</code>, будет состоять из:</p>
      <p>&#9633; разделяющей последовательности "<code>&#9633;&#9633;&#9633;&#9633;&#9633;</code>", которая будет скопирована, как есть;</p>
      <p>&#9633; числа <code>2</code>, которое получается в результате форматирования номера 2 форматирующим токеном "<code>1</code>";</p>
      <p>&#9633; разделяющего символа "<code>.</code>";</p>
      <p>&#9633; числа <code>2</code>, которое получается в результате форматирования номера 2 вторым форматирующим токеном "<code>1</code>";</p>
      <p>&#9633; разделяющего символа "<code>.</code>".</p>
      <p>Объединив все эти части, мы получим отформатированный номер "<code>&#9633;&#9633;&#9633;&#9633;&#9633;2.2</code>".</p>
      <p>Несложно заметить, что главную роль при преобразовании списка номеров в их строковое представление играют форматирующие токены. Каждый такой токен преобразовывает соответствующий ему номер в строку. В табл. 8.3 мы приведем описания этих преобразований.</p>
      <empty-line/>
      <p><emphasis><strong>Таблица 8.3</strong>. Форматирующие токены</emphasis></p>
      <table>
       <tr>
        <th rowspan="2" align="left">Токен</th>
        <th rowspan="2" align="left">Описание</th>
        <th colspan="2" align="left">Примеры</th>
       </tr>
       <tr>
        <th>Токен</th>
        <th align="left">Преобразование</th>
       </tr>
       <tr>
        <td rowspan="5" align="left"><code>1</code></td>
        <td rowspan="5" align="left">Форматирует номер в виде строкового представления десятичного числа</td>
        <td align="left"><code>1</code></td>
        <td align="left"><code>1 </code>&#8594;<code> '1'</code></td>
       </tr>
       <tr>
        <td align="left"><code>1</code></td>
        <td align="left"><code>2 </code>&#8594;<code> '2'</code></td>
       </tr>
       <tr>
        <td align="left"><code>1</code></td>
        <td align="left"><code>10 </code>&#8594;<code> '10'</code></td>
       </tr>
       <tr>
        <td align="left"><code>1</code></td>
        <td align="left"><code>999 </code>&#8594;<code> '999'</code></td>
       </tr>
       <tr>
        <td align="left"><code>1</code></td>
        <td align="left"><code>1000 </code>&#8594;<code> '1000'</code></td>
       </tr>
       <tr>
        <td rowspan="5" align="left"><code>0...01</code></td>
        <td rowspan="5" align="left">Форматирует номер в виде строкового представления десятичного числа; если получившая строка короче токена, она дополняется предшествующими нулями</td>
        <td align="left"><code>0001</code></td>
        <td align="left"><code>1 </code>&#8594;<code> '0001'</code></td>
       </tr>
       <tr>
        <td align="left"><code>001</code></td>
        <td align="left"><code>2 </code>&#8594;<code> '002'</code></td>
       </tr>
       <tr>
        <td align="left"><code>001</code></td>
        <td align="left"><code>10 </code>&#8594;<code> '010'</code></td>
       </tr>
       <tr>
        <td align="left"><code>01</code></td>
        <td align="left"><code>999 </code>&#8594;<code> '999'</code></td>
       </tr>
       <tr>
        <td align="left"><code>00001</code></td>
        <td align="left"><code>1000 </code>&#8594;<code> '01000'</code></td>
       </tr>
       <tr>
        <td rowspan="6" align="left"><code>A</code></td>
        <td rowspan="6" align="left">Форматирует номер в виде последовательности заглавных букв латинского алфавита</td>
        <td align="left"><code>A</code></td>
        <td align="left"><code>1 </code>&#8594;<code> 'A'</code></td>
       </tr>
       <tr>
        <td align="left"><code>A</code></td>
        <td align="left"><code>2 </code>&#8594;<code> 'B'</code></td>
       </tr>
       <tr>
        <td align="left"><code>A</code></td>
        <td align="left"><code>10 </code>&#8594;<code> 'J'</code></td>
       </tr>
       <tr>
        <td align="left"><code>A</code></td>
        <td align="left"><code>27 </code>&#8594;<code> 'AA'</code></td>
       </tr>
       <tr>
        <td align="left"><code>A</code></td>
        <td align="left"><code>999 </code>&#8594;<code> 'ALK'</code></td>
       </tr>
       <tr>
        <td align="left"><code>A</code></td>
        <td align="left"><code>1000 </code>&#8594;<code> 'ALL'</code></td>
       </tr>
       <tr>
        <td rowspan="6" align="left"><code>a</code></td>
        <td rowspan="6" align="left">Форматирует номер в виде последовательности строчных букв латинского алфавита</td>
        <td align="left"><code>a</code></td>
        <td align="left"><code>1 </code>&#8594;<code> 'a'</code></td>
       </tr>
       <tr>
        <td align="left"><code>a</code></td>
        <td align="left"><code>2 </code>&#8594;<code> 'b'</code></td>
       </tr>
       <tr>
        <td align="left"><code>a</code></td>
        <td align="left"><code>10 </code>&#8594;<code> 'j'</code></td>
       </tr>
       <tr>
        <td align="left"><code>a</code></td>
        <td align="left"><code>27 </code>&#8594;<code> 'aa'</code></td>
       </tr>
       <tr>
        <td align="left"><code>a</code></td>
        <td align="left"><code>999 </code>&#8594;<code> 'alk'</code></td>
       </tr>
       <tr>
        <td align="left"><code>a</code></td>
        <td align="left"><code>1000 </code>&#8594;<code> 'all'</code></td>
       </tr>
       <tr>
        <td rowspan="6" align="left"><code>I</code></td>
        <td rowspan="6" align="left">Форматирует номер заглавными римскими цифрами</td>
        <td align="left"><code>I</code></td>
        <td align="left"><code>1 </code>&#8594;<code> 'I'</code></td>
       </tr>
       <tr>
        <td align="left"><code>I</code></td>
        <td align="left"><code>2 </code>&#8594;<code> 'II'</code></td>
       </tr>
       <tr>
        <td align="left"><code>I</code></td>
        <td align="left"><code>10 </code>&#8594;<code> 'X'</code></td>
       </tr>
       <tr>
        <td align="left"><code>I</code></td>
        <td align="left"><code>27 </code>&#8594;<code> 'XXVII'</code></td>
       </tr>
       <tr>
        <td align="left"><code>I</code></td>
        <td align="left"><code>999 </code>&#8594;<code> 'IM'</code></td>
       </tr>
       <tr>
        <td align="left"><code>I</code></td>
        <td align="left"><code>1000 </code>&#8594;<code> 'M'</code></td>
       </tr>
       <tr>
        <td rowspan="6" align="left"><code>i</code></td>
        <td rowspan="6" align="left">Форматирует номер строчными римскими цифрами</td>
        <td align="left"><code>i</code></td>
        <td align="left"><code>1 </code>&#8594;<code> 'i'</code></td>
       </tr>
       <tr>
        <td align="left"><code>i</code></td>
        <td align="left"><code>2 </code>&#8594;<code> 'ii'</code></td>
       </tr>
       <tr>
        <td align="left"><code>i</code></td>
        <td align="left"><code>10 </code>&#8594;<code> 'x'</code></td>
       </tr>
       <tr>
        <td align="left"><code>i</code></td>
        <td align="left"><code>27 </code>&#8594;<code> 'xxvii'</code></td>
       </tr>
       <tr>
        <td align="left"><code>i</code></td>
        <td align="left"><code>999 </code>&#8594;<code> 'im'</code></td>
       </tr>
       <tr>
        <td align="left"><code>i</code></td>
        <td align="left"><code>1000 </code>&#8594;<code> 'm'</code></td>
       </tr>
       <tr>
        <td rowspan="6" align="left">Другой</td>
        <td rowspan="6" align="left">Форматирует номер <code>k</code> как <code>k</code>-й член последовательности, начинающейся этим токеном. Если нумерация таким токеном не поддерживается, вместо него используется токен <code>1</code>.</td>
        <td align="left">Не поддерживающийся токен</td>
        <td align="left"><code>1 </code>&#8594;<code> '1'</code></td>
       </tr>
       <tr>
        <td align="left"><code>b</code></td>
        <td align="left"><code>10 </code>&#8594;<code> 'k'</code></td>
       </tr>
       <tr>
        <td align="left"><code>Б</code></td>
        <td align="left"><code>2 </code>&#8594;<code> 'В'</code></td>
       </tr>
       <tr>
        <td align="left"><code>Б</code></td>
        <td align="left"><code>27 </code>&#8594;<code> 'Ы'</code></td>
       </tr>
       <tr>
        <td align="left"><code>&#225;</code></td>
        <td align="left"><code>999 </code>&#8594;<code> '&#945;&#957;&#968;'</code></td>
       </tr>
       <tr>
        <td align="left"><code>&#229;</code></td>
        <td align="left"><code>1000 </code>&#8594;<code> '&#946;&#950;&#959;'</code></td>
       </tr>
      </table>
      <p>При использовании алфавитной нумерации процессор может учитывать значение атрибута <code>lang</code> элемента <code>xsl:number</code> для того, чтобы использовать буквы алфавита соответствующего языка. Однако на практике возможность эта поддерживается очень слабо: большинство процессоров поддерживают алфавитную нумерацию только с использованием латиницы. Поэтому для того, чтобы использовать при алфавитной нумерации кириллицу, вместо атрибута <code>lang</code> следует использовать форматирующие токены "<code>&amp;#x410;</code>" (русская заглавная буква "<code>А</code>") и "<code>&amp;#х430;</code>" (русская строчная буква "<code>а</code>").</p>
      <subtitle>Пример</subtitle>
      <p>Для форматирования номеров в последовательности <code>1.1.a</code>, <code>1.1.б</code>, <code>1.1.в</code>, …, <code>1.2.а</code> и так далее можно использовать объявление вида:</p>
      <p><code>&lt;xsl:number</code></p>
      <p><code> format="1.&amp;#х430;"</code></p>
      <p><code> level="multiple"</code></p>
      <p><code> count="chapter|section"</code></p>
      <p><code> from="doc"/&gt;</code></p>
      <p>Представим теперь себе следующую ситуацию: нам нужно начать нумерацию с латинской буквы <code>i</code> для того, чтобы получить последовательность номеров вида <code>i</code>, <code>j</code>, <code>k</code>, <code>l</code>, <code>m</code> и так далее. Первое, что приходит в голову — это запись вида</p>
      <p><code>&lt;xsl:number format="i" ... /&gt;</code></p>
      <p>Однако вместо требуемой последовательности мы получим последовательность строчных римских цифр: <code>i</code>, <code>ii</code>, <code>iii</code> и так далее. Иными словами, некоторые форматирующие токены определяют нумерующую последовательность двусмысленно: одним вариантом является алфавитная последовательность, начинающаяся этим токеном, другим — некая традиционная для данного языка (например, последовательность римских цифр для английского).Для того чтобы различать эти последовательности в двусмысленных ситуациях, в <code>xsl:number</code> существует атрибут <code>letter-value</code>. Если его значением является <code>"alphabetic"</code>, нумерующая последовательность является алфавитной, значение <code>"traditional"</code> указывает на то, что следует использовать традиционный для данного языка способ. Если атрибут <code>letter-value</code> опущен, процессор может сам выбирать между алфавитным и традиционным способами нумерации.</p>
      <p>При использовании цифровых форматов нумерации (иными словами, токенов вида <code>1</code>, <code>01</code>, <code>001</code> и так далее) цифры в номере можно разделить на группы, получив, например, такие номера как "<code>2.00.00</code>" из <code>20000</code> или "<code>0-0-0-2</code>" из 2. Для этой цели в <code>xsl:number</code> используется пара атрибутов <code>grouping-separator</code> и <code>grouping-size</code>.</p>
      <p>Атрибут <code>grouping-separator</code> задает символ, который следует использовать для разбивки номера на группы цифр, в то время как <code>grouping-size</code> указывает размер группы. Эти атрибуты всегда должны быть вместе — если хотя бы один из них опущен, второй просто игнорируется.</p>
      <subtitle>Пример</subtitle>
      <p>Элемент <code>xsl:number</code> вида</p>
      <p><code>&lt;xsl:number</code></p>
      <p><code> format="[00000001]"</code></p>
      <p><code> grouping-separator="."</code></p>
      <p><code> grouping-size="2"/&gt;</code></p>
      <p>будет генерировать номера в следующей последовательности:</p>
      <p><code>1 </code>&#8594;<code> '[00.00.00.01]'</code></p>
      <p><code>2 </code>&#8594;<code> '[00.00.00.02]'</code></p>
      <p><code>...</code></p>
      <p><code>999 </code>&#8594;<code> '[00.00.09.99]'</code></p>
      <p><code>1000 </code>&#8594;<code> '[00.00.10.00]'</code></p>
      <p>Пожалуй, следует упомянуть, что в значениях атрибутов <code>format</code>, <code>lang</code>, l<code>etter-value</code>, <code>grouping-size</code> и <code>grouping-separator</code> могут быть указаны шаблоны значений, иными словами могут использоваться выражения в фигурных скобках. Это может быть полезно, например, для того, чтобы сгенерировать форматирующие токены во время выполнения преобразования.</p>
      <subtitle>Пример</subtitle>
      <p>В следующем шаблоне формат номера секции зависит от значения атрибута <code>format</code> ее родительского узла:</p>
      <p><code>&lt;xsl:template match="section"&gt;</code></p>
      <p><code> &lt;xsl:number</code></p>
      <p><code>  format="{../@format}-1 "</code></p>
      <p><code>  level="multiple"</code></p>
      <p><code>  count="chapter|section"/&gt;</code></p>
      <p><code> &lt;xsl:value-of select="@title"/&gt;</code></p>
      <p><code>&lt;/xsl:template&gt;</code></p>
      <p>При обработке входящего документа</p>
      <p><code>&lt;doc&gt;</code></p>
      <p><code> &lt;chapter format="I" title="First Chapter"&gt;</code></p>
      <p><code>  &lt;section title="First Section"/&gt;</code></p>
      <p><code>  &lt;section title="Second Section"/&gt;</code></p>
      <p><code>  &lt;section title="Third Section"/&gt;</code></p>
      <p><code> &lt;/chapter&gt;</code></p>
      <p><code>&lt;/doc&gt;</code></p>
      <p>нумерация секций будет выглядеть как</p>
      <p><code>I-1 First Section</code></p>
      <p><code>I-2 Second Section</code></p>
      <p><code>I-3 Third Section</code></p>
      <p>Если же атрибут <code>format</code> элемента <code>chapter</code> будет иметь значение <code>1</code>, секции будут пронумерованы в виде</p>
      <p><code>1-1 First Section</code></p>
      <p><code>1-2 Second Section</code></p>
      <p><code>1-3 Third Section</code></p>
     </section>
    </section>
   </section>
   <section>
    <title>
     <p>Форматирование чисел</p>
    </title>
    <section>
     <p>Мы уже познакомились с функцией языка XPath <code>string</code>, которая конвертирует свой аргумент в строку. Эта функция может преобразовать в строку и численное значение, но возможности ее при этом сильно ограничены.</p>
     <p>К счастью, XSLT предоставляет мощные возможности для форматирования строкового представления чисел при помощи функции <code>format-number</code> и элемента <code>xsl:decimal-format</code>.</p>
    </section>
    <section>
     <title>
      <p>Функция <emphasis>format-number</emphasis></p>
     </title>
     <p>Запись функции имеет следующий вид:</p>
     <p><code><emphasis>string </emphasis><strong>format-number</strong>(<emphasis>number</emphasis>, <emphasis>string</emphasis>, <emphasis>string</emphasis>?)</code></p>
     <p>Функция <code>format-number</code> принимает на вход три параметра. Первым параметром является число, которое необходимо преобразовать в строку, применив при этом форматирование. Вторым параметром является образец, в соответствии с которым будет форматироваться число. Третий параметр указывает название десятичного формата, который следует применять.</p>
     <p>Образец форматирования в XSLT определяется точно так же, как в классе <code>DecimalFormat</code> языка Java. Для того чтобы читателю, не знакомому с Java, не пришлось изучать документацию этого языка, мы приведем полный синтаксис образцов форматирования. Продукции образца форматирования мы будем помечать номерами с префиксом <code>NF</code>, чтобы не путать их с другими продукциями.</p>
     <p>Прежде всего, образец форматирования может состоять из двух частей: первая часть определяет форматирование положительного числа, вторая часть — отрицательного. Запишем это в виде EBNF-продукции:</p>
     <p><code>[NF 1] NFPattern ::= NFSubpattern (NFSubpatternDelim NFSubpattern)?</code></p>
     <p>Двум частям образца форматирования соответствуют нетерминалы <code>NFSubpattern</code>, которые разделены нетерминалом <code>NFSubpatternDelim</code>.</p>
     <p>В случае если вторая часть образца форматирования опушена, отрицательные числа форматируются точно так же, как и положительные, но им предшествует префикс отрицательного числа (по умолчанию — знак "минус", "<code>-</code>").</p>
     <subtitle>Примеры</subtitle>
     <p><code>format-number(1234.567,'#.00;negative #.00') </code>&#8594;<code> '1234.57'</code></p>
     <p><code>format-number(-1234.567,'#.00/negative #.00') </code>&#8594;<code> 'negative 1234.57'</code></p>
     <p><code>format-number(-1234.567,'#.00') </code>&#8594;<code> '-1234.57'</code></p>
     <p>Каждая из частей образца форматирования состоит из префикса (<code>NFPrefix</code>), целой части (<code>NFInteger</code>), необязательной дробной части (<code>NFFractional</code>) и суффикса (<code>NFSuffix</code>).</p>
     <p><code>[NF 2] NFSubpattern ::= NFPrefix NFinteger NFFractional? NFSuffix</code></p>
     <p>Префикс или суффикс образца форматирования могут содержать символ процента. Если суффикс содержит символ процента, число должно быть умножено на <code>100</code> и выведено со знаком процента. Наличие символа процента в префиксе на форматирование не влияет.</p>
     <subtitle>Пример</subtitle>
     <p><code>format-number(0.45,'0.00%') </code>&#8594;<code> '45.00%'</code></p>
     <p><code>format-number(0.45,'0.##%') </code>&#8594;<code> '45.00%'</code></p>
     <p><code>format-number(0.45678,'%0.00') </code>&#8594;<code> '%0.46'</code></p>
     <p><code>format-number(0.45678,'0.####%') </code>&#8594;<code> '45.678%'</code></p>
     <p>Префикс задает строку, которая будет предшествовать числу, это может быть последовательность любых неформатирующих символов (<code>NFChar</code>) плюс символ процента (<code>NFPercent</code>). Аналогично, суффикс будет следовать за числом, и он тоже не может содержать форматирующих символов (за исключением символа процента).</p>
     <p><code>[NF 3] NFPrefix ::= (NFChar NFPercent?)*</code></p>
     <p><code>[NF 4] NFSuffix ::= (NFChar NFPercent?)*</code></p>
     <subtitle>Пример</subtitle>
     <p>Если мы хотим заключить наше число, к примеру, в квадратные скобки, мы должны будем включить в его образец форматирования префикс "<code>[</code>" и суффикс "<code>]</code>":</p>
     <p><code>format-number(123456, '[#]') </code>&#8594;<code> '[123456]'</code></p>
     <p>Нетерминал <code>NFinteger</code> определяет, как будет выглядеть целая часть числа. Он начинается несколькими символами <code>NFOptDigit</code> (по умолчанию "<code>#</code>"), показывающими позиции, в которых цифры необязательны, и состоит из символов <code>NFReqDigit</code> (по умолчанию "<code>0</code>"), показывающих позиции обязательных цифр, а также символа <code>NFGroupDelim</code> (по умолчанию "<code>,</code>"), показывающего позицию символа-разделителя групп цифр.</p>
     <p><code>[NF 5] NFInteger ::= NFOptDigit*</code></p>
     <p><code>                     (NFReqDigit* NFGroupDelim</code></p>
     <p><code>                     | NFGroupDelim NFOptDigit*)?</code></p>
     <p><code>                     NFReqDigit+</code></p>
     <subtitle>Примеры</subtitle>
     <p><code>format-number(1234.56,'#0000') </code>&#8594;<code> '1235'</code></p>
     <p><code>format-number(1234.56,'00000') </code>&#8594;<code> '01235'</code></p>
     <p><code>format-number(1234.56,'00,000') </code>&#8594;<code> '01,235'</code></p>
     <p><code>format-number(1234.56,'000,00') </code>&#8594;<code> '0,12,35'</code></p>
     <cite>
      <subtitle>Замечание</subtitle>
      <p>Некоторые процессоры позволяют указывать несколько символов-разделителей. Однако даже в этом случае они учитывают только последний из этих символов.</p>
     </cite>
     <subtitle>Пример</subtitle>
     <p><code>format-number(123456789.0123,'0000,000,00') </code>&#8594;<code> '1,23,45,67,89'</code></p>
     <p>Дробная часть числа, представленная нетерминалом <code>NFFraction</code>, начинается символом-разделителем целой и дробной части <code>NFFractionDelim</code> (по умолчанию "<code>.</code>"), продолжается последовательностью символов обязательных позиций цифр <code>NFReqDigit</code> и заканчивается последовательностью символов необязательных позиций <code>NFOptDigit</code>:</p>
     <p><code>[NF 6] NFFraction ::= NFFractionDelim NFReqDigit* NFOptDigit*</code></p>
     <subtitle>Примеры</subtitle>
     <p><code>format-number(1234.567,'#.00') </code>&#8594;<code> '1234.57'</code></p>
     <p><code>format-number(1234.567,'#.00#') </code>&#8594;<code> '1234.567'</code></p>
     <p><code>format-number(1234.567,'#.0000') </code>&#8594;<code> '1234.5670'</code></p>
     <p>Продукция <code>NFChar</code>, использующаяся при определении префикса (<code>NFPrefix</code>) и суффикса (<code>NFSuffix</code>), может содержать любые неформатирующие символы:</p>
     <p><code>[NF 7] NFChar ::= (Char - NFSymbol)</code></p>
     <p>К специальным форматирующим символам относятся следующие:</p>
     <p>&#9633; символ обязательной позиции цифры (по умолчанию "<code>0</code>");</p>
     <p>&#9633; символ необязательной позиции цифры (по умолчанию "<code>#</code>");</p>
     <p>&#9633; символ-разделитель образцов форматирования для положительного и отрицательного числа (по умолчанию "<code>;</code>");</p>
     <p>&#9633; символ-разделитель целой и дробной части (по умолчанию "<code>.</code>");</p>
     <p>&#9633; символ процента (по умолчанию "<code>%</code>").</p>
     <p>Перечислим их продукции:</p>
     <p><code>[NF 8] NFSymbol           ::= NFReqDigit</code></p>
     <p><code>                              | NFOptDigit</code></p>
     <p><code>                              | NFSubpatternDelim</code></p>
     <p><code>                              | NFFractionDelim</code></p>
     <p><code>                              | NFGroupDelim</code></p>
     <p><code>                              | NFPercent</code></p>
     <p><code>[NF 9] NFReqDigit         ::= '0'</code></p>
     <p><code>[NF 10] NFOptDigit        ::= '#'</code></p>
     <p><code>[NF 11] NFSubpatternDelim ::= ';'</code></p>
     <p><code>[NF 12] NFFractionDelim   ::= '.'</code></p>
     <p><code>[NF 13] NFGroupDelim      ::= ','</code></p>
     <p><code>[NF 14] NFPercent         ::= '%'</code></p>
     <p>Синтаксические правила, которые мы привели выше, пока не являются стандартными. Они корректно передают синтаксис образца форматирования, но являются более строгими, чем определения в документации языка Java.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:decimal-format</emphasis></p>
     </title>
     <p>Синтаксис элемента задан конструкцией вида:</p>
     <p><code>&lt;xsl:decimal-format</code></p>
     <p><code> name="<emphasis>имя</emphasis>"</code></p>
     <p><code> decimal-separator="<emphasis>символ</emphasis>"</code></p>
     <p><code> grouping-separator="<emphasis>символ</emphasis>"</code></p>
     <p><code> infinity="<emphasis>строка</emphasis>"</code></p>
     <p><code> minus-sign="<emphasis>символ</emphasis>"</code></p>
     <p><code> NaN="<emphasis>строка</emphasis>"</code></p>
     <p><code> percent="<emphasis>символ</emphasis>"</code></p>
     <p><code> per-mille="<emphasis>символ</emphasis>"</code></p>
     <p><code> zero-digit="<emphasis>символ</emphasis>"</code></p>
     <p><code> digit="<emphasis>символ</emphasis>"</code></p>
     <p><code> pattern-sераrator="<emphasis>символ</emphasis>"/&gt;</code></p>
     <p>XSLT позволяет изменять специальные символы, влияющие на форматирование строки. Именованный набор таких символов и некоторых других указаний называется десятичным форматом и определяется элементом <code>xsl:decimal-format</code>. От атрибутов этого элемента зависит, как будут обрабатываться символы образца форматирования и как число будет отображаться на выходе:</p>
     <p>Атрибут <code>name</code> элемента <code>xsl:decimal-format</code> задает расширенное имя десятичного формата. Если имя не указано, это означает, что элемент <code>xsl:decimal-format</code> определяет десятичный формат по умолчанию.</p>
     <p>Остальные атрибуты контролируют интерпретацию форматирующего образца и вывод строкового представления числа следующим образом:</p>
     <p>&#9633; <code>decimal-separator</code> — задает символ, разделяющий целую и дробную части числа. Значением этого атрибута по умолчанию является символ "<code>.</code>", с Unicode-кодом <code>#x2e</code>. Атрибут <code>decimal-separator</code> рассматривается как специальный символ образца форматирования. Кроме того, он будет использован как разделяющий символ при выводе;</p>
     <p>&#9633; <code>grouping-separator</code> — задает символ, группирующий цифры в целой части записи числа. Такие символы используются, например, для группировки тысяч ("<code>1,234,567.89</code>"). Значением по умолчанию является символ "<code>,</code>", код <code>#x2c</code>. <code>grouping-separator</code> рассматривается как специальный символ образца форматирования. Помимо этого, он будет использован как разделяющий символ групп цифр при выводе числа;</p>
     <p>&#9633; <code>percent</code> — задает символ процента. Значением по умолчанию является символ "<code>%</code>", код <code>#x25</code>. Этот символ будет распознаваться в образце форматирования и использоваться при выводе;</p>
     <p>&#9633; <code>per-mille</code> — задает символ промилле. Значением по умолчанию является символ "<code>‰</code>", код <code>#х2030</code>. Символ промилле распознается в образце форматирования и используется в строковом представлении числа;</p>
     <p>&#9633; <code>zero-digit</code> — задает символ нуля. Значением по умолчанию является символ "<code>0</code>", код <code>#x30;</code>. В качестве цифр при отображении числа будут использоваться символ нуля и 9 символов, следующих за ним. Символ нуля распознается в образце форматирования и используется при выводе строкового представления числа;</p>
     <p>&#9633; <code>digit</code> — определяет символ, который используется в образце форматирования для определения позиции необязательного символа. Значением по умолчанию является символ "<code>#</code>". Этот символ распознается как форматирующий символ необязательной цифры. Он не включается в строковое представление числа;</p>
     <p>&#9633; <code>pattern-separator</code> — определяет символ, который используется в образце форматирования для разделения положительного и отрицательного форматов числа. Он не включается в строковое представление числа. Значением этого атрибута по умолчанию является символ "<code>;</code>";</p>
     <p>&#9633; <code>infinity</code> — задает строку, которая будет представлять бесконечность. Значением по умолчанию является строка "<code>Infinity</code>";</p>
     <p>&#9633; <code>NaN</code> — задает строку, которая будет представлять не-числа. Значением по умолчанию является строка "<code>NaN</code>";</p>
     <p>&#9633; <code>minus-sign</code> — задает символ, который будет использоваться для обозначения отрицательных чисел. Значением по умолчанию является символ "<code>-</code>", код <code>#x2D</code>.</p>
     <p>Элемент <code>xsl:decimal-format</code> не имеет смысла без функции <code>format-number</code>. Все, на что влияют его атрибуты — это формат, который будет использоваться при преобразовании чисел в строку функцией <code>format-number</code>.</p>
     <subtitle>Примеры</subtitle>
     <p>Определение десятичного формата:</p>
     <p><code>&lt;xsl:decimal-format</code></p>
     <p><code> name="format1"</code></p>
     <p><code> decimal-separator=","</code></p>
     <p><code> minus-sign="N"</code></p>
     <p><code> grouping-separator=":"</code></p>
     <p><code> infinity="&amp;#x221E;"</code></p>
     <p><code> NaN="not-a-number"</code></p>
     <p><code> percent="%"</code></p>
     <p><code> digit="$"</code></p>
     <p><code> pattern-separator="|"/&gt;</code></p>
     <p>Примеры функций <code>format-number</code>:</p>
     <p><code>format-number(123456.78, '$,0000', 'format1) </code>&#8594;<code> '123456,7800'</code></p>
     <p><code>format-number(-123456.78, '$,00$$', 'format1') </code>&#8594;<code> 'N123456,78'</code></p>
     <p><code>format-number(123456.78, '$,0000|$,0000-', 'format1') </code>&#8594;<code> '123456,7800'</code></p>
     <p><code>format-number(-123456.78, '$,00001$,0000-', 'format1') </code>&#8594;<code> '123456,7800-'</code></p>
     <p><code>format-number(-123456.78, '000:000:000,00$$', 'format1') </code>&#8594;<code> 'N000:123:456,78'</code></p>
     <p><code>format-number('zero', '000:000:000,00$$', 'format1') -&gt; 'not-a-number'</code></p>
     <p><code>format-number(1 div 0, '$,$', 'format1') </code>&#8594;<code> '&#8734;'</code></p>
     <p><code>format-number(-1 div 0, '$,$', 'format1') </code>&#8594;<code> 'N&#8734;'</code></p>
     <p>Определение десятичного формата:</p>
     <p><code>&lt;xsl:decimal-format name="format2" zero-digit="/"/&gt;</code></p>
     <p>Примеры функций <code>format-number</code>:</p>
     <p><code>format-number(123456789, '#', 'format2') </code>&#8594;<code> '012345678'</code></p>
     <p><code>format-number(123456789, '#') </code>&#8594;<code> '123456780'</code></p>
     <p>Определение десятичного формата:</p>
     <p><code>&lt;xsl:decimal-format name="format3" zero-digit="1"/&gt;</code></p>
     <p>Примеры функций <code>format-number</code>:</p>
     <p><code>format-number(123456789, '#', 'format3') </code>&#8594;<code> '23456789:'</code></p>
     <p><code>format-number(12345.06789, '#.#####', 'format3') </code>&#8594;<code> '23456.1789:'</code></p>
     <p>Десятичный формат, определяемый элементом <code>xsl:decimal-format</code>, в отличие от многих других элементов не может переопределяться в преобразованиях со старшим порядком импорта. Элементы <code>xsl:decimal-format</code> должны определять десятичные форматы с различными именами (за исключением тех случаев, когда значения их атрибутов полностью совпадают).</p>
    </section>
   </section>
   <section>
    <title>
     <p>Контроль вывода документа</p>
    </title>
    <section>
     <p>Несмотря на то, что XSLT-процессоры должны лишь только преобразовывать логические модели документов, организованные в виде деревьев, многие из них имеют также возможность выдавать результат преобразования в виде последовательности символов.</p>
    </section>
    <section>
     <title>
      <p>Элемент <emphasis>xsl:output</emphasis></p>
     </title>
     <section>
      <p>Синтаксис этого элемента приведен ниже:</p>
      <p><code>&lt;xsl:output</code></p>
      <p><code> method = "xml" | "html" | "text" | "<emphasis>имя</emphasis>"</code></p>
      <p><code> version = "<emphasis>токен</emphasis>"</code></p>
      <p><code> encoding = "<emphasis>строка</emphasis>"</code></p>
      <p><code> omit-xml-declaration = "yes" | "no"</code></p>
      <p><code> standalone = "yes" | "no"</code></p>
      <p><code> doctype-public = "<emphasis>строка</emphasis>"</code></p>
      <p><code> doctype-system = "<emphasis>строка</emphasis>"</code></p>
      <p><code> cdata-section-elements = "<emphasis>имена</emphasis>"</code></p>
      <p><code> indent = "yes" | "no"</code></p>
      <p><code> media-type = "<emphasis>строка</emphasis>"/&gt;</code></p>
      <p>Элемент верхнего уровня <code>xsl:output</code> позволяет указывать, каким образом должно быть выведено результирующее дерево.</p>
      <p>Главным атрибутом элемента <code>xsl:output</code> является атрибут <code>method</code>, который определяет, какой метод должен использоваться для вывода документа. Значением этого атрибута может быть любое имя, но при этом техническая рекомендация XSLT определяет только три стандартных метода вывода — <code>"xml"</code>, <code>"html"</code> и <code>"text"</code>. В том случае, если процессор поддерживает нестандартный метод вывода, его реализация полностью зависит от производителя.</p>
      <p>Если в преобразовании не определен элемент <code>xsl:output</code> или в нем не указан атрибут <code>method</code>, метод преобразования выбирается по умолчанию исходя из следующих условий.</p>
      <p>&#9633; Если корень выходящего документа имеет дочерний элемент с локальным именем "<code>html</code>" (в любом регистре символов), которому предшествуют только пробельные символы, методом вывода по умолчанию становится <code>"html</code>".</p>
      <p>&#9633; Во всех остальных случаях методом вывода по умолчанию является <code>"xml"</code>.</p>
      <subtitle>Пример</subtitle>
      <p>Для документа</p>
      <p><code>&lt;HTML&gt;</code></p>
      <p><code> &lt;HEAD&gt;</code></p>
      <p><code>  &lt;TITLE&gt;XSL Transformations (XSLT)&lt;/TITLE&gt;</code></p>
      <p><code> &lt;/HEAD&gt;</code></p>
      <p><code> &lt;BODY&gt;</code></p>
      <p><code>  &lt;H1&gt;XSL Transformations (XSLT)&lt;BR/&gt;Version 1.0&lt;/H1&gt;</code></p>
      <p><code> &lt;/BODY&gt;</code></p>
      <p><code>&lt;/HTML&gt;</code></p>
      <p>Методом вывода по умолчанию будет <code>"html"</code>, а для документа</p>
      <p><code>&lt;BODY&gt;</code></p>
      <p><code> &lt;H1&gt;XSL Transformations (XSLT)&lt;BR/&gt;Version 1.0&lt;/H1&gt;</code></p>
      <p><code>&lt;/BODY&gt;</code></p>
      <p>будет выбран метод вывода <code>"xml"</code>.</p>
      <p>Помимо главного атрибута <code>method</code>, элемент <code>xsl:output</code> имеет следующие атрибуты:</p>
      <p>&#9633; <code>version</code> (версия) — определяет версию языка выходящего документа;</p>
      <p>&#9633; <code>indent</code> (индентация) — определяет, должен ли процессор добавлять пробельные символы для более наглядного форматирования документа;</p>
      <p>&#9633; <code>encoding</code> (кодировка) — определяет, в какой кодировке должен быть выведен документ. Значение этого атрибута не зависит от регистра символов, то есть значения <code>encoding="utf-8"</code> и <code>encoding="UtF-8"</code> будут эквивалентны. В атрибуте <code>encoding</code> можно использовать только печатаемые символы ASCII, то есть символы интервала от <code>#x21</code> до <code>#x7e</code>. Значением <code>encoding</code> должно быть название набора символов, определенное в стандартах IANA (Internet Assigned Numbers Authority) или RFC2278. В противном случае, атрибут должен начинаться символами "<code>x-</code>";</p>
      <p>&#9633; <code>media-type</code> — определяет тип содержимого MIME выходящего документа;</p>
      <p>&#9633; <code>doctype-system</code> — определяет системный идентификатор, который должен быть использован в декларации типа документа (DTD);</p>
      <p>&#9633; <code>doctype-public</code> — определяет публичный идентификатор, который должен быть использован в декларации типа документа (DTD);</p>
      <p>&#9633; <code>omit-xml-declaration</code> (пропустить декларацию XML) — определяет, нужно ли включать декларацию XML в выходящий документ или нет. Значением этого атрибута должно быть либо <code>"yes"</code> (пропустить декларацию), либо <code>"no"</code> (включить декларацию в выходящий документ);</p>
      <p>&#9633; <code>standalone</code> (самостоятельный документ) — определяет, должен ли процессор выводить указание на самостоятельность документа (standalone declaration). Значением этого атрибута может быть либо <code>"yes"</code> (выводить указание), либо <code>"no"</code> (не выводить указание на самостоятельность);</p>
      <p>&#9633; <code>cdata-section-elements</code> — определяет список элементов, текстовое содержимое которых должно быть выведено с использованием секций CDATA.</p>
      <p>Использование этих атрибутов зависит от того, какой из методов выбран для вывода преобразованного документа.</p>
     </section>
     <section>
      <title>
       <p>Метод вывода <emphasis>"xml"</emphasis></p>
      </title>
      <p>Для того чтобы вывести результирующее дерево в виде XML-документа, следует использовать в элементе <code>xsl:output</code> метод <code>"xml"</code>. Ниже мы подробно опишем, каким образом на выход должны влиять другие атрибуты этого элемента.</p>
      <subtitle>Атрибут <emphasis>version</emphasis></subtitle>
      <p>Этот атрибут определяет версию языка XML, которая должна использоваться для вывода результирующего документа. В случае если процессор не поддерживает указанную версию, он может либо выдать ошибку, либо использовать одну из поддерживаемых версий. На данный момент единственной действующей версией языка является версия 1.0 и потому, если в атрибуте в <code>version</code> будет указано другое значение, единственным эффектом от этого будет измененный параметр <code>version</code> в декларации XML.</p>
      <subtitle>Пример</subtitle>
      <p>Предположим, что в преобразовании версия выходящего документа задана как 1.2:</p>
      <p><code>&lt;xsl:output method="xml" version="1.2"/&gt;</code></p>
      <p>Тогда процессор может вывести декларацию XML в следующем виде:</p>
      <p><code>&lt;?xml version="1.2" encoding="utf-8"?&gt;</code></p>
      <p>Значением атрибута version по умолчанию является <code>"1.0"</code>, то есть, для того, чтобы получить декларацию XML вида</p>
      <p><code>&lt;?xml version="1.0" <emphasis>и т. д.</emphasis> ?&gt;</code></p>
      <p>достаточно опустить определение атрибута <code>version</code>:</p>
      <p><code>&lt;xsl:output method="xml"/&gt;</code></p>
      <subtitle>Атрибут <emphasis>encoding</emphasis></subtitle>
      <p>Атрибут <code>encoding</code> указывает на то, какая кодировка предпочтительна для выходящего документа. Множество кодировок зависит от используемого процессора, но при этом в соответствии с технической рекомендацией все они обязаны поддерживать Unicode-формы кодировок UTF-8 и UTF-16.</p>
      <p>В случае если процессор не поддерживает кодировку, указанную в атрибуте <code>encoding</code>, процессор может либо выдать ошибку, либо использовать UTF-8 или UTF-16.</p>
      <p>Если атрибут <code>encoding</code> опущен, процессор должен по умолчанию использовать UTF-8 или UTF-16. На практике абсолютное большинство процессоров используют по умолчанию кодировку UTF-8.</p>
      <p>При выводе содержимого выходящего документа может возникнуть ситуация, когда в выходящем потоке будут находиться символы, которые невозможно будет отобразить при используемой кодировке. В этом случае непечатаемые символы должны быть заменены символьными сущностями.</p>
      <subtitle>Пример</subtitle>
      <p>Представим себе входящий документ в кодировке UTF-8, содержащий символ кириллицы "<code>Э</code>" с Unicode-кодом <code>#x42d</code> (или <code>#1069</code> в десятичной системе счисления):</p>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;page&gt;Э&lt;/page&gt;</code></p>
      <p>Если преобразование будет использовать для вывода кодировку, которая не может отображать символы кириллического алфавита, например ISO-8859-1, то символ "<code>Э</code>" в выходящем документе должен быть заменен символьной сущностью.</p>
      <subtitle>Листинг 8.36. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:output</code></p>
      <p><code>  method="xml"</code></p>
      <p><code>  encoding="ISO-8859-1"</code></p>
      <p><code>  indent="yes"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="/"&gt;</code></p>
      <p><code>  &lt;xsl:copy-of select="/page"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 8.37. Выходящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;</code></p>
      <p><code>&lt;page&gt;&amp;#1069;&lt;/page&gt;</code></p>
      <p>Вместе с тем синтаксис XML не разрешает использовать символьные сущности в именах элементов и атрибутов, и наличие в них символов, не отображаемых кодировкой вывода, будет являться ошибкой. Если в предыдущем примере документ будет иметь вид</p>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;страница&gt;Э&lt;/страница&gt;</code></p>
      <p>то вывести результирующее дерево в кодировке ISO-8859-1 будет невозможно.</p>
      <subtitle>Атрибут<emphasis> indent</emphasis></subtitle>
      <p>Индентацией называют форматирование исходного текста, не влияющее на семантику, но облегчающее читаемость. К примеру, один и тот же XML-документ можно написать как</p>
      <p><code>&lt;A&gt;&lt;В&gt;&lt;С/&gt;&lt;/В&gt;&lt;С&gt;&lt;В&gt;&lt;/В&gt;&lt;/С&gt;&lt;/А&gt;</code></p>
      <p>или</p>
      <p><code>&lt;A&gt;</code></p>
      <p><code> &lt;B&gt;</code></p>
      <p><code>  &lt;C/&gt;</code></p>
      <p><code> &lt;/B&gt;</code></p>
      <p><code> &lt;C&gt;</code></p>
      <p><code>  &lt;B&gt;</code></p>
      <p><code>  &lt;/B&gt;</code></p>
      <p><code> &lt;/C&gt;</code></p>
      <p><code>&lt;/A&gt;</code></p>
      <p>Очевидно, что второй случай гораздо легче для понимания, поскольку в нем легко можно видеть принадлежность элементов одного другому. Подобное форматирование можно использовать и при выводе преобразованного документа при помощи атрибута <code>indent</code> элемента <code>xsl:output</code>. Если этот атрибут имеет значение <code>"yes"</code>, процессор может добавить один или несколько пробельных символов или символов перевода строки — в зависимости от реализации. Как правило, каждый дочерний элемент помещают на новой строке, добавляя впереди два пробела на каждый уровень вложенности.</p>
      <subtitle>Пример</subtitle>
      <subtitle>Листинг 8.38. Входящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;A&gt;&lt;B&gt;&lt;C/&gt;&lt;/B&gt;&lt;C&gt;&lt;B&gt;&lt;/В&gt;&lt;/C&gt;&lt;/A&gt;</code></p>
      <subtitle>Листинг 8.39. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:output indent="yes"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="/"&gt;</code></p>
      <p><code>  &lt;xsl:copy-of select="/"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 8.40. Выходящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;A&gt;</code></p>
      <p><code> &lt;B&gt;</code></p>
      <p><code>  &lt;C/&gt;</code></p>
      <p><code> &lt;/B&gt;</code></p>
      <p><code> &lt;C&gt;</code></p>
      <p><code>  &lt;B/&gt;</code></p>
      <p><code> &lt;/C&gt;</code></p>
      <p><code>&lt;/A&gt;</code></p>
      <p>Следует быть осторожными при использовании <code>indent="yes"</code> там, где в содержимом документа могут встречаться значащие пробелы. Индентация позволяет процессору при выводе документа добавлять пробельные символы по собственному усмотрению. В случаях, когда при последующей обработке преобразованного документа пробельные символы могут быть восприняты неадекватно, лучше индентацию не использовать.</p>
      <subtitle>Атрибут <emphasis>cdata-section-elements</emphasis></subtitle>
      <p>Для того чтобы вывести текстовое содержимое некоторых элементов в виде секций CDATA, XSLT предлагает простой механизм — следует лишь перечислить в атрибуте <code>cdata-section-elements</code> элемента <code>xsl:output</code> элементы, которые на выходе должны содержать секции символьных данных.</p>
      <subtitle>Пример</subtitle>
      <subtitle>Листинг 8.41. Входящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;page&gt;&amp;lt;br/&amp;gt;&lt;br/&gt;&lt;/page&gt;</code></p>
      <subtitle>Листинг 8.42. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:output</code></p>
      <p><code>  indent="yes"</code></p>
      <p><code>  cdata-section-elements="page"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="/"&gt;</code></p>
      <p><code>  &lt;xsl:copy-of select="/"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 8.43. Выходящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;page&gt;&lt;![CDATA[&lt;br/&gt;]]&gt;&lt;br/&gt;</code></p>
      <p><code>&lt;/page&gt;</code></p>
      <p>В соответствии с синтаксисом XML, секции CDATA не могут содержать последовательности символов "<code>]]&gt;</code>". Потому, встретив такую комбинацию в тексте элемента, имя которого включено в <code>cdata-section-elements</code>, процессор заменит ее двумя секциями CDATA. Одна будет содержать "<code>]]</code>", вторая – "<code>&gt;</code>".</p>
      <subtitle>Пример</subtitle>
      <subtitle>Листинг 8.44. Входящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;page&gt;</code></p>
      <p><code> &lt;data&gt;]]&amp;gt;&lt;/data&gt;</code></p>
      <p><code> &lt;pre&gt;&amp;lt;!-- Comment --&gt;&lt;/pre&gt;</code></p>
      <p><code>&lt;/page&gt;</code></p>
      <subtitle>Листинг 8.45. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:output</code></p>
      <p><code> indent="yes"</code></p>
      <p><code> cdata-section-elements="data pre"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="/"&gt;</code></p>
      <p><code>  &lt;xsl:copy-of select="/"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 8.46. Выходящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;page&gt;</code></p>
      <p><code> &lt;data&gt;&lt;![CDATA[]]]]&gt;&lt;![CDATA[&gt;]]&gt;&lt;/data&gt;</code></p>
      <p><code> &lt;pre&gt;&lt;![CDATA[&lt;!-- Comment --&gt;]]&gt;&lt;/pre&gt;</code></p>
      <p><code>&lt;/page&gt;</code></p>
      <subtitle>Атрибут <emphasis>doctype-system</emphasis></subtitle>
      <p>Для определения логической структуры документов в XML используются DTD — определения типов документов. В большинстве случаев определения типов содержатся во внешних ресурсах, которые включаются в документ в виде системных или публичных идентификаторов.</p>
      <p>XSLT позволяет создавать ссылки на внешние определения типов при помощи атрибута <code>doctype-system</code> элемента <code>xsl:output</code>.</p>
      <subtitle>Пример</subtitle>
      <p>Предположим, что мы создаем документ, логическая схема которого определена во внешнем файле по адресу <code>"/dtds/document.dtd"</code>. Тогда, определив в преобразовании элемент <code>xsl:output</code> с атрибутом <code>doctype-system</code>, равным <code>"/dtds/document.dtd"</code>, мы получим в выходящем документе определение типа в виде</p>
      <p><code>&lt;!DOCTYPE <emphasis>элемент</emphasis> SYSTEM "/dtds/document.dtd"&gt;</code></p>
      <p>где <code><emphasis>элемент</emphasis></code> — первый элемент выходящего документа.</p>
      <subtitle>Листинг 8.47. Входящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;page&gt; content &lt;/page&gt;</code></p>
      <subtitle>Листинг 8.48. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:output indent="yes" doctype-system="/dtds/document.dtd"/&gt;</code></p>
      <p><code> &lt;xsl:template match="/"&gt;&lt;xsl:copy-of select="/"/&gt;&lt;/xsl: template&gt;</code></p>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 8.49. Выходящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;!DOCTYPE page SYSTEM "/dtds/document.dtd"&gt;</code></p>
      <p><code>&lt;page&gt; content &lt;/page&gt;</code></p>
      <subtitle>Атрибут <emphasis>doctype-public</emphasis></subtitle>
      <p>Если в преобразовании атрибутом <code>doctype-system</code> элемента <code>xsl:output</code> задано внешнее определение логического типа документа, это определение может быть расширено также и публичным идентификатором. Публичный идентификатор указывается в атрибуте <code>doctype-public</code> элемента <code>xsl:output</code>. Его использование может быть продемонстрировано следующим примером.</p>
      <subtitle>Листинг 8.50. Входящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;page&gt; content &lt;/page&gt;</code></p>
      <subtitle>Листинг 8.51. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:output indent="yes"</code></p>
      <p><code>  doctype-system="/dtds/document.dtd"</code></p>
      <p><code>  doctype-public="-//Document//Description" /&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="/"&gt;&lt;xsl:copy-of select="/"/&gt;&lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 8.52. Выходящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;!DOCTYPE page</code></p>
      <p><code> PUBLIC "-//Document//Description" "/dtds/document.dtd"&gt;</code></p>
      <p><code>&lt;page&gt; content &lt;/page&gt;</code></p>
      <subtitle>Атрибут <emphasis>media-type</emphasis></subtitle>
      <p>Атрибут <code>media-type</code> позволяет задавать медиа-тип содержимого выходящего документа. Для метода вывода <code>"xml"</code> значением <code>media-type</code> по умолчанию является <code>"text/xml"</code>. Несмотря на то, что <code>media-type</code> не оказывает никакого влияния на содержимое самого документа, XSLT-процессоры, используемые на стороне сервера, могут в зависимости от значения этого атрибута изменять MIME-тип исходящих данных при использовании, к примеру, такого протокола, как HTTP.</p>
      <subtitle>Атрибут <emphasis>omit-xml-declaration</emphasis></subtitle>
      <p>XML-документы, в принципе, могут быть корректными и без декларации XML. Поэтому XSLT позволяет опускать эту декларацию в выходящем документе, для чего значению атрибута <code>omit-xml-declaration</code> должно быть присвоено <code>"yes"</code>:</p>
      <p><code>&lt;xsl:output</code></p>
      <p><code> omit-xml-declaration="yes"/&gt;</code></p>
      <p>В случае если значение атрибута <code>omit-xml-declaration</code> опущено или не равно <code>"yes"</code>, процессор будет выводить в выходящем документе декларацию XML, которая включает информацию о версии (по умолчанию <code>"1.0"</code>) и кодировке документа (по умолчанию <code>"utf-8"</code> или <code>"utf-16"</code> в зависимости от процессора).</p>
      <subtitle>Атрибут standalone</subtitle>
      <p>Для того чтобы объявить документ как самостоятельный или несамостоятельный (standalone или non-standalone соответственно), следует использовать атрибут <code>standalone</code> элемента <code>xsl:output</code>. Если этот атрибут будет присутствовать в <code>xsl:output</code>, то процессор включит в декларацию XML объявление <code>standalone</code> с соответствующим значением. Если атрибут <code>standalone</code> не указан, объявление <code>standalone</code> в декларацию XML выходящего документа включено не будет.</p>
     </section>
     <section>
      <title>
       <p>Метод вывода<emphasis> "html"</emphasis></p>
      </title>
      <p>В нынешнем состоянии языки XML и HTML сильно похожи синтаксически, но при этом имеют некоторые довольно весомые различия. Метод вывода <code>"html"</code> используется для того, чтобы выводить документы в формате, который будет понятен большинству существующих на данный момент Web-браузеров.</p>
      <p>Одно из основных различий HTML и XML состоит в том, что в XML пустые элементы имеют формат <code>&lt;<emphasis>имя</emphasis>/&gt;</code>, в то время как в HTML тот же элемент был бы выведен, как <code>&lt;<emphasis>имя</emphasis>&gt;</code> — без косой черты. Метод вывода <code>"html"</code> учитывает эти различия и выводит теги пустых элементов HTML без косой черты после имени. В соответствии с технической рекомендацией языка HTML 4.0, пустыми элементами являются <code>area</code>, <code>base</code>, <code>basefont</code>, <code>br</code>, <code>col</code>, <code>frame</code>, <code>hr</code>, <code>img</code>, <code>input</code>, <code>isindex</code>, <code>link</code>, <code>meta</code> и <code>param</code>.</p>
      <subtitle>Пример</subtitle>
      <subtitle>Листинг 8.53. Входящий документ</subtitle>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;page&gt;</code></p>
      <p><code> &lt;title&gt;I'm just a simple page...&lt;/title&gt;</code></p>
      <p><code> &lt;content&gt;I've got a simple content&lt;/content&gt;</code></p>
      <p><code>&lt;/page&gt;</code></p>
      <subtitle>Листинг 8.54. Преобразование</subtitle>
      <p><code> &lt;xsl:stylesheet</code></p>
      <p><code>  version="1.0"</code></p>
      <p><code>  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:output indent="yes" method="html"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="/page"&gt;</code></p>
      <p><code>  &lt;html&gt;</code></p>
      <p><code>   &lt;head&gt;</code></p>
      <p><code>    &lt;title&gt;</code></p>
      <p><code>     &lt;xsl:value-of select="title"/&gt;</code></p>
      <p><code>    &lt;/title&gt;</code></p>
      <p><code>   &lt;/head&gt;</code></p>
      <p><code>   &lt;body&gt;</code></p>
      <p><code>    Welcome!&lt;br/&gt;</code></p>
      <p><code>    Be our guest! &lt;HR/&gt;</code></p>
      <p><code>    &lt;xsl:value-of select="content"/&gt;</code></p>
      <p><code>   &lt;/body&gt;</code></p>
      <p><code>  &lt;/html&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 8.55. Выходящий документ</subtitle>
      <p><code>&lt;html&gt;</code></p>
      <p><code> &lt;head&gt;</code></p>
      <p><code>  &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"&gt;</code></p>
      <p><code>  &lt;title&gt;I'm just a simple page...&lt;/title&gt;</code></p>
      <p><code> &lt;/head&gt;</code></p>
      <p><code> &lt;body&gt;</code></p>
      <p><code>  Welcome!&lt;br&gt;</code></p>
      <p><code>  Be our guest! &lt;HR&gt;</code></p>
      <p><code>  I've got a simple content</code></p>
      <p><code> &lt;/body&gt;</code></p>
      <p><code>&lt;/html&gt;</code></p>
      <p>Как можно заметить, метод вывода <code>"html"</code> распознает элементы HTML вне зависимости от регистра символов — в нашем примере пустой элемент <code>&lt;HR/&gt;</code> был выведен как <code>&lt;HR&gt;</code>, что соответствует синтаксису HTML.</p>
      <p>Документы, которые преобразуются в HTML, могут также иметь программы, определенные внутри элемента <code>script</code> или стили, заданные внутри элемента <code>style</code>. В случае если внутри этих элементов оказываются символы, считающиеся в XML специальными — такие как "<code>&lt;</code>", "<code>&amp;</code>" и так далее, процессор не должен заменять их символьными или встроенными сущностями.</p>
      <subtitle>Пример</subtitle>
      <p>Предположим, что в преобразуемом документе элемент <code>script</code> определен с использованием специальных символов, которые заменены сущностями:</p>
      <p><code>&lt;script&gt; if (a &amp;gt; b) swap(a, b) &lt;/script&gt;</code></p>
      <p>или с использованием секций символьных данных:</p>
      <p><code>&lt;script&gt;&lt;![CDATA[ if (a&gt;b) swap(a, b) ]]&gt;&lt;/script&gt;</code></p>
      <p>При использовании метода вывода <code>"html"</code> оба варианта будут выведены, как</p>
      <p><code>&lt;script&gt; if (a&gt;b) swap(a, b) &lt;/script&gt;</code></p>
      <p>Пожалуй, стоит еще раз повторить, что это относится только к элементам <code>style</code> и <code>script</code>. Специальные символы, использованные в других элементах, будут заменены символьными или встроенными сущностями.</p>
      <subtitle>Пример</subtitle>
      <p><code>&lt;P&gt;This &gt;o&amp;lt; is a black hole of this page!&lt;/P&gt;</code></p>
      <p>будет выведено как</p>
      <p><code>&lt;P&gt;This &amp;gt;o&amp;lt; is a black hole of this page!&lt;/P&gt;</code></p>
      <p>В соответствии со спецификацией, некоторые атрибуты в HTML могут и не иметь значений — как правило, это атрибуты с булевыми значениями, такие, к примеру, как атрибут <code>selected</code> элемента <code>option</code>, присутствие которого в элементе означает то, что опция выбрана, отсутствие — то, что она не выбрана. Для того чтобы получить в выходящем документе</p>
      <p><code>&lt;option selected&gt;</code></p>
      <p>следует в преобразовании указывать</p>
      <p><code>&lt;option selected="selected"&gt;</code></p>
      <p>то есть присваивать булевому атрибуту значение, равное собственному имени. Такие значения будут выведены в минимизированной форме, как это и требовалось.</p>
      <p>HTML и XML также имеют небольшие различия в формате вывода инструкций по обработке. В то время как в XML эти инструкции имеют вид</p>
      <p><code>&lt;?<emphasis>приложение содержимое</emphasis>?&gt;</code></p>
      <p>в HTML инструкции по обработке заканчиваются не "<code>?&gt;</code>", а просто правой угловой скобкой ("<code>&gt;</code>"):</p>
      <p><code>&lt;?<emphasis>приложение содержимое</emphasis>&gt;</code></p>
      <p>Таким образом, результатом выполнения кода</p>
      <p><code>&lt;xsl:processing-instruction name="app"&gt;content&lt;/xsl:processing-instruction&gt;</code></p>
      <p>при использовании метода XML будет</p>
      <p><code>&lt;?app content?&gt;</code></p>
      <p>а при использовании метода HTML</p>
      <p><code>&lt;?app content&gt;</code></p>
      <subtitle>Атрибут <emphasis>version</emphasis></subtitle>
      <p>Атрибут <code>version</code> элемента <code>xsl:output</code> в методе <code>"html"</code> обозначает версию языка HTML, которая должна использоваться в выходящем документе. По умолчанию значением этого атрибута является <code>"4.0"</code>, что означает соответствие выходящего документа спецификации языка HTML версии 4.0. Отметим, что последней версией языка HTML на момент написания этой книги является версия 4.02, однако отличия между этими версиями незначительны.</p>
      <subtitle>Атрибут <emphasis>encoding</emphasis></subtitle>
      <p>Кодировка выходящего документа определяется в HTML несколько иначе, чем в XML. Если в XML мы использовали определение <code>encoding</code> в декларации XML, то в HTML кодировка описывается в элементе <code>meta</code> следующим образом:</p>
      <p><code>&lt;html&gt; &lt;head&gt;</code></p>
      <p><code>&lt;meta http-equiv="Content-Type"</code></p>
      <p><code> content="text/html; charset=windows-1251"&gt;</code></p>
      <p><code>...</code></p>
      <p>Поэтому, если в выходящем документе внутри корневого элемента <code>html</code> присутствует элемент <code>head</code>, процессор должен добавить в него элемент meta с соответствующим определением кодировки.</p>
      <subtitle>Пример</subtitle>
      <p>Элемент</p>
      <p><code>&lt;xsl:output encoding="ISO-8859-1"/&gt;</code></p>
      <p>добавит в элемент <code>head</code> выходящего HTML-документа элемент <code>meta</code> в следующем виде:</p>
      <p><code>&lt;meta http-equiv="Content-Type"</code></p>
      <p><code> content="text/html; charset=ISO-8859-1"&gt;</code></p>
      <p>Таким образом, для определения кодировки выходящего HTML-документа не следует вручную создавать соответствующий элемент <code>meta</code> — нужно просто указать требуемую кодировку в атрибуте <code>encoding</code> элемента <code>xsl:output</code>.</p>
      <subtitle>Атрибут <emphasis>indent</emphasis></subtitle>
      <p>XSLT позволяет использовать в HTML документах индентацию точно так же, как мы бы использовали ее в методе <code>"xml"</code>.</p>
      <subtitle>Атрибуты <emphasis>doctype-system</emphasis> и <emphasis>doctype-public</emphasis></subtitle>
      <p>Декларация типа документа с внешними системными или публичными идентификаторами может быть использована в HTML точно так же, как в XML. Поскольку в объявлении типа документа после <code>&lt;!DOCTYPE</code> должно стоять имя корневого элемента, при методе вывода <code>"html"</code> этим именем будет <code>"HTML"</code> или <code>"html"</code> в зависимости от регистра символов имени корневого элемента документа.</p>
      <subtitle>Атрибут <emphasis>media-type</emphasis></subtitle>
      <p>Атрибут <code>media-type</code> определяет медиа-тип содержимого выходящего документа. Для HTML-документов значением <code>media-type</code> по умолчанию будет <code>"text/html"</code>.</p>
     </section>
     <section>
      <title>
       <p>Метод вывода<emphasis> "text"</emphasis></p>
      </title>
      <p>XSLT позволяет выводить результат преобразования как простой текст. При использовании <code>method="text"</code> результирующее дерево приводится к строке, то есть в этом случае результатом преобразования будет строковое сложение всех текстовых узлов дерева.</p>
      <subtitle>Пример</subtitle>
      <p>Входящий документ</p>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;page&gt;</code></p>
      <p><code> &lt;title&gt;My heart's in the Highlands&lt;/title&gt;</code></p>
      <p><code> &lt;content&gt;My heart is not here&lt;/content&gt;</code></p>
      <p><code>&lt;/page&gt;</code></p>
      <p>одним и тем же шаблоном:</p>
      <p><code>&lt;xsl:template match="/page"&gt;</code></p>
      <p><code> &lt;poem title="{title}"&gt;</code></p>
      <p><code>  &lt;xsl:value-of select="title"/&gt;</code></p>
      <p><code>  &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
      <p><code>  &lt;xsl:value-of select="content"/&gt;</code></p>
      <p><code> &lt;/poem&gt;</code></p>
      <p><code>&lt;/xsl:template&gt;</code></p>
      <p>при использовании метода вывода <code>"xml"</code> будет преобразован к виду</p>
      <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
      <p><code>&lt;poem title="My heart's in the Highlands"&gt;</code></p>
      <p><code> My heart's in the Highlands</code></p>
      <p><code> My heart is not here</code></p>
      <p><code>&lt;/poem&gt;</code></p>
      <p>а при использовании метода <code>"text"</code> к виду</p>
      <p><code>My heart's in the Highlands</code></p>
      <p><code>My heart is not here</code></p>
      <subtitle>Атрибут <emphasis>encoding</emphasis></subtitle>
      <p>Атрибут <code>encoding</code> указывает на предпочтительную кодировку вывода текста документа. Значение атрибута <code>encoding</code> по умолчанию зависит от программной платформы, на которой производится преобразование. В большинстве процессоров по умолчанию используются кодировки UTF-8, ASCII и ISO-8859-1.</p>
      <p>В случае если кодировка, используемая для вывода текста, не отображает некоторые символы документа, процессор может выдать ошибку.</p>
      <subtitle>Атрибут <emphasis>media-type</emphasis></subtitle>
      <p>По умолчанию в качестве значения атрибута <code>media-type</code>, используемого для простого текста, указывается <code>"text/plain"</code>. Значение атрибута <code>media-type</code> может быть использовано сервером, преобразующим документ в качестве MIME-типа.</p>
     </section>
     <section>
      <title>
       <p>Другие методы вывода</p>
      </title>
      <p>Как уже было сказано раньше, спецификация XSLT позволяет помимо основных методов <code>"xml"</code>, <code>"html"</code> и <code>"text"</code> использовать также и другие методы, реализация которых будет зависеть от производителя того или иного процессора. Кажется вполне логичной и закономерной возможность использования, к примеру, такого метода, как <code>"pdf"</code> для создания документов в Adobe Portable Document Format (переносимом формате документов) или метода <code>"bin"</code> для создания двоичного потока данных. Однако, на данном этапе, процесс сериализации (создания физической сущности из логической модели) пока еще не определен в общем виде для произвольного метода. Возможно, в будущем, по аналогии с объектной моделью документа (DOM) будут созданы схожие интерфейсы для более легкого определения методов сериализации и интеграции преобразований в другие программы, но в настоящее время следует ограничиваться тремя основными методами.</p>
      <p>Отметим также, что спецификация языка XSLT определяет функциональность элемента <code>xsl:output</code> как возможную, но не обязательную. Процессоры обязаны манипулировать логическими моделями XML-документов, но при этом они не обязаны поддерживать сериализацию и уметь выводить преобразованный XML-документ как последовательность байт. Конечно же, абсолютное большинство процессоров поддерживает такую возможность, но при всем том она остается не более чем возможностью.</p>
      <p>Поэтому из соображений переносимости можно лишь только надеяться, что документ будет выведен так, как было задумано. Не следует исключать возможности, что в определённых условиях процессор не сможет контролировать процесс вывода документа.</p>
      <p>Типичным примером такой ситуации может быть использование процессора совместно с другими компонентами, которые обмениваются с процессором документами в виде DOM-структур, но сами загружают и выводят документы. В этом примере компоненты, занимающиеся выводом преобразованного документа, могут спокойным образом игнорировать все то, что было указано в элементе <code>xsl:output</code> или в атрибутах <code>disable-output-escaping</code> других элементов преобразования. Более того, они даже не будут знать, что было там указано, поскольку эти значения не касаются процесса преобразования как такового — они относятся к выводу, контролировать который процессор в данном случае не может.</p>
      <p>Отсюда следует однозначный вывод: не нужно чересчур злоупотреблять возможностями <code>xsl:output</code> и <code>disable-output-escaping</code>.</p>
     </section>
    </section>
    <section>
     <title>
      <p>Замена специальных символов</p>
     </title>
     <p>Как мы уже знаем, в XML есть несколько специальных символов, которые, как правило, заменяются процессором при выводе документа на соответствующие символьные или встроенные сущности. К примеру, для того, чтобы вывод был корректным XML-документом, процессор обязан заменять символы "<code>&lt;</code>" и "<code>&amp;</code>" на встроенные (<code>&amp;lt;</code> и <code>&amp;amp;</code>) или символьные (<code>&amp;#60;</code> и <code>&amp;#38;</code>) сущности.</p>
     <p>Между тем довольно часто бывает необходимым выводить в выходящем документе символы разметки.</p>
     <subtitle>Пример</subtitle>
     <p>Пусть входящий документ содержит описание товара, заданное в секции CDATA:</p>
     <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
     <p><code>&lt;product&gt;</code></p>
     <p><code> &lt;title&gt;An elephant&lt;/title&gt;</code></p>
     <p><code> &lt;description&gt;&lt;![CDATA[This is a &lt;em&gt;big&lt;/em&gt; and &lt;b&gt;grey&lt;/b&gt; animal!]]&gt;&lt;/description&gt;</code></p>
     <p><code>&lt;/product&gt;</code></p>
     <p>Если мы будем преобразовывать этот документ с использованием шаблона</p>
     <p><code>&lt;xsl:template match="product"&gt;</code></p>
     <p><code> &lt;p&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="title"/&gt;&lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;&lt;br/&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="description"/&gt;</code></p>
     <p><code>&lt;/p&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>то в выходящем документе специальные символы будут заменены:</p>
     <p><code>&lt;p&gt;An elephant</code></p>
     <p><code>&lt;br/&gt;This is a &amp;lt;em&amp;gt;big&amp;lt;/em&amp;gt; and &amp;lt;b&amp;gt;grey&amp;lt;/b&amp;gt; animal!&lt;/p&gt;</code></p>
     <p>Для того чтобы избежать замены, можно воспользоваться атрибутом <code>disable-output-escaping</code> (отменить замену символов) элементов <code>xsl:value-of</code> и xsl:text. Этот атрибут может принимать значения <code>"yes"</code> и <code>"no"</code> ("no" — значение по умолчанию). Значение <code>"yes"</code> означает, что процессор при выводе текста, создаваемого <code>xsl:text</code> или <code>xsl:value-of</code> не должен заменять специальные символы. Если бы в предыдущем примере мы использовали преобразование.</p>
     <subtitle>Листинг 8.56. Преобразование, содержащее disable-output-escaping</subtitle>
     <p><code>&lt;xsl:stylesheet version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:output indent="yes" method="xml"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="product"&gt;</code></p>
     <p><code>  &lt;p&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="title"/&gt;&lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;&lt;br/&gt;</code></p>
     <p><code>   &lt;xsl:value-of disable-output-escaping="yes" select="description"/&gt;</code></p>
     <p><code>  &lt;/p&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>то на выходе мы бы получили документ</p>
     <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
     <p><code>&lt;p&gt;An elephant</code></p>
     <p><code>&lt;br/&gt;This is a &lt;em&gt;big&lt;/em&gt; and &lt;b&gt;grey&lt;/b&gt; animal!&lt;/p&gt;</code></p>
     <p>Атрибут <code>disable-output-escaping</code> налагает ряд ограничений на использование текстовых узлов, генерируемых элементами <code>xsl:text</code> и <code>xsl:value-of</code>: эти узлы не могут входить в качестве текстового содержимого в узлы атрибутов, комментариев или инструкций по обработке. Кроме того, дерево, содержащее текстовые узлы, для которых была отменена замена специальных символов, не может быть приведено к строке или числу. И в том и в другом случае процессор может либо выдать ошибку преобразования, либо проигнорировать отмену замены специальных символов.</p>
     <p>Атрибут <code>disable-output-escaping</code> имеет также и более концептуальное ограничение. Процессор сможет отменить замену символов только в том случае, когда он сам будет контролировать процесс вывода. Как мы уже обсуждали в предыдущем разделе, ситуации, когда процесс вывода не будет выполняться самим процессором, не такая уж и редкость. Поэтому следует использовать <code>disable-output-escaping</code> только в тех случаях, когда другой альтернативы нет или когда имеется полная уверенность, что этот метод будет работать.</p>
     <p>Атрибут <code>disable-output-escaping</code> работает с методами вывода <code>"xml"</code> и <code>"html"</code>, но не оказывает никакого влияния на метод <code>"text"</code>, поскольку при этом методе все специальные символы и так выводятся без замены.</p>
    </section>
    <section>
     <title>
      <p>Кодировки в XSLT-преобразованиях</p>
     </title>
     <p>Несмотря на то, что в логических деревьях, которыми манипулирует XSLT, текстовые узлы представляются в кодировке Unicode, очень часто в обрабатываемых документах бывает необходимо использовать также другие кодировки. К примеру, большинство русскоязычных документов хранятся в кодировках Windows-1251 и KOI8-R.</p>
     <p>Если внимательно присмотреться к преобразованиям, можно заметить, что, как правило, в них участвуют минимум три документа — входящий (преобразовываемый) документ, документ преобразования (преобразующий) и выходящий (преобразованный документ). Соответственно, каждый из них может иметь собственную кодировку.</p>
     <p>Кодировка входящего документа указывается в его xml-декларации. Например, документы в кодировке Windows-1251 должны иметь xml-декларацию вида</p>
     <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
     <p>Возможно, небольшим сюрпризом окажется то, что в соответствии со стандартом XML, имена тегов вовсе не обязаны состоять исключительно из латинских букв. В имени элемента можно использовать весь кириллический алфавит, а также множество других символов. Совершенно корректным будет документ</p>
     <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
     <p><code>&lt;страница&gt;</code></p>
     <p><code> &lt;содержимое/&gt;</code></p>
     <p><code>&lt;/страница&gt;</code></p>
     <p>Аналогичным образом кириллицу, а также другие наборы символов и алфавиты можно использовать и в самих преобразованиях, поскольку те в свою очередь также являются XML-документами.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг 8.57. Входящий документ</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
     <p><code>&lt;каждый&gt;</code></p>
     <p><code> &lt;охотник&gt;</code></p>
     <p><code>  &lt;желает&gt;</code></p>
     <p><code>   &lt;знать&gt;</code></p>
     <p><code>    &lt;где&gt;</code></p>
     <p><code>     &lt;сидит&gt;</code></p>
     <p><code>      &lt;фазан/&gt;</code></p>
     <p><code>     &lt;/сидит&gt;</code></p>
     <p><code>    &lt;/где&gt;</code></p>
     <p><code>   &lt;/знать&gt;</code></p>
     <p><code>  &lt;/желает&gt;</code></p>
     <p><code> &lt;/охотник&gt;</code></p>
     <p><code>&lt;/каждый&gt;</code></p>
     <subtitle>Листинг 8.58. Преобразование</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> &lt;xsl:output indent="yes" encoding="windows-1251"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="каждый"&gt;</code></p>
     <p><code>  &lt;редкий&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/редкий&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="охотник"&gt;</code></p>
     <p><code>  &lt;рыболов&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/рыболов&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="желает/знать"&gt;</code></p>
     <p><code>  &lt;может&gt;</code></p>
     <p><code>   &lt;забыть&gt;</code></p>
     <p><code>    &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>   &lt;/забыть&gt;</code></p>
     <p><code>  &lt;/может&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="где"&gt;</code></p>
     <p><code>  &lt;как&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/как&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="сидит"&gt;</code></p>
     <p><code>  &lt;плавает&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/плавает&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="фазан"&gt;</code></p>
     <p><code>  &lt;щука&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>  &lt;/щука&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 8.59. Выходящий документ</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
     <p><code>&lt;редкий&gt;</code></p>
     <p><code> &lt;рыболов&gt;</code></p>
     <p><code>  &lt;может&gt;</code></p>
     <p><code>   &lt;забыть&gt;</code></p>
     <p><code>    &lt;как&gt;</code></p>
     <p><code>     &lt;плавает&gt;</code></p>
     <p><code>      &lt;щука/&gt;</code></p>
     <p><code>     &lt;/плавает&gt;</code></p>
     <p><code>    &lt;/как&gt;</code></p>
     <p><code>   &lt;/забыть&gt;</code></p>
     <p><code>  &lt;/может&gt;</code></p>
     <p><code> &lt;/рыболов&gt;</code></p>
     <p><code>&lt;/редкий&gt;</code></p>
     <p>Напомним, что кодировка выходящего документа определяется атрибутом <code>encoding</code> элемента <code>xsl:output</code> и не зависит от кодировок преобразования и обрабатываемых документов. Например, можно легко создать преобразование, которое будет изменять кодировку входящего документа. Это будет идентичное преобразование с элементом <code>xsl:output</code>, определяющим целевой набор символов.</p>
     <subtitle>Листинг 8.60. Преобразование, изменяющее кодировку документа на KOI8-R</subtitle>
     <p><code>&lt;xsl:stylesheet version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> &lt;xsl:output encoding="KOI8-R"/&gt;</code></p>
     <p><code> &lt;xsl:template match="@*|node()"&gt;</code></p>
     <p><code>  &lt;xsl:copy&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code>  &lt;/xsl:copy&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Как можно видеть, XSLT довольно гибко поддерживает кодировки — входящие и выходящие документы, а также сами преобразования могут иметь разные наборы символов. Единственным ограничением является множество кодировок, поддерживаемое самим процессором, вернее парсером, который он использует для разбора входящих документов, и сериализатором, который служит для создания физического экземпляра выходящего документа.</p>
     <p>Практически во всех процессорах поддерживаются кодировки UTF-8, US- ASCII и ISO-8859-1, но далеко не все могут работать с Windows-1251 или KOI8-R. Поэтому, создавая документы и преобразования в нестандартных кодировках, мы заведомо ограничиваем переносимость решений. В случаях, когда XML/XSLT приложения создаются под конкретный процессор с заведомо известными возможностями, это не является большой проблемой, однако в тех случаях, когда требуется универсальность или точно не известно, каким процессором будет производиться обработка, единственным выходом будет использовать UTF-8 — как во входящих документах, так и в самих преобразованиях.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Случай нескольких входящих документов</p>
    </title>
    <section>
     <p>Базовая архитектура преобразования подразумевает один входящий документ. Несмотря на это, в преобразованиях можно использовать и обрабатывать информацию, хранящуюся в других, внешних документах. Доступ к этим документам можно получить при помощи функции <code>document</code>.</p>
    </section>
    <section>
     <title>
      <p>Функция <emphasis>document</emphasis></p>
     </title>
     <section>
      <p>Запись функции:</p>
      <p><code><emphasis>node-set </emphasis><strong>document</strong>(<emphasis>object</emphasis>, <emphasis>node-set</emphasis>?)</code></p>
      <p>Функция <code>document</code> позволяет обращаться к внешним документам по их URI, например</p>
      <p><code>&lt;xsl:copy-of select="document('http://www.w3.org')"/&gt;</code></p>
      <p>скопирует в выходящий документ содержимое главной страницы Консорциума W3.</p>
      <p>Функция <code>document</code> возвращает множество узлов. В простейшем случае это множество будет состоять из корневого узла внешнего документа. Функцию <code>document</code> можно использовать в более сложных XPath-выражениях, например в выражениях фильтрации. Так функция</p>
      <p><code>&lt;xsl:copy-of select="document('http://www.w3.org')/html/body/a"/&gt;</code></p>
      <p>скопирует все элементы а, находящиеся в теле (<code>/html/body</code>) внешнего документа.</p>
      <p>Базовый сценарий использования функции <code>document</code> очень прост: ей передается строка, содержащая URI внешнего ресурса, а результатом является множество узлов, состоящее из корня внешнего документа. Однако на этом возможности <code>document</code> не заканчиваются. Мы рассмотрим несколько вариантов вызова функции <code>document</code> с параметрами различного типа.</p>
     </section>
     <section>
      <title>
       <p>Вызов <emphasis>document(string)</emphasis></p>
      </title>
      <p>В случае если функции <code>document</code> передана строка, возвращаемое множество будет состоять из корневого узла внешнего документа. URI этого документа как раз и сообщается строковым аргументом функции <code>document</code>.</p>
      <p>Интересной особенностью является возможность передать пустую строку:</p>
      <p><code>document('')</code></p>
      <p>В этом случае <code>document</code> возвратит корневой узел самого преобразования. При помощи <code>document('')</code> можно получать доступ к информации, хранящейся в самом преобразовании (оно ведь тоже является ХМL-документом). К сожалению, перед обращением к документу не существует способа проверить его существование. Процессор может либо выдать ошибку, либо возвратить пустое множество.</p>
      <subtitle>Пример</subtitle>
      <subtitle>Листинг 8.61. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
      <p><code> xmlns:user="urn:user-namespace"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;user:data&gt;</code></p>
      <p><code>  &lt;item&gt;1&lt;/item&gt;</code></p>
      <p><code>  &lt;item&gt;2&lt;/item&gt;</code></p>
      <p><code> &lt;/user:data&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:variable</code></p>
      <p><code>  name="data" select="document('')/xsl:stylesheet/user:data"/&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="/"&gt;</code></p>
      <p><code>  &lt;xsl:copy-of select="$data/item"/&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 8.62. Выходной документ</subtitle>
      <p><code>&lt;item</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
      <p><code> xmlns:user="urn:user-namespace"&gt;1&lt;/item&gt;</code></p>
      <p><code>&lt;item</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
      <p><code> xmlns:user="urn:user-namespace"&gt;2&lt;/item&gt;</code></p>
     </section>
     <section>
      <title>
       <p>Вызов <emphasis>document(node-set)</emphasis></p>
      </title>
      <p>Передавая функции <code>document</code> множество узлов, можно получить доступ к нескольким документам, URI которых являются строковыми значениями узлов множества. Это, в частности, позволяет обращаться к документам, URI которых указаны в узлах обрабатываемого документа. Например, в контексте элемента</p>
      <p><code>&lt;а href="http://www.w3.org"&gt;...&lt;/а&gt;</code></p>
      <p>вполне корректным вызовом функции <code>document</code> будет <code>document (@href)</code>.</p>
      <p>Выражение <code>@href</code> — здесь возвращает множество, состоящее из единственного узла атрибута. Его строковое значение (<code>"http://www.w3.org"</code>) будет использовано как URI внешнего документа. Результирующее множество узлов будет содержать единственный корневой узел документа, расположенного по адресу <strong>http://www.w3.org</strong>.</p>
      <p>Приведем еще один пример. XPath-выражение <code>//a/@href</code> возвращает множество всех атрибутов <code>href</code> элементов <code>а</code> текущего документа. Тогда множество document(<code>//a/@href</code>) будет содержать корневые узлы всех документов, на которые ссылается посредством элементов а текущий документ.</p>
     </section>
     <section>
      <title>
       <p>Вызов <emphasis>document(string, node-set)</emphasis></p>
      </title>
      <p>URI, которые передаются функции <code>document</code>, могут быть как абсолютными, так и относительными, например <code>document('doc.xml')</code> возвратит корень документа <code>doc.xml</code>, находящегося в том же каталоге, что и само преобразование.</p>
      <p>Функция <code>document</code> позволяет менять "точку отсчета" относительных URI. Если в качестве второго аргумента функции document передано множество узлов, то относительные идентификаторы ресурсов будут отсчитываться от базового адреса первого (в порядке просмотра документа) узла этого множества.</p>
      <p>Базовым URI узла дерева является:</p>
      <p>&#9633; если элемент или инструкция по обработке принадлежит внешней сущности, базовым URI соответствующего узла будет URI внешней сущности;</p>
      <p>&#9633; иначе базовым URI является URI документа;</p>
      <p>&#9633; базовым URI текстового узла, узла атрибута, комментария или пространства имен является базовый URI родительского элемента.</p>
      <p>Поясним вышесказанное на примерах.</p>
      <p>Конструкция</p>
      <p><code>&lt;xsl:copy-of select="document('doc.xml')"/&gt;</code></p>
      <p>копирует в выходящий документ <code>doc.xml</code>, находящийся в одном каталоге вместе с преобразованием.</p>
      <p>Несмотря на то, что в следующем определении <code>xsl:for-each</code> меняет контекст, <code>document('doc.xml')</code> все равно возвращает корень документа <code>doc.xml</code>, находящегося в одном с преобразованием каталоге:</p>
      <p><code>&lt;xsl:for-each select="document('a/data.xml')"&gt;</code></p>
      <p><code> &lt;xsl:copy-of select="document('doc.xml')"/&gt;</code></p>
      <p><code>&lt;/xsl:for-each&gt;</code></p>
      <p>В следующей конструкции <code>document('doc.xml', /)</code> копирует документ <code>a/doc.xml,</code> поскольку в качестве базового URI используется URI корня документа <code>a/data.xml</code>:</p>
      <p><code>&lt;xsl:for-each select="document('a/data.xml')"&gt;</code></p>
      <p><code> &lt;xsl:copy-of select="document('doc.xml', /)"/&gt;</code></p>
      <p><code>&lt;/xsl:for-each&gt;</code></p>
      <p>Того же самого эффекта можно достичь следующим образом:</p>
      <p><code>&lt;xsl:copy-of select="document('doc.xml', document('a/data.xml'))"/&gt;</code></p>
      <p>В следующей конструкции за базовый URI опять принимается URI самого преобразования (вернее, его корневого узла):</p>
      <p><code>&lt;xsl:copy-of select="document('doc.xml', document(''))"/&gt;</code></p>
      <p>Протестируем теперь все это вместе в одном преобразовании.</p>
      <subtitle>Листинг 8.63. Преобразование</subtitle>
      <p><code>&lt;xsl:stylesheet</code></p>
      <p><code> version="1.0"</code></p>
      <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
      <empty-line/>
      <p><code> &lt;xsl:template match="/"&gt;</code></p>
      <p><code>  &lt;xsl:copy-of select="document('doc.xml')"/&gt;</code></p>
      <p><code>  &lt;xsl:for-each select="document('a/data.xml')"&gt;</code></p>
      <p><code>   &lt;xsl:copy-of select="document('doc.xml')"/&gt;</code></p>
      <p><code>  &lt;/xsl:for-each&gt;</code></p>
      <p><code>  &lt;xsl:for-each select="document('a/data.xml')"&gt;</code></p>
      <p><code>   &lt;xsl:copy-of select="document('doc.xml', /)"/&gt;</code></p>
      <p><code>  &lt;/xsl:for-each&gt;</code></p>
      <p><code>  &lt;xsl:copy-of select="document('doc.xml', document('a/data.xml'))"/&gt;</code></p>
      <p><code>  &lt;xsl:for-each select="document('a/data.xml')"&gt;</code></p>
      <p><code>   &lt;xsl:copy-of select="document('doc.xml', document(''))"/&gt;</code></p>
      <p><code>  &lt;/xsl:for-each&gt;</code></p>
      <p><code> &lt;/xsl:template&gt;</code></p>
      <empty-line/>
      <p><code>&lt;/xsl:stylesheet&gt;</code></p>
      <subtitle>Листинг 8.64. Документ doc.xml</subtitle>
      <p><code>&lt;doc&gt;doc.xml&lt;/doc&gt;</code></p>
      <subtitle>Листинг 8.65. Документ a/doc.xml</subtitle>
      <p><code>&lt;doc&gt;a/doc.xml&lt;/doc&gt;</code></p>
      <subtitle>Листинг 8.66. Выходящий документ</subtitle>
      <p><code>&lt;doc&gt;doc.xml&lt;/doc&gt;</code></p>
      <p><code>&lt;doc&gt;doc.xml&lt;/doc&gt;</code></p>
      <p><code>&lt;doc&gt;a/doc.xml&lt;/doc&gt;</code></p>
      <p><code>&lt;doc&gt;a/doc.xml&lt;/doc&gt;</code></p>
      <p><code>&lt;doc&gt;doc.xml&lt;/doc&gt;</code></p>
     </section>
     <section>
      <title>
       <p>Вызов <emphasis>document(node-set, node-set)</emphasis></p>
      </title>
      <p>Если функции <code>document</code> передаются два множества узлов, то вычисление результата можно описать примерно следующим образом:</p>
      <p>&#9633; каждый из узлов первого аргумента преобразуется в строковый вид;</p>
      <p>&#9633; для каждого из полученных значений выполняется вызов типа <code>document(string, node-set)</code>;</p>
      <p>&#9633; результирующие множества объединяются.</p>
      <p>Иными словами, <code>document(node-set, node-set)</code> работает через <code>document(string, node-set)</code> точно так же, как <code>document(node-set)</code> работает через <code>document(string)</code>. Разница лишь в том, что в первом случае базовый URI будет изменен.</p>
     </section>
    </section>
   </section>
   <section>
    <title>
     <p>Другие дополнительные функции XSLT</p>
    </title>
    <section>
     <title>
      <p>Функция<emphasis> current</emphasis></p>
     </title>
     <p>Выражение для этой функции имеет вид:</p>
     <p><code><emphasis>node-set </emphasis><strong>current</strong>()</code></p>
     <p>Функция <code>current</code> возвращает множество, состоящее из текущего узла преобразования.</p>
     <p>Мы часто использовали термины текущий узел и узел контекста как синонимы: действительно, в большинстве случаев между ними нет никакой разницы, текущий узел преобразования совпадает с узлом контекста вычисления выражений. Однако бывают ситуации, когда они являются двумя различными узлами.</p>
     <p>Представим себе, что нам нужно выбрать элементы <code>item</code> со значением атрибута <code>source</code>, равным значению этого атрибута текущего узла. Очевидно, путь выборки будет выглядеть как <code>item[<emphasis>предикат</emphasis>]</code>, где предикат определяет условие равенства атрибутов текущего и выбираемого. Но как записать это условие? Предикат будет вычисляться в контексте проверяемого элемента <code>item</code>, значит, все относительные пути выборки типа <code>@source</code> или <code>./@source</code> или <code>self::item/@source</code> будут отсчитываться именно от проверяемого элемента. В этом случае узел контекста и текущий узел преобразования — не одно и то же.</p>
     <p>Для того чтобы обратиться в предикате именно к текущему узлу, следует использовать функцию <code>current</code>:</p>
     <p><code>item[@source=current()/@source]</code></p>
     <p>Это выражение выберет все дочерние элементы <code>item</code> текущего узла, значение атрибута <code>source</code> которых будет таким же, как и у него.</p>
    </section>
    <section>
     <title>
      <p>Функция <emphasis>unparsed-entity-uri</emphasis></p>
     </title>
     <p>Выражение для этой функции следующее:</p>
     <p><code><emphasis>string </emphasis><strong>unparsed-entity-uri</strong>(<emphasis>string</emphasis>)</code></p>
     <p>Функция <code>unparsed-entity-uri</code> возвращает уникальный идентификатор ресурса, который соответствует неразбираемой внешней сущности, имя которой передано как аргумент.</p>
     <subtitle>Пример</subtitle>
     <p>Описывая синтаксис XML, мы приводили пример документа, который использовал неразбираемые внешние сущности.</p>
     <subtitle>Листинг 8.67<emphasis>.</emphasis> Входящий документ использующий неразбираемые внешние сущности</subtitle>
     <p><code>&lt;!DOCTYPE menu [</code></p>
     <p><code> &lt;!ELEMENT menu (menuitem*)&gt;</code></p>
     <p><code> &lt;!ELEMENT menuitem EMPTY&gt;</code></p>
     <p><code> &lt;!ATTLIST menuitem</code></p>
     <p><code>  image ENTITY #REQUIRED</code></p>
     <p><code>  title CDATA #REQUIRED</code></p>
     <p><code>  href CDATA #REQUIRED&gt;</code></p>
     <p><code> &lt;!NOTATION gif SYSTEM "gif-viewer.exe"&gt;</code></p>
     <p><code> &lt;!NOTATION jpg SYSTEM "jpg-viewer.exe"&gt;</code></p>
     <p><code> &lt;!ENTITY news SYSTEM "news.gif" NDATA gif&gt;</code></p>
     <p><code> &lt;!ENTITY products SYSTEM "prod.jpg" NDATA jpg&gt;</code></p>
     <p><code> &lt;!ENTITY support SYSTEM "support.gif" NDATA gif&gt;</code></p>
     <p><code>]&gt;</code></p>
     <p><code>&lt;menu&gt;</code></p>
     <p><code> &lt;menuitem image="news" title="News" href="news.htm"/&gt;</code></p>
     <p><code> &lt;menuitem image="products" title="Products" href="prods.htm"/&gt;</code></p>
     <p><code> &lt;menuitem image="support" title="Support" href="support.htm"/&gt;</code></p>
     <p><code>&lt;/menu&gt;</code></p>
     <p>Для того чтобы вычислить местоположение графических файлов, соответствующих пунктам этого меню, нужно будет использовать функцию <code>unparsed- entity-uri</code>. Аргументом этой функции в данном случае будет значение атрибута <code>image</code>, ведь именно этот атрибут задает имя неразбираемой сущности, которая соответствует изображению пункта меню. Преобразование такого документа в HTML будет иметь приблизительно следующий вид.</p>
     <subtitle>Листинг 8.68. Преобразование, использующее функцию unparsed-entity-uri</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:output</code></p>
     <p><code>  method="html"</code></p>
     <p><code>  indent="yes"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="menu"&gt;</code></p>
     <p><code>  &lt;table&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="menuitem"/&gt;</code></p>
     <p><code>  &lt;/table&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="menuitem"&gt;</code></p>
     <p><code>  &lt;tr&gt;</code></p>
     <p><code>   &lt;td&gt;</code></p>
     <p><code>    &lt;A alt="{@title}" href="{@href}"&gt;</code></p>
     <p><code>     &lt;img src="{unparsed-entity-uri(@image)}"/&gt;</code></p>
     <p><code>    &lt;/A&gt;</code></p>
     <p><code>   &lt;/td&gt;</code></p>
     <p><code>  &lt;/tr&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результат преобразования приведен на следующем листинге.</p>
     <subtitle>Листинг 8.69. Выходящий документ</subtitle>
     <p><code>&lt;table&gt;</code></p>
     <p><code> &lt;tr&gt;</code></p>
     <p><code>  &lt;td&gt;</code></p>
     <p><code>   &lt;A alt="News" href="news.htm"&gt;</code></p>
     <p><code>    &lt;img src="file:/C:/XML/news.gif"/&gt;</code></p>
     <p><code>   &lt;/A&gt;</code></p>
     <p><code>  &lt;/td&gt;</code></p>
     <p><code> &lt;/tr&gt;</code></p>
     <p><code> &lt;tr&gt;</code></p>
     <p><code>  &lt;td&gt;</code></p>
     <p><code>   &lt;A alt="Products" href="prods.htm"&gt;</code></p>
     <p><code>    &lt;img src="file:/C:/XML/prod.jpg"/&gt;</code></p>
     <p><code>   &lt;/A&gt;</code></p>
     <p><code>  &lt;/td&gt;</code></p>
     <p><code> &lt;/tr&gt;</code></p>
     <p><code> &lt;tr&gt;</code></p>
     <p><code>  &lt;td&gt;</code></p>
     <p><code>   &lt;A alt="Support" href="support.htm"&gt;</code></p>
     <p><code>    &lt;img src="file:/С:/XML/support.gif"/&gt;</code></p>
     <p><code>   &lt;/A&gt;</code></p>
     <p><code>  &lt;/td&gt;</code></p>
     <p><code> &lt;/tr&gt;</code></p>
     <p><code>&lt;/table&gt;</code></p>
     <p>Остается только добавить, что <code>unparsed-entity-uri</code> — это единственная функция, которая позволяет работать с неразбираемыми сущностями. Никаких средств для обработки нотаций и вспомогательных приложений, которые им соответствуют, в XSLT нет. Сказывается тот факт, что неразбираемые сущности и нотации очень редко используются в документах, поэтому их поддержка в XSLT минимальна.</p>
    </section>
    <section>
     <title>
      <p>Функция <emphasis>generate-id</emphasis></p>
     </title>
     <p>Синтаксическая конструкция этой функции:</p>
     <p><code><emphasis>string </emphasis><strong>generate-id</strong>(<emphasis>node-set?</emphasis>)</code></p>
     <p>Функция <code>generate-id</code> возвращает уникальный строковый идентификатор первого в порядке просмотра документа узла, передаваемого ей в виде аргумента. Если аргумент опущен, функция возвращает уникальный идентификатор контекстного узла. Если аргументом является пустое множество, функция должна возвращать пустую строку.</p>
     <p>Функция <code>generate-id</code> обладает следующими свойствами.</p>
     <p>&#9633; Функция <code>generate-id</code> возвращает для двух узлов один и тот же идентификатор тогда и только тогда, когда эти два узла совпадают. Это означает, что во время выполнения одного преобразования функция <code>generate-id</code> будет возвращать один идентификатор для одного и того же узла, а для разных узлов <code>generate-id</code> обязательно возвратит разные идентификаторы.</p>
     <p>&#9633; Возвращаемый идентификатор состоит только из цифр и букв ASCII и начинается буквой, то есть синтаксически является корректным XML-именем и может использоваться как имя элемента, атрибута, как значение ID-атрибута или в любом другом месте, где могут использоваться имена XML.</p>
     <p>Кроме этого спецификация оговаривает следующие важные положения, которые мы приведем ниже.</p>
     <p>&#9633; Процессор не обязан генерировать один и тот же идентификатор при разных выполнениях преобразования одного и того же документа. Иными словами, если в понедельник процессор <code><emphasis>X</emphasis></code> при выполнении преобразования <code><emphasis>Y</emphasis></code> сгенерирует для узла <code><emphasis>Z</emphasis></code> документа <code><emphasis>D</emphasis></code> идентификатор <code><emphasis>I</emphasis></code>, то во вторник тот же процессор <code><emphasis>X</emphasis></code> при выполнении того же преобразования <code><emphasis>Y</emphasis></code> с тем же документом <code><emphasis>D</emphasis></code> может сгенерировать для того же самого узла <code><emphasis>Z</emphasis></code> совершенно другой, отличный от <code><emphasis>I</emphasis></code> идентификатор.</p>
     <p>&#9633; Форма возвращаемого идентификатора может быть произвольной, но при этом она должна удовлетворять описанному выше синтаксису. Это означает, что каждый процессор может по-своему генерировать идентификатор. Спецификация не определяет никакого стандартного метода реализации функции <code>generate-id</code>.</p>
     <p>&#9633; Генерируемый идентификатор может совпадать, а может и не совпадать со значениями уникальных атрибутов, то есть атрибутов, тип данных которых объявлен в блоке DTD как <code>ID</code>.</p>
     <p>Помимо очевидного применения, например, для явного задания уникального идентификатора в выходящем документе, функция <code>generate-id</code> совершено неожиданным образом облегчает задачи группировки. Подробнее об этом мы расскажем в <emphasis>главе 11</emphasis>.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что в наших XML-документах изменилась логическая схема: теперь каждый элемент <code>item</code> должен обладать уникальным атрибутом <code>id</code>.</p>
     <p>Выполнить задачу конвертации может простое преобразование.</p>
     <subtitle>Листинг 8.70. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="@*|node()"&gt;</code></p>
     <p><code>  &lt;xsl:copy&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code>  &lt;/xsl:copy&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="item"&gt;</code></p>
     <p><code>  &lt;xsl:copy&gt;</code></p>
     <p><code>   &lt;xsl:attribute name="id"&gt;</code></p>
     <p><code>    &lt;xsl:text&gt;&lt;xsl:value-of select="generate-id()"/&gt;&lt;xsl:text&gt;</code></p>
     <p><code>   &lt;/xsl:attribute&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code>  &lt;/xsl:copy&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>В выходящем документе элементы <code>item</code> будут иметь уникальные идентификаторы.</p>
     <subtitle>Листинг 8.71. Выходящий документ</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;</code></p>
     <p><code>&lt;items&gt;</code></p>
     <p><code> &lt;item id="b1b1b2" source="a" name="A"/&gt;</code></p>
     <p><code> &lt;item id="b1b1b4" source="b" name="B"/&gt;</code></p>
     <p><code> ...</code></p>
     <p><code> &lt;item id="b1b1c34" source="a" name="F"/&gt;</code></p>
     <p><code>&lt;/items&gt;</code></p>
     <p>Сразу оговоримся, что этот способ будет работать не всегда: <code>generate-id</code> создает идентификатор, который является уникальным среди всех остальных идентификаторов узлов, а не среди всех значений уникальных атрибутов документа. Так что если бы какой-либо элемент имел ID-атрибут со значением <code>b1b1b4</code>, выходящий документ перестал бы быть правильным. Однако же, если в документе до преобразования вообще не было уникальных атрибутов, все будет в порядке.</p>
    </section>
    <section>
     <title>
      <p>Функция <emphasis>system-property</emphasis></p>
     </title>
     <p>Синтаксис этой функции приведен ниже:</p>
     <p><code><emphasis>object </emphasis><strong>system-property</strong>(<emphasis>string</emphasis>)</code></p>
     <p>Функция <code>system-property</code> возвращает значение свойства, которое определяется ее строковым параметром. Аргумент этой функции должен представлять расширенное имя системного свойства. Если процессор не поддерживает свойство с таким именем, функция должна вернуть пустую строку.</p>
     <p>Эта функция предназначена для получения информации об окружении, в котором производится преобразование. В стандарте языка указано, что все процессоры в обязательном порядке должны поддерживать следующие системные свойства:</p>
     <p>&#9633; <code>xsl:version</code> — это свойство должно возвращать номер версии языка XSLT, которую поддерживает данный процессор.</p>
     <p>&#9633; <code>xsl:vendor</code> — это свойство должно возвращать текстовую информацию о производителе используемого процессора.</p>
     <p>&#9633; <code>xsl:vendor-uri</code> — это свойство должно возвращать URL производителя — как правило, <code>xsl:vendor-uri</code> — это адрес Web-сайта производителя процессора.</p>
     <p>К сожалению, в первой версии языка XSLT процессоры обязаны поддерживать только эти свойства. Очень полезным, было бы, например, свойство, возвращающее имя преобразования или преобразовываемого файла. К сожалению, ничего подобного в стандарте не предусмотрено.</p>
     <subtitle>Пример</subtitle>
     <p>В качестве примера приведем небольшой шаблон, выводящий в виде комментария информацию о процессоре.</p>
     <subtitle>Листинг 8.72. Шаблон, выводящий системную информацию</subtitle>
     <p><code>&lt;xsl:template name="info"&gt;</code></p>
     <p><code> &lt;xsl:comment&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#xA; | XSLT Version: &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of</code></p>
     <p><code>   select="format-number(system-property('xsl:version'), '0.0')"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#xA; | XSLT Processor: &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="system-property('xsl:vendor')"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#xA; | URL: &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="system-property('xsl:vendor-url')"/&gt;</code></p>
     <p><code>  &lt;xsl:text&gt;&amp;#xA; +&lt;/xsl:text&gt;</code></p>
     <p><code> &lt;/xsl:comment&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Процессор SAXON, написанный Майклом Кеем (Michael Kay), выводит следующий комментарий:</p>
     <p><code>&lt;!--</code></p>
     <p><code> | XSLT Version: 1.0</code></p>
     <p><code> | XSLT Processor: SAXON 6.0.2 from Michael Kay of ICL</code></p>
     <p><code> | URL: http://users.iclway.co.uk/mhkay/saxon/index.html</code></p>
     <p><code> +--&gt;</code></p>
     <p>Ожидается, что в будущих версиях XSLT набор системных свойств будет расширен. Кроме того, многие процессоры поддерживают дополнительные системные свойства, не оговоренные в спецификации.</p>
    </section>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 9</p>
    <p>Совместное использование XSLT с другими языками программирования</p>
   </title>
   <section>
    <title>
     <p>XSLT и другие языки</p>
    </title>
    <p>Несмотря на то, что XSLT является вполне самостоятельным языком, его очень часто используют как составную часть в проектах, которые пишутся на других языках программирования. Тому существует множество причин. Попытаемся выделить главные из них.</p>
    <p>&#9633; Традиционные императивные языки программирования очень плохо подходят для обработки древовидно структурированных данных. Программы, действия в которых непременно выполняются последовательно одно за другим, в общем случае не могут эффективно (с точки зрения компактности и понятности кода) обработать сложные иерархические структуры.</p>
    <p>&#9633; В некоторых случаях XSLT-преобразования документов оказываются, наоборот, настолько сложны, что из соображений эффективности и простоты бывает намного легче использовать традиционные языки.</p>
    <p>&#9633; Во многих проектах использование XSLT может обеспечить легкую и гибкую интеграцию. Например, если одним из этапов процедуры обмена XML-данными будет XSLT-преобразование, расширение количества форматов, известных системе, будет производиться не дописыванием исходного кода, а добавлением преобразований. А поскольку XSLT обеспечивает не только синтаксические, но и семантические преобразования, то есть преобразования на структурном уровне, роль этого языка в проектах интеграции, основанных на использовании XML, может быть очень велика.</p>
    <p>&#9633; Использование XSLT-преобразований может коренным образом упростить создание Web-ориентированных приложений. Надо сказать, что во многих случаях XSLT-преобразования просто избавляют от необходимости программировать что-либо на других языках; однако даже тогда, когда без традиционных подходов не обойдешься, XSLT служит хорошую службу, обеспечивая простой, удобный и легко настраиваемый вывод фрагментов HTML.</p>
    <p>В этом разделе мы приведем примеры использования преобразований в различных языках и средах разработки. Конечно же, предлагаемые программы очень просты, но и их уже должно быть достаточно, чтобы начать применять XSLT в составе своих проектов.</p>
   </section>
   <section>
    <title>
     <p>Выполнение XSLT-преобразований в Object Pascal</p>
    </title>
    <section>
     <p>В этой главе мы приведем пример использования XSLT-преобразований в простом проекте, созданном в среде разработки Delphi. Базовым языком Delphi является Object Pascal. Решение, которое мы предложим, будет основываться на использовании библиотеки MSXML Parser 3.0 от Microsoft.</p>
     <p>Небольшое приложение, которое мы создадим, будет преобразовывать XML-документ (по умолчанию — "<code>source.xml</code>") при помощи XSLT-преобразования (по умолчанию — "<code>stylesheet.xsl</code>") и показывать результат преобразования.</p>
    </section>
    <section>
     <title>
      <p>Импорт MSXML в Delphi</p>
     </title>
     <p>Первым шагом после создания нового проекта (назовем его <code>DelphiXML</code>) будет импортирование библиотеки типов MSXML. Это позволит использовать в программе классы, интерфейсы и методы MSXML, в том числе и XSLT-процессор.</p>
     <p>Для того чтобы импортировать библиотеку типов MSXML, выберем пункт меню Project/Import Type Library… (рис. 9.1).</p>
     <image l:href="#img_70.png"/>
     <p><strong>Рис. 9.1</strong>. Импорт MSXML — шаг 1</p>
     <p>В появившемся диалоге выберем пункт "Microsoft XML v3.0 (Version 3.0)" и создадим новый модуль кнопкой Create Unit (рис. 9.2).</p>
     <image l:href="#img_71.png"/>
     <p><strong>Рис. 9.2</strong>. Импорт MSXML — шаг 2</p>
     <p>Получившийся файл <code>MSXML2_TLB.pas</code> присоединим к проекту (Project/Add to Project…); теперь можно приступать к работе.</p>
     <p>Для того чтобы использовать MSXML в нашем проекте, нам потребуется включить модуль <code>MSXML2_TLB</code> в список используемых модулей. Кроме того, для обработки исключений нам также потребуется модуль <code>comobj</code>. В итоге объявление <code>uses</code> будет выглядеть следующим образом:</p>
     <p><code>uses</code></p>
     <p><code> Windows, Messages, SysUtils, Classes, Graphics, Controls,</code></p>
     <p><code> Forms, Dialogs, StdCtrls, ComCtrls, MSXML2_TLB, comobj;</code></p>
    </section>
    <section>
     <title>
      <p>Форма проекта</p>
     </title>
     <p>Нам понадобится форма с тремя страничками и тремя компонентами <code>TMemo</code>. В первом будет показываться исходный текст преобразуемого документа, во втором — XSLT-преобразование и в третьем — результат преобразования.</p>
     <p>Приблизительный внешний вид формы показан на рис. 9.3.</p>
     <image l:href="#img_72.png"/>
     <p><strong>Рис. 9.3</strong>. Внешний вид формы проекта</p>
    </section>
    <section>
     <title>
      <p>Использование <emphasis>DOMDocument</emphasis></p>
     </title>
     <p>Объектная модель XML-документа в импортированной библиотеке будет представлена интерфейсом <code>DOMDocument</code>. В главном модуле проекта мы объявим две переменные, которые будут соответствовать обрабатываемому документу (<code>xmlSource</code>) и документу преобразования (<code>xmlStylesheet</code>):</p>
     <p><code>var</code></p>
     <p><code> xmlSource: DOMDocument;</code></p>
     <p><code> xmlStylesheet: DOMDocument;</code></p>
     <p>Для того чтобы создать экземпляры объектов наших документов, мы воспользуемся классом <code>СoDOMDocument</code>, который был создан в модуле <code>MSXML2_TLB</code> при импортировании. Метод <code>Create</code> этого класса создаст объекты, к методам и свойствам которых мы будем обращаться посредством уже упомянутого интерфейса <code>DOMDocument</code>:</p>
     <p><code>xmlSource := CoDOMDocument.Create;</code></p>
     <p><code>xmlStylesheet := CoDOMDocument.Create;</code></p>
     <p>Для того чтобы загрузить XML-файл, мы воспользуемся функцией <code>load</code> интерфейса <code>DOMDocument</code>:</p>
     <p><code>xmlSource.load('source.xml');</code></p>
     <p>При загрузке файла вполне вероятны ошибки. Например, XML-документ может не являться хорошо оформленным. Для того чтобы успешно справиться с такого рода исключительными ситуациями, мы будем использовать конструкцию <code>try...except</code> и отрабатывать исключение <code>EoleException</code>:</p>
     <p><code>try</code></p>
     <p><code> xmlStylesheet.load('stylesheet.xsl');</code></p>
     <p><code> memoStylesheet.Text := xmlStylesheet.xml;</code></p>
     <p><code>except</code></p>
     <p><code> on e: EOleException do</code></p>
     <p><code>  memoStylesheet.Text := e.Message;</code></p>
     <p><code>end;</code></p>
     <p>Для выполнения самого преобразования нам будет нужно использовать функцию <code>transformNode</code>:</p>
     <p><code>try</code></p>
     <p><code> memoResult.Text := xmlSource.transformNode(xmlStylesheet);</code></p>
     <p><code>except</code></p>
     <p><code> on e: EOleException do</code></p>
     <p><code>  memoResult.Text := e.Message;</code></p>
     <p><code>end;</code></p>
     <p>Для удобства мы можем также добавить диалоги для загрузки файлов и многое другое, но эти усовершенствования мы здесь разбирать не будем. Ограничимся тем, что приведем главную часть исходного кода этого проекта.</p>
     <subtitle>Листинг 9.1. Использование XSLT-преобразования в Delphi</subtitle>
     <p><code>unit source;</code></p>
     <empty-line/>
     <p><code>interface</code></p>
     <empty-line/>
     <p><code>uses</code></p>
     <p><code> Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,</code></p>
     <p><code> StdCtrls, ComCtrls, MSXML2_TLB, comobj;</code></p>
     <empty-line/>
     <p><code>type</code></p>
     <p><code> TMain = class(TForm)</code></p>
     <p><code>  { Компоненты формы и обработчики событий }</code></p>
     <p><code> private</code></p>
     <p><code> public</code></p>
     <p><code> end;</code></p>
     <empty-line/>
     <p><code>var</code></p>
     <p><code> xmlSource: DOMDocument;</code></p>
     <p><code> xmlStylesheet: DOMDocument;</code></p>
     <p><code> Main: TMain;</code></p>
     <empty-line/>
     <p><code>implementation</code></p>
     <empty-line/>
     <p><code>{$R *.DFM}</code></p>
     <empty-line/>
     <p><code>procedure TMain.FormCreate(Sender: Tobject);</code></p>
     <p><code>begin</code></p>
     <p><code> xmlSource := CoDOMDocument.Create;</code></p>
     <p><code> xmlStylesheet := CoDOMDocument.Create;</code></p>
     <empty-line/>
     <p><code> try</code></p>
     <p><code>  xmlSource.load('source.xml');</code></p>
     <p><code>  memoSource.Text := xmlSource.xml;</code></p>
     <p><code> except</code></p>
     <p><code>  on e: EOleException do</code></p>
     <p><code>   memoSource.Text := e.Message;</code></p>
     <p><code> end;</code></p>
     <p><code> try</code></p>
     <p><code>  xmlStylesheet.load('stylesheet.xsl');</code></p>
     <p><code>  memoStylesheet.Text := xmlStylesheet.xml;</code></p>
     <p><code> except</code></p>
     <p><code>  on e: EOleException do</code></p>
     <p><code>   memoStylesheet.Text := e.Message;</code></p>
     <p><code> end;</code></p>
     <p><code>end;</code></p>
     <empty-line/>
     <p><code>procedure TMain.pcMainChange(Sender: TObject);</code></p>
     <p><code>begin</code></p>
     <p><code> if pcMain.ActivePage = sheetResult then</code></p>
     <p><code> try</code></p>
     <p><code>  memoResult.Text := xmlSource.transformNode(xmlStylesheet);</code></p>
     <p><code> except</code></p>
     <p><code>  on e: EOleException do</code></p>
     <p><code>   memoResult.Text := e.Message;</code></p>
     <p><code> end;</code></p>
     <p><code>end;</code></p>
     <empty-line/>
     <p><code>{ Прочие процедуры и функции }</code></p>
     <empty-line/>
     <p><code>end.</code></p>
     <p>Процесс использования нашего приложения приведен на следующих рисунках (рис. 9.4–9.6).</p>
     <image l:href="#img_73.png"/>
     <p><strong>Рис. 9.4</strong>. Входящий документ</p>
     <image l:href="#img_74.png"/>
     <p><strong>Рис. 9.5</strong>. Преобразование</p>
     <image l:href="#img_75.png"/>
     <p><strong>Рис. 9.6</strong>. Выходящий документ</p>
    </section>
   </section>
   <section>
    <title>
     <p>Выполнение XSLT-преобразований в C/C++</p>
    </title>
    <section>
     <p>В качестве примера использования XSLT в языках С и С++ мы приведем очень простую программу, которая выполняет над документом <code>source.xml</code> преобразование <code>stylesheet.xsl</code> и выводит результат в файл <code>document.out</code>. На этот раз в качестве процессора мы будем использовать Xalan-C++, а в качестве среды разработки — Microsoft Visual С++.</p>
    </section>
    <section>
     <title>
      <p>Настройка путей</p>
     </title>
     <p>Для того чтобы использовать библиотеки Xalan в своем проекте, прежде всего, необходимо включить в исходный код файлы заголовков:</p>
     <p><code>#include "util/PlatformUtils.hpp"</code></p>
     <p><code>#include "XalanTransformer/XalanTransformer.hpp"</code></p>
     <p>Файл <code>PlatformUtils.hpp</code> относится к библиотеке Xerces-C++, который используется в Xalan в качестве парсера XML-документов. Файл заголовка <code>XalanTransformer.hpp</code> относится к классу <code>XalanTransformer</code>, который мы и будем использовать для преобразования нашего документа.</p>
     <p>Заголовочные файлы Xalan и Xerces могут быть найдены в поставке Xalan в каталогах <code>xml-xalan\c\src</code> и <code>xml-xerces\c\src</code> соответственно. Для того чтобы они могли быть обнаружены компилятором, эти пути следует явным образом прописать в настройках среды (меню Tools/Options), как показано на рис. 9.7.</p>
     <image l:href="#img_76.png"/>
     <p><strong>Рис. 9.7</strong>. Настройка путей Xalan в MSVC</p>
     <p>Для того чтобы скомпилированный объектный код мог быть скомпонован, в проекте также должны быть указаны пути к библиотечным файлам Xalan (рис. 9.8).</p>
     <image l:href="#img_77.png"/>
     <p><strong>Рис. 9.8</strong>. Настройка путей библиотек в проекте</p>
    </section>
    <section>
     <title>
      <p>Использование класса <emphasis>XalanTransformer</emphasis></p>
     </title>
     <p>Теперь, когда мы разобрались со всякого рода настройками, можно заняться самой программой. Типичный сценарий использования Xalan в программе можно проиллюстрировать следующим кодом.</p>
     <subtitle>Листинг 9.2. Типовой сценарий использования Xalan</subtitle>
     <p><code>// Инициализируем Xerces</code></p>
     <p><code>XMLPlatformUtils::Initialize();</code></p>
     <p><code>// Инициализируем класс XalanTransformer</code></p>
     <p><code>XalanTransformer::initialize();</code></p>
     <p><code>// Создаем экземпляр класса XalanTransformer</code></p>
     <p><code>XalanTransformer theXalanTransformer;</code></p>
     <empty-line/>
     <p><code>...</code></p>
     <p><code>// Выполняем преобразование</code></p>
     <p><code>theXalanTransformer.transform( ... );</code></p>
     <p><code>...</code></p>
     <empty-line/>
     <p><code>// Освобождаем XalanTransformer</code></p>
     <p><code>XalanTransformer::terminate();</code></p>
     <p><code>// Освобождаем Xerces</code></p>
     <p><code>XMLPlatformUtils::Terminate();</code></p>
     <p>В соответствии с этим сценарием наша программа будет выглядеть следующим образом:</p>
     <p><code>#include "StdAfx.h"</code></p>
     <p><code>#include "util/PlatformUtils.hpp"</code></p>
     <p><code>#include "XalanTransformer/XalanTransformer.hpp"</code></p>
     <p><code>#include "strstream"</code></p>
     <empty-line/>
     <p><code>int main(int argc, const char* argv[]) {</code></p>
     <p><code> using std::cerr;</code></p>
     <empty-line/>
     <p><code> // Инициализируем Xerces</code></p>
     <p><code> XMLPlatformUtils::Initialize();</code></p>
     <p><code> // Инициализируем класс XalanTransformer</code></p>
     <p><code> XalanTransformer::initialize();</code></p>
     <p><code> // Создаем экземпляр класса XalanTransformer</code></p>
     <p><code> XalanTransformer theXalanTransformer;</code></p>
     <empty-line/>
     <p><code> // Выполняем преобразование</code></p>
     <p><code> int theResult = theXalanTransformer.transform("source.xml",</code></p>
     <p><code>  "stylesheet.xsl", "document.out");</code></p>
     <empty-line/>
     <p><code> // В случае, если произошла ошибка, выводим, информацию о ней</code></p>
     <p><code> if (theResult != 0) {</code></p>
     <p><code>  cerr &lt;&lt; "XalanError: \n" &lt;&lt; theXalanTransformer.getLastError();</code></p>
     <p><code> }</code></p>
     <empty-line/>
     <p><code> // Освобождаем XalanTransformer</code></p>
     <p><code> XalanTransformer::terminate();</code></p>
     <p><code> // Освобождаем Xerces</code></p>
     <p><code> XMLPlatformUtils::Terminate();</code></p>
     <empty-line/>
     <p><code> return theResult;</code></p>
     <p><code>}</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Выполнение XSLT-преобразований в PHP</p>
    </title>
    <section>
     <p>Начиная с четвертых версий, PHP поставляется вместе с XSLT-процессором Sablotron, который включен в РНР в качестве расширения.</p>
     <p>Для того чтобы использовать Sablotron в PHP-скриптах, следует выполнить следующие действия:</p>
     <p>1. Убедиться, что файл php_sablot.dll присутствует в каталоге расширений.</p>
     <p>2. Убедиться, что в файле php.ini присутствует строка <code>extension=php_sablot.dll</code>.</p>
     <p>3. Убедиться, что библиотеки expat.dll и sablot.dll находятся в каталоге, указанном в переменной окружения <code>PATH</code>.</p>
     <cite>
      <subtitle>Замечание</subtitle>
      <p>Приведенное описание касается только использования Sablotron на платформе Windows32. На других платформах потребуется сконфигурировать РНР с флагом <code>--with-sablot</code>. В остальном установка совершенно аналогична.</p>
     </cite>
     <p>Теперь, когда библиотека Sablotron подключена, мы сможем написать небольшую программу, которая будет выводить страницу гостевой книги.</p>
    </section>
    <section>
     <title>
      <p>Страница гостевой книги</p>
     </title>
     <p>Предположим, что мы храним (или экспортируем) данные гостевой книги в следующем формате.</p>
     <subtitle>Листинг 9.3. Данные гостевой книги — файл source.xml</subtitle>
     <p><code>&lt;page&gt;</code></p>
     <p><code> &lt;date&gt;18/08/2001&lt;/date&gt;</code></p>
     <p><code> &lt;messages&gt;</code></p>
     <p><code>  &lt;message&gt;</code></p>
     <p><code>   &lt;ID&gt;1&lt;/ID&gt;</code></p>
     <p><code>   &lt;POSTED&gt;15/03/45BC&lt;/POSTED&gt;</code></p>
     <p><code>   &lt;PERSON&gt;Julius&lt;/PERSON&gt;</code></p>
     <p><code>   &lt;EMAIL&gt;caesar@hotmail.com&lt;/EMAIL&gt;</code></p>
     <p><code>   &lt;SUBJECT&gt;:(&lt;/SUBJECT&gt;</code></p>
     <p><code>   &lt;MSG&gt;Et tu, Brute...&lt;/MSG&gt;</code></p>
     <p><code>  &lt;/message&gt;</code></p>
     <p><code>  &lt;message&gt;</code></p>
     <p><code>   &lt;ID&gt;2&lt;/ID&gt;</code></p>
     <p><code>   &lt;POSTED&gt;20/07/1969&lt;/POSTED&gt;</code></p>
     <p><code>   &lt;PERSON&gt;Neil&lt;/PERSON&gt;</code></p>
     <p><code>   &lt;SUBJECT&gt;What did I have to say? Oh, yes...&lt;/SUBJECT&gt;</code></p>
     <p><code>   &lt;MSG&gt;One small step for a man; one giant leap for mankind!&lt;/MSG&gt;</code></p>
     <p><code>  &lt;/message&gt;</code></p>
     <p><code> &lt;/messages&gt;</code></p>
     <p><code>&lt;/page&gt;</code></p>
     <p>Для того чтобы вывести форму гостевой книги и сообщения, содержащиеся в <code>source.xml</code>, мы создадим следующее преобразование.</p>
     <subtitle>Листинг 9.4. Преобразование stylesheet.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> &lt;!-- Формат вывода - html --&gt;</code></p>
     <p><code> &lt;xsl:output method="html"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Шаблон обработки корневого узла --&gt;</code></p>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;!-- Создаем форму гостевой книги --&gt;</code></p>
     <p><code>  &lt;form method="POST" action="guestbook.xsql"&gt;</code></p>
     <p><code>   &lt;table&gt;</code></p>
     <p><code>    &lt;tr&gt;</code></p>
     <p><code>     &lt;td&gt;Name&lt;/td&gt;</code></p>
     <p><code>     &lt;td&gt;E-mail&lt;/td&gt;</code></p>
     <p><code>    &lt;/tr&gt;</code></p>
     <p><code>    &lt;tr&gt;</code></p>
     <p><code>     &lt;td&gt;&lt;input class="flat" type="text" name="person"/&gt;&lt;/td&gt;</code></p>
     <p><code>     &lt;td&gt;&lt;input class="flat" type="text" name="email"/&gt;&lt;/td&gt;</code></p>
     <p><code>    &lt;/tr&gt;</code></p>
     <p><code>    &lt;tr&gt;</code></p>
     <p><code>     &lt;td colspan="2"&gt;</code></p>
     <p><code>      &lt;xsl:text&gt;Subject&lt;/xsl:text&gt;&lt;BR/&gt;</code></p>
     <p><code>      &lt;input type="text" name="subject"/&gt;&lt;br/&gt;</code></p>
     <p><code>      &lt;!-- В скрытом поле posted помещаем текущую дату --&gt;</code></p>
     <p><code>      &lt;input type="hidden" name="posted" value="{page/date}"/&gt;&lt;br/&gt;</code></p>
     <p><code>      &lt;textarea rows="10" cols="50" name="msg"/&gt;&lt;br/&gt;&lt;br/&gt;</code></p>
     <p><code>      &lt;input type="submit" value="Post"/&gt;</code></p>
     <p><code>     &lt;/td&gt;</code></p>
     <p><code>    &lt;/tr&gt;</code></p>
     <p><code>   &lt;/table&gt;</code></p>
     <p><code>  &lt;/form&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;!-- Обрабатываем страницу --&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates select="page"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Обработка страницы --&gt;</code></p>
     <p><code> &lt;xsl:template match="page"&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates select="messages"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Обработка сообщений --&gt;</code></p>
     <p><code> &lt;xsl:template match="messages"&gt;</code></p>
     <p><code>  &lt;xsl:apply-templates select="message"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Вывод сообщения --&gt;</code></p>
     <p><code> &lt;xsl:template match="message"&gt;</code></p>
     <p><code>  &lt;p&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;From: &lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:choose&gt;</code></p>
     <p><code>    &lt;!-- Если e-mail не указан, выводим просто имя --&gt;</code></p>
     <p><code>    &lt;xsl:when test="not(EMAIL)"&gt;</code></p>
     <p><code>     &lt;xsl:value-of select="PERSON"/&gt;</code></p>
     <p><code>    &lt;/xsl:when&gt;</code></p>
     <p><code>    &lt;!-- Если e-mail указан, выводим гиперссылку --&gt;</code></p>
     <p><code>    &lt;xsl:otherwise&gt;</code></p>
     <p><code>     &lt;A href="mailto:{EMAIL}"&gt;&lt;xsl:value-of select="PERSON"/&gt;&lt;/A&gt;</code></p>
     <p><code>    &lt;/xsl:otherwise&gt;</code></p>
     <p><code>   &lt;/xsl:choose&gt;</code></p>
     <p><code>   &lt;!-- Выводим дату записи --&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="concat(', ', POSTED)"/&gt;&lt;br/&gt;</code></p>
     <p><code>   &lt;!-- Если была указана тема, выводим ее --&gt;</code></p>
     <p><code>   &lt;xsl:if test="SUBJECT"&gt;</code></p>
     <p><code>    &lt;xsl:text&gt;Subject: &lt;/xsl:text&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="SUBJECT"/&gt;&lt;BR/&gt;</code></p>
     <p><code>   &lt;/xsl:if&gt;</code></p>
     <p><code>   &lt;HR/&gt;</code></p>
     <p><code>   &lt;!-- Выводим текст сообщения --&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="MSG"/&gt;</code></p>
     <p><code>  &lt;/p&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Теперь займемся самим php-скриптом.</p>
     <subtitle>Листинг 9.5. Скрипт guestbook.php</subtitle>
     <p><code>&lt;html&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;title&gt;Guestbook&lt;/title&gt;</code></p>
     <p><code>  &lt;META</code></p>
     <p><code>   http-equiv="Content-Type"</code></p>
     <p><code>   content="text/html; charset=windows-1251"&gt;</code></p>
     <p><code>  &lt;link rel="stylesheet" type="text/css" href="style.css"/&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code> &lt;body&gt;</code></p>
     <p><code>  &lt;?php</code></p>
     <p><code>   // Загружаем входящий документ</code></p>
     <p><code>   $sourcefile = "source.xml";</code></p>
     <p><code>   $sourcehandle = fopen($sourcefile, "r")</code></p>
     <p><code>    or die("Невозможно открыть входящий документ.");</code></p>
     <p><code>   $source = fread($sourcehandle, filesize($sourcefile));</code></p>
     <p><code>   // Загружаем преобразование</code></p>
     <p><code>   $stylesheetfile = "stylesheet.xsl";</code></p>
     <p><code>   $stylesheethandle = fopen($stylesheetfile, "r")</code></p>
     <p><code>    or die("Невозможно открыть файл преобразования");</code></p>
     <p><code>   $stylesheet = fread($stylesheethandle, filesize($stylesheetfile));</code></p>
     <p><code>   // Инициализируем XSLT-процессор</code></p>
     <p><code>   $xslt = @xslt_create() or die("Can't create XSLT handle!");</code></p>
     <p><code>   // Выполняем преобразование</code></p>
     <p><code>   @xslt_process($stylesheet, $source, $result);</code></p>
     <p><code>   // Выводим результат</code></p>
     <p><code>   echo $result;</code></p>
     <p><code>   // Освобождаем ресурсы</code></p>
     <p><code>   @xslt_free($xslt);</code></p>
     <p><code>  ?&gt;</code></p>
     <p><code> &lt;/body&gt;</code></p>
     <p><code>&lt;/html&gt;</code></p>
     <p>Приблизительный результат выполнения этого скрипта можно видеть на рис. 9.9.</p>
     <image l:href="#img_78.png"/>
     <p><strong>Рис. 9.9</strong>. Сгенерированная из PHP-скрипта страница гостевой книги</p>
    </section>
   </section>
   <section>
    <title>
     <p><strong>Выполнение XSLT-преобразований в JavaScript</strong></p>
    </title>
    <p>JavaScript является одним из наиболее популярных скриптовых языков, которые применяются при программировании для Web. В этой главе мы покажем, как при помощи JavaScript и MSXML создать интерактивный каталог, основанный на XML и XSLT.</p>
    <p>Предположим, что каталог организован в виде иерархии категорий приблизительно следующим образом.</p>
    <subtitle>Листинг 9.6. XML-документ каталога</subtitle>
    <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
    <p><code>&lt;catalog&gt;</code></p>
    <p><code> &lt;category title="Компьютеры"&gt;</code></p>
    <p><code>  &lt;category title="Настольные компьютеры"/&gt;</code></p>
    <p><code>  &lt;category title="Серверы"/&gt;</code></p>
    <p><code> &lt;/category&gt;</code></p>
    <p><code> &lt;category title="Комплектующие"&gt;</code></p>
    <p><code>  &lt;category title="Процессоры"/&gt;</code></p>
    <p><code>  &lt;category title="Материнские платы"/&gt;</code></p>
    <p><code> &lt;/category&gt;</code></p>
    <p><code> &lt;category title="Расходные материалы"&gt;</code></p>
    <p><code>  &lt;category title="Картриджи"&gt;</code></p>
    <p><code>   &lt;category title="Картриджи для плоттеров"/&gt;</code></p>
    <p><code>   &lt;category title="Картриджи для принтеров"/&gt;</code></p>
    <p><code>  &lt;/category&gt;</code></p>
    <p><code>  &lt;category title="Тонеры"/&gt;</code></p>
    <p><code>  &lt;category title="Бумага"/&gt;</code></p>
    <p><code> &lt;/category&gt;</code></p>
    <p><code>&lt;/catalog&gt;</code></p>
    <p>При отображении этого дерева мы будем раскрывать только определенную выбранную ветвь категорий. Скажем, если пользователь выбрал категорию "Расходные материалы", показывать информацию о компьютерах мы ему не будем. Иными словами, мы будем показывать только те категории, которые являются надкатегориями выбранной. Для того чтобы сделать это как можно эффективнее, мы выполним следующие шаги.</p>
    <p>&#9633; При помощи ключа и уникального идентификатора, сгенерированного функцией <code>generate-id</code>, мы найдем в дереве требуемую категорию и присвоим ее переменной <code>$category</code>.</p>
    <p>&#9633; Воспользовавшись осью <code>ansector-or-self</code>, мы найдем все надкатегории данной, то есть все категории, которые прямо или косвенно содержат найденную. Путь выборки будет иметь вид <code>$category/ancestor-or-self::category</code>. Найденное множество мы присвоим переменной <code>$path</code>.</p>
    <p>&#9633; При обработке каждой из категорий мы будем обрабатывать ее подкатегории только в том случае, если она является надкатегорией выбранной; иначе говоря — только в том случае, когда ее узел принадлежит множеству узлов <code>$path</code>. Проверять это мы будем при помощи условия <code>count(.|$path)=count($path)</code>.</p>
    <p>Искомое преобразование в итоге запишется в виде.</p>
    <subtitle>Листинг 9.7. Преобразование обрабатывающее наш каталог</subtitle>
    <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <p><code> &lt;!-- Выводим документ в формате html и кодировке windows-1251 --&gt;</code></p>
    <p><code> &lt;xsl:output method="html" encoding="windows-1251"/&gt;</code></p>
    <p><code> &lt;!--</code></p>
    <p><code>  | Переменная, которая содержит уникальный</code></p>
    <p><code>  | идентификатор выбранного узла дерева</code></p>
    <p><code>  +--&gt;</code></p>
    <p><code> &lt;xsl:param name="current" select="''"/&gt;</code></p>
    <p><code> &lt;!-- Определение ключа категории --&gt;</code></p>
    <p><code> &lt;xsl:key name="cat" match="category" use="generate-id(.)"/&gt;</code></p>
    <p><code> &lt;!-- Находим текущую категорию --&gt;</code></p>
    <p><code> &lt;xsl:variable name="category" select="key('cat',$current)"/&gt;</code></p>
    <p><code> &lt;!--</code></p>
    <p><code>  | Находим надкатегории текущей категории, узлы которых</code></p>
    <p><code>  | мы будем раскрывать в дереве</code></p>
    <p><code>  +--&gt;</code></p>
    <p><code> &lt;xsl:variable name="path"</code></p>
    <p><code>  select="$category/ancestor-or-self::category"/&gt;</code></p>
    <empty-line/>
    <p><code> &lt;!-- Шаблон обработки каталога --&gt;</code></p>
    <p><code> &lt;xsl:template match="catalog"&gt;</code></p>
    <p><code>  &lt;xsl:apply-templates select="category"/&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;!-- Шаблон обработки категории--&gt;</code></p>
    <p><code> &lt;xsl:template match="category"&gt;</code></p>
    <p><code>  &lt;!-- Параметр, указывающий отступ --&gt;</code></p>
    <p><code>  &lt;xsl:param name="indent"/&gt;</code></p>
    <p><code>  &lt;!-- Выводим отступ --&gt;</code></p>
    <p><code>  &lt;xsl:value-of select="$indent"/&gt;</code></p>
    <p><code>  &lt;!-- Выводим информацию о категории в виде ссылки --&gt;</code></p>
    <p><code>  &lt;а href="javascript:expand('{generate-id(.)}')"&gt;</code></p>
    <p><code>   &lt;!-- Перед названием категории выводим соответствующую иконку --&gt;</code></p>
    <p><code>   &lt;img height="11" width="11" border="0"&gt;</code></p>
    <p><code>    &lt;xsl:choose&gt;</code></p>
    <p><code>     &lt;!--</code></p>
    <p><code>      | Если категория не содержит субэлементов,</code></p>
    <p><code>      | выводим иконку с точкой</code></p>
    <p><code>      +--&gt;</code></p>
    <p><code>     &lt;xsl:when test="not(*)"&gt;</code></p>
    <p><code>      &lt;xsl:attribute name="src"&gt;images/dot.gif&lt;/xsl:attribute&gt;</code></p>
    <p><code>     &lt;/xsl:when&gt;</code></p>
    <p><code>     &lt;!--</code></p>
    <p><code>      | Если категория принадлежит ветке выбранной категории,</code></p>
    <p><code>      | выводим иконку с минусом, что означает раскрытую ветку</code></p>
    <p><code>      +--&gt;</code></p>
    <p><code>     &lt;xsl:when test="count(.|$path)=count($path)"&gt;</code></p>
    <p><code>      &lt;xsl:attribute name="src"&gt;images/minus.gif&lt;/xsl:attribute&gt;</code></p>
    <p><code>     &lt;/xsl:when&gt;</code></p>
    <p><code>     &lt;!--</code></p>
    <p><code>      | Если категория не принадлежит ветке выбранной категории,</code></p>
    <p><code>      | выводим иконку с плюсом, что означает нераскрытую ветку</code></p>
    <p><code>      +--&gt;</code></p>
    <p><code>     &lt;xsl:otherwise&gt;</code></p>
    <p><code>      &lt;xsl:attribute name="src"&gt;images/plus.gif&lt;/xsl:attribute&gt;</code></p>
    <p><code>     &lt;/xsl:otherwise&gt;</code></p>
    <p><code>    &lt;/xsl:choose&gt;</code></p>
    <p><code>   &lt;/img&gt;</code></p>
    <p><code>   &lt;!--</code></p>
    <p><code>    | Выводим неразрывный пробел.</code></p>
    <p><code>    | &amp;#xA0; в Unicode соответствует &amp;nbsp;</code></p>
    <p><code>    +--&gt;</code></p>
    <p><code>   &lt;xsl:text&gt;&amp;#xA0;&lt;/xsl:text&gt;</code></p>
    <p><code>   &lt;!-- Выводим название категории --&gt;</code></p>
    <p><code>   &lt;xsl:value-of select="@title"/&gt;</code></p>
    <p><code>  &lt;/a&gt;</code></p>
    <p><code>  &lt;br/&gt;&lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
    <p><code>  &lt;!--</code></p>
    <p><code>   | Если категория принадлежит раскрываемой ветке,</code></p>
    <p><code>   | обрабатываем ее подкатегории</code></p>
    <p><code>   +--&gt;</code></p>
    <p><code>  &lt;xsl:if test="count(.|$path)=count($path)"&gt;</code></p>
    <p><code>   &lt;xsl:apply-templates select="category"&gt;</code></p>
    <p><code>    &lt;!-- Увеличиваем отступ на три пробела --&gt;</code></p>
    <p><code>    &lt;xsl:with-param name="indent"</code></p>
    <p><code>     select="concat($indent,'&amp;#xA0;&amp;#xA0;&amp;#xA0;')"/&gt;</code></p>
    <p><code>   &lt;/xsl:apply-templates&gt;</code></p>
    <p><code>  &lt;/xsl:if&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>Теперь осталось лишь только создать страницу, которая при помощи JavaScript и MSXML будет выполнять преобразования и выводить результат.</p>
    <p>Для того чтобы воспользоваться возможностями MSXML, мы включим в нашу страницу два объекта:</p>
    <p><code>&lt;!-- Объект, представляющий входящий документ --&gt;</code></p>
    <p><code>&lt;object</code></p>
    <p><code> id="source"</code></p>
    <p><code> width="0"</code></p>
    <p><code> height="0"</code></p>
    <p><code> classid="clsid:f5078f32-c551-11d3-89b9-0000f81fe221"&gt;</code></p>
    <p><code> &lt;param name="async" value="false"&gt;</code></p>
    <p><code> &lt;param name="validateOnParse" value="false"&gt;</code></p>
    <p><code>&lt;/object&gt;</code></p>
    <p><code>&lt;!-- Объект, представляющий документ преобразования --&gt;</code></p>
    <p><code>&lt;object</code></p>
    <p><code> id="stylesheet"</code></p>
    <p><code> width="0"</code></p>
    <p><code> height="0"</code></p>
    <p><code> classid="clsid:f5078f32-c551-11d3-89b9-0000f81fe221"&gt;</code></p>
    <p><code> &lt;param name="async" value="false"&gt;</code></p>
    <p><code> &lt;param name="validateOnParse" value="false"&gt;</code></p>
    <p><code>&lt;/object&gt;</code></p>
    <p>"Магический" код <code>clsid:f5078f32-c551-11d3-89b9-0000f81fe221</code>, который присутствует в тегах обоих объектов, на самом деле не что иное, как уникальный идентификатор библиотеки MSXML 3.0, которую мы и будем использовать для выполнения преобразования. Итак, код нашей HTML- страницы будет выглядеть следующим образом.</p>
    <subtitle>Листинг 9.8. Код HTML-страницы</subtitle>
    <p><code>&lt;html&gt;</code></p>
    <p><code> &lt;head&gt;</code></p>
    <p><code>  &lt;meta</code></p>
    <p><code>   http-equiv="Content-Type"</code></p>
    <p><code>   content="text/html; charset=windows-1251" /&gt;</code></p>
    <p><code>  &lt;style type="text/css"&gt;</code></p>
    <p><code>   body {font-family:Tahoma,Verdana,Arial,sans-serif; font-size:14px}</code></p>
    <p><code>   a:link {COLOR:#990000; BACKGROUND: #ffffff; TEXT-DECORATION: none}</code></p>
    <p><code>   a:hover {BACKGROUND: #dddddd; TEXT-DECORATION: none}</code></p>
    <p><code>   a:visited {COLOR: #990000; TEXT-DECORATION: none}</code></p>
    <p><code>  &lt;/style&gt;</code></p>
    <p><code>  &lt;script language="JavaScript"&gt;</code></p>
    <p><code>   &lt;!--</code></p>
    <p><code>   // Объявляем глобальные переменные</code></p>
    <p><code>   // Входящий документ</code></p>
    <p><code>   var source;</code></p>
    <p><code>   // Преобразование</code></p>
    <p><code>   var stylesheet;</code></p>
    <p><code>   // Результат</code></p>
    <p><code>   var result;</code></p>
    <empty-line/>
    <p><code>   // Функция, выполняющая действия по инициализации</code></p>
    <p><code>   function init() {</code></p>
    <p><code>    // Инициализируем ссылку на объект входящего документа</code></p>
    <p><code>    source = document.all['source'];</code></p>
    <p><code>    // Загружаем входящий документ</code></p>
    <p><code>    source.load('source.xml');</code></p>
    <p><code>    // Инициализируем ссылку на объект преобразования</code></p>
    <p><code>    stylesheet = document.all['stylesheet'];</code></p>
    <p><code>    // Загружаем документ преобразования</code></p>
    <p><code>    stylesheet.load('stylesheet.xsl');</code></p>
    <p><code>    // Находим элемент, в который мы будем выводить</code></p>
    <p><code>    // результат обработки</code></p>
    <p><code>    result = document.all['result'];</code></p>
    <p><code>   }</code></p>
    <empty-line/>
    <p><code>   // Функция, выполняющая "раскрытие"</code></p>
    <p><code>   //определенной ветки дерева категорий.</code></p>
    <p><code>   function expand(id) {</code></p>
    <p><code>    // Получаем ссылку на атрибут select</code></p>
    <p><code>    // объявления параметра current</code></p>
    <p><code>    var attSelect = stylesheet.selectSingleNode(</code></p>
    <p><code>     "/xsl:stylesheet/xsl:param[@name='current']/@select");</code></p>
    <p><code>    // Изменяем значение этого атрибута. Одинарные кавычки необходимы</code></p>
    <p><code>    // для того, чтобы новое значение воспринималось как литерал.</code></p>
    <p><code>    attSelect.nodeValue = "'" + id + "'";</code></p>
    <p><code>    // Выполняем преобразование</code></p>
    <p><code>    strResult = source.transformNode(stylesheet);</code></p>
    <p><code>    // Обновляем страницу</code></p>
    <p><code>    result.innerHTML = strResult;</code></p>
    <p><code>   }</code></p>
    <p><code>   //--&gt;</code></p>
    <p><code>  &lt;/script&gt;</code></p>
    <p><code> &lt;/head&gt;</code></p>
    <p><code> &lt;body onload="init()"&gt;</code></p>
    <p><code>  &lt;!-- Объект, представляющий входящий документ --&gt;</code></p>
    <p><code>  &lt;object</code></p>
    <p><code>   id="source"</code></p>
    <p><code>   width="0"</code></p>
    <p><code>   height="0"</code></p>
    <p><code>   classid="clsid:f5078f32-c551-11d3-89b9-0000f81fe221"&gt;</code></p>
    <p><code>   &lt;param name="async" value="false"&gt;</code></p>
    <p><code>   &lt;param name="validateOnParse" value="false"&gt;</code></p>
    <p><code>  &lt;/object&gt;</code></p>
    <p><code>  &lt;!-- Объект, представляющий документ преобразования --&gt;</code></p>
    <p><code>  &lt;object</code></p>
    <p><code>   id="stylesheet"</code></p>
    <p><code>   width="0"</code></p>
    <p><code>   height="0"</code></p>
    <p><code>   classid="clsid:f5078f32-c551-11d3-89b9-0000f81fe221"&gt;</code></p>
    <p><code>   &lt;param name="async" value="false"&gt;</code></p>
    <p><code>   &lt;param name="validateOnParse" value="false"&gt;</code></p>
    <p><code>  &lt;/object&gt;</code></p>
    <p><code>  &lt;a href="javascript:expand(' ')"&gt;Каталог&lt;/а&gt;</code></p>
    <p><code>  &lt;!-- В этом элементе мы будем выводить результат --&gt;</code></p>
    <p><code>  &lt;div id="result"/&gt;</code></p>
    <p><code> &lt;/body&gt;</code></p>
    <p><code>&lt;/html&gt;</code></p>
    <p>В браузере эта страница будет выглядеть следующим образом (рис. 9.10).</p>
    <image l:href="#img_79.png"/>
    <p><strong>Рис. 9.10</strong>. Динамический каталог на HTML с использованием JavaScript, MSXML на основе XML и XSLT</p>
   </section>
   <section>
    <title>
     <p>Выполнение XSLT-преобразований в VBScript/ASP</p>
    </title>
    <p>Использование MSXML на стороне сервера не сильно отличается от клиентской версии, которую мы разобрали выше. Поскольку MSXML является стандартным СОМ-объектом, его можно использовать в любом языке программирования, умеющем работать с COM. В следующем примере будет показано, как можно использовать MSXML в ASP-странице, написанной на языке VBScript. Мы напишем небольшое Web-приложение, которое позволит отправлять короткие сообщения (SMS) через разные службы, используя один интерфейс.</p>
    <p>Почти у всех операторов мобильной связи формы для отправки сообщений более или менее стандартны, например:</p>
    <p><code>&lt;form action=" http://www.bmtelecom.ru/wap/xm.php?snd=1 " method="POST"&gt;</code></p>
    <p><code> &lt;input type="hidden" name="num" value="<emphasis>номер телефона</emphasis>"&gt;</code></p>
    <p><code> &lt;textarea rows="10" cols="50" name="msg"&gt;<emphasis>текст сообщения</emphasis>&lt;/textarea&gt;</code></p>
    <p><code> &lt;br&gt;&lt;br&gt;</code></p>
    <p><code> &lt;input class="flat" type="submit" value="Послать сообщение"&gt;</code></p>
    <p><code>&lt;/form&gt;</code></p>
    <p>При этом различаться могут адреса служб отправки сообщений, методы отправки форм и наименования полей ввода. Все это мы можем описать в отдельном документе.</p>
    <subtitle>Листинг 9.9. Документ, описывающий формы служб отправки сообщений — services.xml</subtitle>
    <p><code>&lt;services&gt;</code></p>
    <p><code> &lt;service id="MTNSMS"&gt;</code></p>
    <p><code>  &lt;action&gt;http://www.mtnsms.com/sendsms.php&lt;/action&gt;</code></p>
    <p><code>  &lt;method&gt;GET&lt;/method&gt;</code></p>
    <p><code>  &lt;text&gt;msg&lt;/text&gt;</code></p>
    <p><code>  &lt;number&gt;num&lt;/number&gt;</code></p>
    <p><code> &lt;/service&gt;</code></p>
    <empty-line/>
    <p><code> &lt;service id="SMSHost"&gt;</code></p>
    <p><code>  &lt;action&gt;http://www.smshost.net/servlets/sms&lt;/action&gt;</code></p>
    <p><code>  &lt;method&gt;POST&lt;/method&gt;</code></p>
    <p><code>  &lt;text&gt;message&lt;/text&gt;</code></p>
    <p><code>  &lt;number&gt;phone&lt;/number&gt;</code></p>
    <p><code> &lt;/service&gt;</code></p>
    <p><code>&lt;/services&gt;</code></p>
    <p>Контакт-лист после этого может быть оформлен следующим образом.</p>
    <subtitle>Листинг 9.10. Контакт-лист — документ source.xml</subtitle>
    <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
    <p><code>&lt;people&gt;</code></p>
    <p><code> &lt;person id="p1"&gt;</code></p>
    <p><code>  &lt;name&gt;Иван Иванович&lt;/name&gt;</code></p>
    <p><code>  &lt;number&gt;18005557684&lt;/number&gt;</code></p>
    <p><code>  &lt;service id="MTNSMS"/&gt;</code></p>
    <p><code> &lt;/person&gt;</code></p>
    <p><code> &lt;person id="p2"&gt;</code></p>
    <p><code>  &lt;name&gt;Иван Никифорович&lt;/name&gt;</code></p>
    <p><code>  &lt;number&gt;447856273447&lt;/number&gt;</code></p>
    <p><code>  &lt;service id="SMSHost"/&gt;</code></p>
    <p><code> &lt;/person&gt;</code></p>
    <p><code>&lt;/people&gt;</code></p>
    <p>Преобразование, генерирующее HTML-страницу с формой отправки можно задать как.</p>
    <subtitle>Листинг 9.11. Преобразование stylesheet.xsl</subtitle>
    <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transfоrm"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:output</code></p>
    <p><code>  method="html"</code></p>
    <p><code>  indent="yes"</code></p>
    <p><code>  encoding="windows-1251"/&gt;</code></p>
    <empty-line/>
    <p><code> &lt;!-- Параметр, указывающий выбранного адресата, по умолчанию - p1 --&gt;</code></p>
    <p><code> &lt;xsl:param name="id" select="p1"/&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="/"&gt;</code></p>
    <p><code>  &lt;html&gt;</code></p>
    <p><code>   &lt;xsl:call-template name="head"/&gt;</code></p>
    <p><code>   &lt;body&gt;</code></p>
    <p><code>    &lt;xsl:apply-templates select="people"/&gt;</code></p>
    <p><code>   &lt;/body&gt;</code></p>
    <p><code>  &lt;/html&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="people"&gt;</code></p>
    <p><code>  &lt;!-- Создаем список адресатов --&gt;</code></p>
    <p><code>  &lt;xsl:apply-templates select="person"/&gt;</code></p>
    <p><code>  &lt;!-- Создаем форму для выбранного адресата --&gt;</code></p>
    <p><code>  &lt;xsl:apply-templates select="person[@id=$id]" mode="form"/&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="person"&gt;</code></p>
    <p><code>  &lt;!-- Если текущий адресат выбран --&gt;</code></p>
    <p><code>  &lt;xsl:if test="@id = $id"&gt;</code></p>
    <p><code>   &lt;!-- Выводим его имя в квадратных скобках и без гиперссылки --&gt;</code></p>
    <p><code>   &lt;xsl:text&gt;&amp;#xA0;[&amp;#хА0;&lt;/xsl:text&gt;</code></p>
    <p><code>   &lt;xsl:value-of select="name"/&gt;</code></p>
    <p><code>   &lt;xsl:text&gt;&amp;#xA0;]&amp;#xA0;&lt;/xsl:text&gt;</code></p>
    <p><code>  &lt;/xsl:if&gt;</code></p>
    <p><code>  &lt;!-- Если адресат не выбран --&gt;</code></p>
    <p><code>  &lt;xsl:if test="@id != $id"&gt;</code></p>
    <p><code>   &lt;!-- Выводим его имя без скобок и с гиперссылкой --&gt;</code></p>
    <p><code>   &lt;xsl:text&gt;&amp;#xA0;&amp;#хА0;&amp;#хА0;&lt;/xsl:text&gt;</code></p>
    <p><code>   &lt;A href="sms.asp?id={@id}"&gt;</code></p>
    <p><code>    &lt;xsl:value-of select="name"/&gt;</code></p>
    <p><code>   &lt;/A&gt;</code></p>
    <p><code>   &lt;xsl:text&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&lt;/xsl:text&gt;</code></p>
    <p><code>  &lt;/xsl:if&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;!-- Шаблон создания формы для выбранного адресата --&gt;</code></p>
    <p><code> &lt;xsl:template match="person" mode="form"&gt;</code></p>
    <p><code>  &lt;!--</code></p>
    <p><code>   | Находим элемент, описывающий параметры службы отправки сообщений</code></p>
    <p><code>   | текущему адресату</code></p>
    <p><code>   +--&gt;</code></p>
    <p><code>  &lt;xsl:variable name="service"</code></p>
    <p><code>   select="document('services.xml')/services/</code></p>
    <p><code>   service[@id = current()/service/@id]"/&gt;</code></p>
    <p><code>  &lt;br/&gt;</code></p>
    <p><code>  &lt;form</code></p>
    <p><code>   action="{$service/action}" method="{$service/method}"&gt;</code></p>
    <p><code>   &lt;input type="hidden"</code></p>
    <p><code>    name="{$service/number}"</code></p>
    <p><code>    value="{number}"/&gt;</code></p>
    <p><code>   &lt;textarea class="no-scrollbar" rows="10" cols="50"</code></p>
    <p><code>    name="{$service/text}"/&gt;</code></p>
    <p><code>   &lt;br/&gt;</code></p>
    <p><code>   &lt;input class="flat" type="submit" value="Послать сообщение"/&gt;</code></p>
    <p><code>  &lt;/form&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template name="head"&gt;</code></p>
    <p><code>  &lt;head&gt;</code></p>
    <p><code>   &lt;title&gt;SMS Center&lt;/title&gt;</code></p>
    <p><code>   &lt;link rel="stylesheet" type="text/css" href="style.css"/&gt;</code></p>
    <p><code>  &lt;/head&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>Теперь дело осталось за ASP-страницей, которая применяла бы преобразование <code>stylesheet.xsl</code> к документу <code>source.xml</code> и возвращала результат клиенту.</p>
    <subtitle>Листинг 9.12. ASP-страница, использующая XSLT-преобразования</subtitle>
    <p><code>&lt;%@ LANGUAGE = VBScript %&gt;</code></p>
    <p><code>&lt;%</code></p>
    <p><code> ' Загружаем входящий документ</code></p>
    <p><code> Dim source</code></p>
    <p><code> Set source = Server.CreateObject("MSXML2.FreeThreadedDOMDocument.3.0")</code></p>
    <p><code> source.load Server.MapPath("source.xml")</code></p>
    <empty-line/>
    <p><code> ' Загружаем преобразование</code></p>
    <p><code> Dim stylesheet</code></p>
    <p><code> Set stylesheet =</code></p>
    <p><code>  Server.CreateObject("MSXML2.FreeThreadedDOMDocument.3.0")</code></p>
    <p><code> stylesheet.load Server.MapPath("stylesheet.xsl")</code></p>
    <empty-line/>
    <p><code> ' Создаем объект XSLTemplate для преобразования</code></p>
    <p><code> Dim templates</code></p>
    <p><code> Set templates = Server.CreateObject("MSXML2.XSLTemplate")</code></p>
    <p><code> templates.stylesheet = stylesheet.documentElement</code></p>
    <empty-line/>
    <p><code> ' Создаем объект XSLT-процессора</code></p>
    <p><code> Dim processor</code></p>
    <p><code> Set processor = templates.createProcessor</code></p>
    <p><code> processor.input = source</code></p>
    <empty-line/>
    <p><code> ' Присваиваем параметру id значение параметра запроса id</code></p>
    <p><code> ' (то, что передано в sms.asp?id=...)</code></p>
    <p><code> processor.addParameter "id", "" + Request.QueryString("id"), ""</code></p>
    <p><code> ' Выполняем преобразование</code></p>
    <p><code> processor.transform</code></p>
    <p><code> ' Возвращаем результат</code></p>
    <p><code> Response.Charset = "windows-1251"</code></p>
    <p><code> Response.Write processor.output</code></p>
    <p><code>%&gt;</code></p>
    <p>На рис. 9.11 показаны результаты работы <code>sms.asp</code> для i<code>d=p1</code> и <code>id=p2</code>.</p>
    <image l:href="#img_80.png"/>
    <p><strong>Рис. 9.11</strong>. Внешний вид страницы, возвращаемой <code>sms.asp</code></p>
    <p>При вызове страницы <code>sms.asp</code> или <code>sms.asp?id=p1</code> форма отправки сообщений будет сгенерирована в следующем виде:</p>
    <p><code>&lt;form action="http://www.mtnsms.com/sendsms.php" method="GET"&gt;</code></p>
    <p><code> &lt;input type="hidden" name="num" value="18005557684"&gt;</code></p>
    <p><code> &lt;textarea class="no-scrollbar" rows="10" cols="50" name="msg"&gt;</code></p>
    <p><code> &lt;/textarea&gt;</code></p>
    <p><code> &lt;br&gt;&lt;br&gt;</code></p>
    <p><code> &lt;input class="flat" type="submit" value="Послать сообщение"&gt;</code></p>
    <p><code>&lt;/form&gt;</code></p>
    <p>Для <code>sms.asp?id=p2</code> форма будет иметь вид:</p>
    <p><code>&lt;form action="http://www.smshost.net/servlets/sms" method="POST"&gt;</code></p>
    <p><code> &lt;input type="hidden" name="phone" value="447856273447"&gt;</code></p>
    <p><code> &lt;textarea class="no-scrollbar" rows="10" cols="50" name="message"&gt;</code></p>
    <p><code> &lt;/textarea&gt;</code></p>
    <p><code> &lt;br&gt;&lt;br&gt;</code></p>
    <p><code> &lt;input class="flat" type="submit" value="Послать сообщение"&gt;</code></p>
    <p><code>&lt;/form&gt;</code></p>
   </section>
   <section>
    <title>
     <p>Выполнение XSLT-преобразований в Python</p>
    </title>
    <p>Пример использования XSLT-преобразований в Python, который мы продемонстрируем ниже, будет основываться на использовании библиотек 4Suite и PyXML.</p>
    <p>Простейший скрипт, преобразующий документ <code>source.xml</code> при помощи преобразования <code>stylesheet.xsl</code> будет выглядеть следующим образом.</p>
    <subtitle>Листинг 9.13. Простейший вызов 4Suite</subtitle>
    <p><code>python -с "import sys;from xml.xslt import _4xslt;_4xslt.Run(sys.argv[1:])" -i source.xml stylesheet.xsl</code></p>
    <p>Использование XSLT-процессора в собственных программах на Python ненамного сложнее.</p>
    <subtitle>Листинг 9.14. Использование XSLT-процессора в Python</subtitle>
    <p><code># Импортируем библиотеки</code></p>
    <p><code>import sys</code></p>
    <p><code>from xml.xslt.Processor import Processor</code></p>
    <p><code># Создаем XSLT-процессор</code></p>
    <p><code>processor = Processor()</code></p>
    <p><code># Загружаем XSLT-преобразование</code></p>
    <p><code>processor.appendStylesheetUri('stylesheet.xsl')</code></p>
    <p><code># Выполняем преобразование</code></p>
    <p><code>result = processor.runUri('source.xml')</code></p>
    <p><code># Выводим результирующий документ print result</code></p>
   </section>
   <section>
    <title>
     <p>Выполнение XSLT-преобразований в PL/SQL</p>
    </title>
    <p>Универсальность технологии XSLT позволяет использовать ее на самых различных уровнях архитектуры приложений. В этом разделе мы приведем пример использования преобразований внутри базы данных.</p>
    <p>На этот раз в качестве целевой платформы будет использоваться база данных Oracle 8i, которая обеспечивает поддержку XSLT несколькими встроенными пакетами: <code>XMLDOM</code>, <code>XMLPARSER</code> и <code>XSLPROCESSOR</code>.</p>
    <p>Представим себе следующую схему элементарной БД (рис. 9.12):</p>
    <image l:href="#img_81.png"/>
    <p><strong>Рис. 9.12</strong>. Схема простой базы данных</p>
    <p>Таблица STYLESHEET содержит XSLT-преобразования, которые хранятся в полях <code>CONTENT</code>, поле <code>ID</code> указывает уникальный идентификатор каждого из них.</p>
    <p>Таблица <code>SOURCE</code> содержит XML-документы (поле <code>CONTENT</code>), каждому из которых соответствует некоторое преобразование (внешний ключ <code>STYLESHEETID</code>). Нашей задачей будет создание представления, в котором документы, хранящиеся в таблице <code>SOURCE</code>, будут обрабатываться соответствующими преобразованиями из таблицы <code>STYLESHEET</code>.</p>
    <p>Прежде всего, создадим таблицы и ключи, соответствующие приведенной выше схеме базы данных.</p>
    <subtitle>Листинг 9.15. Создание схемы БД</subtitle>
    <p><code>-- Создаем таблицу stylesheet</code></p>
    <p><code>CREATE TABLE STYLESHEET</code></p>
    <p><code> (ID     INTEGER NOT NULL,</code></p>
    <p><code> CONTENT CLOB NULL);</code></p>
    <empty-line/>
    <p><code>-- Создаем первичный ключ таблицы STYLESHEET</code></p>
    <p><code>ALTER TABLE STYLESHEET</code></p>
    <p><code> ADD (PRIMARY KEY (ID));</code></p>
    <empty-line/>
    <p><code>-- Создаем таблицу SOURCE</code></p>
    <p><code>CREATE TABLE SOURCE</code></p>
    <p><code> (ID          INTEGER NOT NULL,</code></p>
    <p><code> CONTENT      CLOB NULL,</code></p>
    <p><code> STYLESHEETID INTEGER NOT NULL);</code></p>
    <empty-line/>
    <p><code>-- Создаем первичный ключ таблицы SOURCE</code></p>
    <p><code>ALTER TABLE SOURCE</code></p>
    <p><code> ADD (PRIMARY KEY (ID));</code></p>
    <empty-line/>
    <p><code>-- Создаем внешний ключ, связывающий таблицы SOURCE и STYLESHEET</code></p>
    <p><code>ALTER TABLE SOURCE</code></p>
    <p><code> ADD (FOREIGN KEY (STYLESHEETID) REFERENCES STYLESHEET);</code></p>
    <p>После того, как схема базы данных была создана, в нее можно добавить записи, содержащие преобразования и обрабатываемые ими документы. Мы ограничимся простым преобразованием и еще более простым документом.</p>
    <subtitle>Листинг 9.16. Преобразование</subtitle>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <p><code> &lt;xsl:template match="A"&gt;</code></p>
    <p><code>  &lt;B&gt;&lt;xsl:value-of select="."/&gt;&lt;/B&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <subtitle>Листинг 9.17. Обрабатываемый документ</subtitle>
    <p><code>&lt;A&gt;value&lt;/A&gt;</code></p>
    <subtitle>Листинг 9.18. SQL-скрипт, загружающий документ и преобразование в БД</subtitle>
    <p><code>-- Сохраняем преобразование</code></p>
    <p><code>INSERT INTO STYLESHEET VALUES</code></p>
    <p><code>(1, '&lt;xsl:stylesheet                                     '||</code></p>
    <p><code>    ', version="1.0"                                     '||</code></p>
    <p><code>    '  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; '||</code></p>
    <p><code>    '  &lt;xsl:template match="A"&gt;                          '||</code></p>
    <p><code>    '   &lt;B&gt;&lt;xsl:value-of select="."/&gt;&lt;/B&gt;                '||</code></p>
    <p><code>    '   &lt;/xsl:template&gt;                                  '||</code></p>
    <p><code>    '  &lt;/xsl:stylesheet&gt;                                 ');</code></p>
    <empty-line/>
    <p><code>-- Сохраняем документ</code></p>
    <p><code>INSERT INTO SOURCE VALUES</code></p>
    <p><code>(1, '&lt;A&gt;value&lt;/A&gt;', 1);</code></p>
    <p>Для того чтобы выполнять преобразования в <code>SELECT</code>-выражении представления таблицы <code>SOURCE</code>, мы напишем функцию <code>PROCESS</code>, которая будет возвращать результат обработки документа с уникальным идентификатором, заданным параметром <code>sourceID</code>.</p>
    <subtitle>Листинг 9.19. Функция PROCESS</subtitle>
    <p><code>CREATE OR REPLACE FUNCTION PROCESS (sourceID NUMBER) RETURN VARCHAR2 IS</code></p>
    <empty-line/>
    <p><code> -- Инициализация XML-парсера и XSLT-процессора</code></p>
    <p><code> parser XMLPARSER.Parser := XMLPARSER.newParser;</code></p>
    <p><code> processor XSLPROCESSOR.Processor := XSLPROCESSOR.newProcessor;</code></p>
    <empty-line/>
    <p><code> -- Переменные для CLOB-значений входящего документа и преобразования</code></p>
    <p><code> sourceCLOB CLOB;</code></p>
    <p><code> stylesheetCLOB CLOB;</code></p>
    <empty-line/>
    <p><code> -- Переменные для DOM-объектов входящего документа и преобразования</code></p>
    <p><code> sourceXML XMLDOM.DOMDocument;</code></p>
    <p><code> stylesheetXML XMLDOM.DOMDocument;</code></p>
    <empty-line/>
    <p><code> -- Переменная для объекта преобразования</code></p>
    <p><code> stylesheet XSLPROCESSOR.Stylesheet;</code></p>
    <empty-line/>
    <p><code> -- Переменная результата</code></p>
    <p><code> result varchar2(32767);</code></p>
    <empty-line/>
    <p><code>BEGIN</code></p>
    <empty-line/>
    <p><code> -- Получаем CLOB-значение входящего документа в переменную sourceCLOB</code></p>
    <p><code> SELECT CONTENT</code></p>
    <p><code> INTO sourceCLOB</code></p>
    <p><code> FROM SOURCE</code></p>
    <p><code> WHERE ID = sourceID;</code></p>
    <empty-line/>
    <p><code> -- Получаем CLOB-значение соответствующего преобразования</code></p>
    <p><code> SELECT STYLESHEET.CONTENT</code></p>
    <p><code> INTO stylesheetCLOB</code></p>
    <p><code> FROM STYLESHEET, SOURCE</code></p>
    <p><code> WHERE SOURCE.ID = sourceID AND SOURCE.STYLESHEETID = STYLESHEET.ID;</code></p>
    <empty-line/>
    <p><code> -- Если хотя бы одно из значений - NULL, прерываем обработку</code></p>
    <p><code> -- и возвращаем NULL</code></p>
    <p><code> IF sourceCLOB IS NULL OR stylesheetCLOB IS NULL THEN</code></p>
    <p><code>  RETURN NULL;</code></p>
    <p><code> END IF;</code></p>
    <empty-line/>
    <p><code> -- Разбираем CLOB-значение входящего документа</code></p>
    <p><code> XMLPARSER.parseCLOB(parser, sourceCLOB);</code></p>
    <p><code> sourceXML := XMLPARSER.getDocument(parser);</code></p>
    <empty-line/>
    <p><code> -- Разбираем CLOB-значение документа преобразования</code></p>
    <p><code> XMLPARSER.parseCLOB(parser, stylesheetCLOB);</code></p>
    <p><code> stylesheetXML := XMLPARSER.getDocument(parser);</code></p>
    <empty-line/>
    <p><code> -- Инициализируем объект преобразования</code></p>
    <p><code> stylesheet := XSLPROCESSOR.newStylesheet(stylesheetXML, NULL);</code></p>
    <empty-line/>
    <p><code> -- Выполняем преобразование</code></p>
    <p><code> XSLPROCESSOR.processXSL(processor, stylesheet, sourceXML, result);</code></p>
    <empty-line/>
    <p><code> -- Освобождаем ресурсы</code></p>
    <p><code> XSLPROCESSOR.freeProcessor(processor);</code></p>
    <p><code> XMLPARSER.freeParser(parser);</code></p>
    <p><code> XMLDOM.freeDocument(sourceXML);</code></p>
    <p><code> XMLDOM.freeDocument(stylesheetXML);</code></p>
    <p><code> RETURN result;</code></p>
    <empty-line/>
    <p><code> -- Обработка исключений</code></p>
    <p><code> EXCEPTION</code></p>
    <empty-line/>
    <p><code>  -- Если возникла исключительная ситуация</code></p>
    <p><code>  WHEN OTHERS THEN</code></p>
    <p><code>   -- Освобождаем ресурсы</code></p>
    <p><code>   XSLPROCESSOR.freeProcessor(processor);</code></p>
    <p><code>   XMLPARSER.freeParser(parser);</code></p>
    <p><code>   XMLDOM.freeDocument(sourceXML);</code></p>
    <p><code>   XMLDOM.freeDocument(stylesheetXML);</code></p>
    <empty-line/>
    <p><code>  -- Передаем исключение дальше</code></p>
    <p><code>  RAISE;</code></p>
    <p><code>END;</code></p>
    <p>Представление обработанных документов теперь может быть описано совершенно элементарно.</p>
    <subtitle>Листинг 9.20. Представление PROCESSED_SOURCE</subtitle>
    <p><code>CREATE OR REPLACE VIEW PROCESSED_SOURCE AS</code></p>
    <p><code>SELECT ID, PROCESS(ID) AS CONTENT</code></p>
    <p><code>FROM SOURCE;</code></p>
    <p>Продемонстрируем работу функции <code>PROCESS</code> и представления <code>PROCESS_SOURCE</code> на примере двух запросов.</p>
    <subtitle>Листинг 9.21. Запросы к таблице SOURCE и представлению PROCESSED_SOURCE</subtitle>
    <p><code>SQL&gt; SELECT * FROM SOURCE;</code></p>
    <empty-line/>
    <p><code>ID  CONTENT       STYLESHEETID</code></p>
    <p><code>--  ------------  ------------</code></p>
    <p><code>1   &lt;A&gt;value&lt;/A&gt;  1</code></p>
    <empty-line/>
    <p><code>SQL&gt; SELECT * FROM PROCESSED_SOURCE;</code></p>
    <empty-line/>
    <p><code>ID CONTENT</code></p>
    <p><code>-- -------------------------------------------------------</code></p>
    <p><code>1  &lt;?xml version = '1.0' encoding = 'UTF-8'?&gt; &lt;B&gt;value&lt;/B&gt;</code></p>
   </section>
   <section>
    <title>
     <p>Выполнение XSLT-преобразований в Java</p>
    </title>
    <p>Язык Java традиционно широко поддерживает XML-технологии: большинство передовых разработок в этой области реализуется, как правило, сначала на Java и уж затем переносится на другие платформы разработки.</p>
    <p>Не стал исключением и XSLT. Можно смело сказать, что количество XSLT-средств, написанных на Java, превосходит половину вообще всех существующих в настоящее время XSLT-пакетов.</p>
    <p>Для того чтобы продемонстрировать использование XSLT в Java, мы приведем два варианта одной и той же программы — серверного приложения (сервлета), которое по запросу клиента будет возвращать информацию о текущем HTTP-сеансе в формате HTML.</p>
    <p>Первый вариант сервлета можно назвать "традиционным". В нем HTML-документ создается серией инструкций <code>out.println(...)</code>, которые выводят в выходящий поток размеченную HTML-тегами информацию о текущем сеансе.</p>
    <subtitle>Листинг 9.22. Традиционный вариант сервлета</subtitle>
    <p><code>import javax.servlet.*;</code></p>
    <p><code>import javax.servlet.http.*;</code></p>
    <p><code>import java.io.*;</code></p>
    <p><code>import java.util.*;</code></p>
    <empty-line/>
    <p><code>public class example extends HttpServlet {</code></p>
    <p><code> /**</code></p>
    <p><code> * Инициализация.</code></p>
    <p><code> */</code></p>
    <p><code> public void init(ServletConfig config) throws ServletException {</code></p>
    <p><code>  super.init(config);</code></p>
    <p><code> }</code></p>
    <empty-line/>
    <p><code> /**</code></p>
    <p><code> * Основной метод сервлета</code></p>
    <p><code> */</code></p>
    <p><code> public void service(HttpServletRequest request,</code></p>
    <p><code>  HttpServletResponse response)</code></p>
    <p><code>  throws ServletException, IOException {</code></p>
    <p><code>  // Выставляем тип содержимого</code></p>
    <p><code>  response.setContentType("text/html");</code></p>
    <p><code>  // Инициализируем выходящий поток</code></p>
    <p><code>  OutputStreamWriter osw =</code></p>
    <p><code>   new OutputStreamWriter(response.getOutputStream());</code></p>
    <p><code>  PrintWriter out = new PrintWriter (response.getOutputStream());</code></p>
    <p><code>  // Выполняем вывод HTML-страницы</code></p>
    <p><code>  out.println("&lt;html&gt;");</code></p>
    <p><code>  // Выводим головную часть HTML-документа</code></p>
    <p><code>  out.println(" &lt;head&gt;");</code></p>
    <p><code>  out.println("  &lt;title&gt;Request information&lt;/title&gt;");</code></p>
    <p><code>  out.println(" &lt;/head&gt;");</code></p>
    <p><code>  // Выводим тело документа</code></p>
    <p><code>  out.println(" &lt;body&gt;");</code></p>
    <p><code>  // Выводим общую информацию о запросе</code></p>
    <p><code>  out.println("  &lt;h1&gt;General information&lt;/h1&gt;");</code></p>
    <p><code>  out.println("  &lt;table&gt;");</code></p>
    <p><code>  // Выводим имя сервера</code></p>
    <p><code>  out.println("   &lt;tr&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;Server name&lt;/td&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;" + request.getServerName() + "&lt;/td&gt;");</code></p>
    <p><code>  out.println("   &lt;/tr&gt;");</code></p>
    <p><code>  // Выводим порт сервера</code></p>
    <p><code>  out.println("   &lt;tr&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;Server port&lt;/td&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;" + request.getServerPort() + "&lt;/td&gt;");</code></p>
    <p><code>  out.println("   &lt;/tr&gt;");</code></p>
    <p><code>  // Выводим адрес запрашивающей стороны</code></p>
    <p><code>  out.println("   &lt;tr&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;Remote address&lt;/td&gt;") ;</code></p>
    <p><code>  out.println("    &lt;td&gt;" + request.getRemoteAddr() + "&lt;/td&gt;");</code></p>
    <p><code>  out.println("   &lt;/tr&gt;");</code></p>
    <p><code>  // Выводим название протокола запроса</code></p>
    <p><code>  out.println("   &lt;tr&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;Protocol&lt;/td&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;" + request.getProtocol() + "&lt;/td&gt;");</code></p>
    <p><code>  out.println("   &lt;/tr&gt;");</code></p>
    <p><code>  // Выводим метод запроса</code></p>
    <p><code>  out.println("   &lt;tr&gt;") ;</code></p>
    <p><code>  out.println("    &lt;td&gt;Method&lt;/td&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;" + request.getMethod() + "&lt;/td&gt;");</code></p>
    <p><code>  out.println("   &lt;/tr&gt;");</code></p>
    <p><code>  // Выводим URI запроса</code></p>
    <p><code>  out.println("   &lt;tr&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;Request URI&lt;/td&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;" + request.getRequestURI() + "&lt;/td&gt;");</code></p>
    <p><code>  out.println("   &lt;/tr&gt;");</code></p>
    <p><code>  // Выводим строку запроса</code></p>
    <p><code>  out.println("   &lt;tr&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;Query String&lt;/td&gt;");</code></p>
    <p><code>  out.println("    &lt;td&gt;" + request.getQueryString() + "&lt;/td&gt;");</code></p>
    <p><code>  out.println("   &lt;/tr&gt;");</code></p>
    <p><code>  out.println("  &lt;/table&gt;");</code></p>
    <p><code>  // Выводим параметры запроса</code></p>
    <p><code>  out.println("  &lt;h1&gt;Request parameters&lt;/h1&gt;");</code></p>
    <p><code>  out.println("  &lt;table&gt;");</code></p>
    <p><code>  for (Enumeration e = request.getParameterNames();</code></p>
    <p><code>   e.hasMoreElements();) {</code></p>
    <p><code>   String name = e.nextElement().toString();</code></p>
    <p><code>   String[] values = request.getParameterValues(name);</code></p>
    <p><code>   for (int i=0; i &lt; values.length; i++) {</code></p>
    <p><code>    out.println("   &lt;tr&gt;");</code></p>
    <p><code>    out.println("    &lt;td&gt;" + name + "&lt;/td&gt;");</code></p>
    <p><code>    out.println("    &lt;td&gt;" + values[i] + "&lt;/td&gt;");</code></p>
    <p><code>    out.println("   &lt;/tr&gt;");</code></p>
    <p><code>   }</code></p>
    <p><code>  }</code></p>
    <p><code>  out.println("  &lt;/table&gt;");</code></p>
    <p><code>  // Выводим параметры HTTP-сессии</code></p>
    <p><code>  out.println("  &lt;h1&gt;Session parameters&lt;/h1&gt;");</code></p>
    <p><code>  out.println("  &lt;table&gt;");</code></p>
    <p><code>  HttpSession session = request.getSession(true);</code></p>
    <p><code>  String[] names = session.getValueNames();</code></p>
    <p><code>  for (int i=0; i &lt; names.length; i++) {</code></p>
    <p><code>   String name = session.getValueNames()[i];</code></p>
    <p><code>   out.println("   &lt;tr&gt;");</code></p>
    <p><code>   out.println("    &lt;td&gt;" + name + "&lt;/td&gt;");</code></p>
    <p><code>   out.println("    &lt;td&gt;" +</code></p>
    <p><code>   session.getValue(name).toString() + "&lt;/td&gt;");</code></p>
    <p><code>   out.println("   &lt;/tr&gt;");</code></p>
    <p><code>  }</code></p>
    <p><code>  out.println("  &lt;/table&gt;");</code></p>
    <p><code>  // Выводим cookies</code></p>
    <p><code>  response.addCookie(new Cookie("content", "apple jam"));</code></p>
    <p><code>  out.println("  &lt;h1&gt;Cookies&lt;/h1&gt;");</code></p>
    <p><code>  out.println("  &lt;table&gt;");</code></p>
    <p><code>  Cookie[] cookies = request.getCookies();</code></p>
    <p><code>  for (int i=0; i &lt; cookies.length; i++) {</code></p>
    <p><code>   out.println("   &lt;tr&gt;");</code></p>
    <p><code>   out.println("    &lt;td&gt;" + cookies[i].getName() + "&lt;/td&gt;");</code></p>
    <p><code>   out.println("    &lt;td&gt;" + cookies[i].getValue() + "&lt;/td&gt;");</code></p>
    <p><code>   out.println("   &lt;/tr&gt;");</code></p>
    <p><code>  }</code></p>
    <p><code>  out.println("  &lt;/table&gt;");</code></p>
    <p><code>  out.println(" &lt;/body&gt;");</code></p>
    <p><code>  out.println("&lt;/html&gt;");</code></p>
    <p><code>  // Закрываем выходящий поток</code></p>
    <p><code>  out.close();</code></p>
    <p><code> }</code></p>
    <p><code>}</code></p>
    <p>Результатом обращения к этому сервлету по URL вида</p>
    <p><code>http://localhost/servlet/example?x=1&amp;y=2&amp;z=3&amp;x=4&amp;y=5&amp;z=6</code></p>
    <p>будет документ, аналогичный представленному на рис. 9.13.</p>
    <image l:href="#img_82.png"/>
    <p><strong>Рис. 9.13</strong>. Результат обращения к сервлету</p>
    <p>Несложно видеть, насколько жестко в этом сервлете закодирована презентация данных: для минимального изменения генерируемого документа придется в обязательном порядке изменять сам сервлет, что в современных системах может быть непозволительной роскошью, — все равно, что перебирать мотор для того, чтобы перекрасить автомобиль.</p>
    <p>Второй вариант того же самого сервлета, который мы предложим ниже, демонстрирует, как в данном случае при помощи XSLT можно разделить данные и их презентацию. Идея очень проста: вместо того, чтобы в жестко заданном виде выводить информацию в выходящий поток, можно создать XML-документ в виде DOM-объекта и затем применить к нему XSLT-преобразование, которое создаст для него требуемое HTML-представление.</p>
    <p>В этом варианте сервлета мы будем использовать Java-версию XML-библиотеки Oracle XDK (Oracle XML SDK, платформа разработки XML-приложений, созданная в Oracle Corp.). В данном примере из этой библиотеки мы будем использовать только XSLT-процессор (класс <code>XSLProcessor</code>) и реализацию DOM-модели XML-документа (класс <code>XMLDocument</code>). Во всем остальном мы будем полагаться на Java-реализацию стандартных интерфейсов объектной модели документа DOM, разработанной Консорциумом W3. DOM-интерфейсы позволят нам манипулировать XML-документом на уровне модели: создавать и включать друг в друга узлы элементов, текстовые узлы и так далее.</p>
    <subtitle>Листинг 9.23. Вариант сервлета, использующий XSLT</subtitle>
    <p><code>import javax.servlet.*;</code></p>
    <p><code>import javax.servlet.http.*;</code></p>
    <p><code>import java.io.*;</code></p>
    <p><code>import java.util.*;</code></p>
    <p><code>import java.net.*;</code></p>
    <p><code>import oracle.xml.parser.v2.*;</code></p>
    <p><code>import org.w3c.dom.*;</code></p>
    <empty-line/>
    <p><code>public class example extends HttpServlet {</code></p>
    <p><code> /**</code></p>
    <p><code> * Функция, создающая в элементе parent элемент с именем name и</code></p>
    <p><code> * текстовым значением value. Если value имеет значение null,</code></p>
    <p><code> * текст не создается.</code></p>
    <p><code> */</code></p>
    <p><code> public static Element addElement(Element parent, String name, String value) {</code></p>
    <p><code>  Element child = parent.getOwnerDocument().createElement(name);</code></p>
    <p><code>  parent.appendChild(child);</code></p>
    <p><code>  if (value != null) {</code></p>
    <p><code>   Text text = parent.getOwnerDocument().createTextNode(value);</code></p>
    <p><code>   child.appendChild(text);</code></p>
    <p><code>  }</code></p>
    <p><code>  return child;</code></p>
    <p><code> }</code></p>
    <empty-line/>
    <p><code> /**</code></p>
    <p><code> * Инициализация.</code></p>
    <p><code> */</code></p>
    <p><code> public void init(ServletConfig config) throws ServletException {</code></p>
    <p><code>  super.init(config);</code></p>
    <p><code> }</code></p>
    <empty-line/>
    <p><code> /**</code></p>
    <p><code> * Основной метод сервлета</code></p>
    <p><code> */</code></p>
    <p><code> public void service(HttpServletRequest request,</code></p>
    <p><code>  HttpServletResponse response)</code></p>
    <p><code>  throws ServletException, IOException {</code></p>
    <p><code>  // Выставляем тип содержимого</code></p>
    <p><code>  response.setContentType("text/html");</code></p>
    <p><code>  // Инициализируем выходящий поток</code></p>
    <p><code>  OutputStreamWriter o_sw =</code></p>
    <p><code>   new OutputStreamWriter(response.getOutputStream());</code></p>
    <p><code>  PrintWriter out = new PrintWriter(response.getOutputStream());</code></p>
    <p><code>  // Получаем объекты</code></p>
    <p><code>  cookie Cookie[] cookies = request.getCookies();</code></p>
    <p><code>  // Создаем выходящий документ</code></p>
    <p><code>  XMLDocument doc = new XMLDocument();</code></p>
    <p><code>  // Создаем корневой элемент</code></p>
    <p><code>  Request Element elRequest = doc.createElement("Request");</code></p>
    <p><code>  doc.appendChild(elRequest);</code></p>
    <p><code>  // Создаем элемент General</code></p>
    <p><code>  Element elGeneral = addElement(elRequest, "General", null);</code></p>
    <p><code>  // Создаем элементы, содержащие общую информацию</code></p>
    <p><code>  addElement(elGeneral, "ServerName", request.getServerName());</code></p>
    <p><code>  addElement(elGeneral, "ServerPort",</code></p>
    <p><code>   Integer.toString(request.getServerPort()));</code></p>
    <p><code>  addElement(elGeneral, "RemoteAddr", request.getRemoteAddr());</code></p>
    <p><code>  addElement(elGeneral, "Protocol", request.getProtocol());</code></p>
    <p><code>  addElement(elGeneral, "Method", request.getMethod());</code></p>
    <p><code>  addElement(elGeneral, "RequestURI", request.getRequestURI());</code></p>
    <p><code>  addElement(elGeneral, "QueryString", request.getQueryString());</code></p>
    <p><code>  // Создаем элемент Param</code></p>
    <p><code>  Element elParam = addElement(elRequest, "Param", null);</code></p>
    <p><code>  // В элементе Param создаем элементы, описывающие параметры запроса</code></p>
    <p><code>  for (Enumeration e = request.getParameterNames();</code></p>
    <p><code>   e.hasMoreElements();) {</code></p>
    <p><code>   String name = e.nextElement().toString();</code></p>
    <p><code>   String[] values = request.getParameterValues(name);</code></p>
    <p><code>   // Для каждого из значений каждого из параметров</code></p>
    <p><code>   // создаем соответствующий элемент</code></p>
    <p><code>   for (int i=0; i &lt; values.length; i++)</code></p>
    <p><code>    addElement(elParam, name, values[i]);</code></p>
    <p><code>  }</code></p>
    <p><code>  // Создаем элемент Session</code></p>
    <p><code>  Element elSession = addElement(elRequest, "Session", null);</code></p>
    <p><code>  // Получаем объект HTTP-сессии</code></p>
    <p><code>  HttpSession session = request.getSession(true);</code></p>
    <p><code>  // Получаем имена параметров сессии</code></p>
    <p><code>  String[] names = session.getValueNames();</code></p>
    <p><code>  // В элементе Session создаем по элементу</code></p>
    <p><code>  // для каждого из параметров сессии</code></p>
    <p><code>  for (int i=0; i &lt; names.length; i++)</code></p>
    <p><code>   addElement(elSession, session.getValueNames()[i],</code></p>
    <p><code>    session.getValue(session.getValueNames()[i]).toString());</code></p>
    <p><code>  // Создаем элемент Cookie</code></p>
    <p><code>  Element elCookie = addElement(elRequest, "Cookie", null);</code></p>
    <p><code>  // Создаем по элементу для каждого из объектов cookies</code></p>
    <p><code>  for (int i=0; i &lt; cookies.length; i++)</code></p>
    <p><code>   addElement(elCookie, cookies[i].getName(), cookies[i].getValue());</code></p>
    <p><code>  // Преобразовываем созданный документ и выводим результат</code></p>
    <p><code>  try {</code></p>
    <p><code>   // Загружаем преобразование</code></p>
    <p><code>   XSLStylesheet stylesheet = new XSLStylesheet(</code></p>
    <p><code>    new URL("http://localhost/stylesheet.xsl"), null);</code></p>
    <p><code>   // Выполняем преобразование</code></p>
    <p><code>   XMLDocumentFragment fragment =</code></p>
    <p><code>    (XMLDocumentFragment)doc.transformNode(stylesheet);</code></p>
    <p><code>   // Выводим результат</code></p>
    <p><code>   fragment.print(out);</code></p>
    <p><code>  }</code></p>
    <p><code>  catch (MalformedURLException mue) {} </code></p>
    <p><code>  catch (XSLException xsle) {}</code></p>
    <p><code>  // Закрываем выходящий поток</code></p>
    <p><code>  out.close();</code></p>
    <p><code> }</code></p>
    <p><code>}</code></p>
    <p>В этом сервлете вместо того, чтобы просто печатать в выходящий поток данные и HTML-разметку, в переменной <code>doc</code> мы генерируем DOM-объект XML-документа. После того как все текстовые узлы и узлы элементов будут сгенерированы, документ, содержащийся в переменной <code>doc</code>, примет приблизительно следующий вид.</p>
    <subtitle>Листинг 9.24. XML-документ, сгенерированный в сервлете</subtitle>
    <p><code>&lt;Request&gt;</code></p>
    <p><code> &lt;General&gt;</code></p>
    <p><code>  &lt;ServerName&gt;aphrodite.fzi.de&lt;/ServerName&gt;</code></p>
    <p><code>  &lt;ServerPort&gt;80&lt;/ServerPort&gt;</code></p>
    <p><code>  &lt;RemoteAddr&gt;127.0.0.1&lt;/RemoteAddr&gt;</code></p>
    <p><code>  &lt;Protocol&gt;HTTP/1.1&lt;/Protocol&gt;</code></p>
    <p><code>  &lt;Method&gt;GET&lt;/Method&gt;</code></p>
    <p><code>  &lt;RequestURI&gt;/servlet/example1&lt;/RequestURI&gt;</code></p>
    <p><code>  &lt;QueryString&gt;x=1&amp;amp;y=2&amp;amp;z=3&amp;amp;x=4&amp;amp;y=5&amp;amp;z=6</code></p>
    <p><code>  &lt;/QueryString&gt;</code></p>
    <p><code> &lt;/General&gt;</code></p>
    <p><code> &lt;Param&gt;</code></p>
    <p><code>  &lt;z&gt;3&lt;/z&gt;</code></p>
    <p><code>  &lt;z&gt;6&lt;/z&gt;</code></p>
    <p><code>  &lt;y&gt;2&lt;/y&gt;</code></p>
    <p><code>  &lt;y&gt;5&lt;/y&gt;</code></p>
    <p><code>  &lt;x&gt;1&lt;/x&gt;</code></p>
    <p><code>  &lt;x&gt;4&lt;/x&gt;</code></p>
    <p><code> &lt;/Param&gt;</code></p>
    <p><code> &lt;Session&gt;</code></p>
    <p><code>  &lt;v&gt;4&lt;/v&gt;</code></p>
    <p><code> &lt;/Session&gt;</code></p>
    <p><code> &lt;Cookie&gt;</code></p>
    <p><code>  &lt;content&gt;apple jam&lt;/content&gt;</code></p>
    <p><code>  &lt;JServSessionIdroot&gt;aaenbyjqc0&lt;/JServSessionIdroot&gt;</code></p>
    <p><code> &lt;/Cookie&gt;</code></p>
    <p><code>&lt;/Request&gt;</code></p>
    <p>После того как генерация документа завершена, к нему применяется преобразование <code>stylesheet.xsl</code>, которое создает его HTML-представление.</p>
    <subtitle>Листинг 9.25. Преобразование stylesheet.xsl</subtitle>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="Request"&gt;</code></p>
    <p><code>  &lt;html&gt;</code></p>
    <p><code>   &lt;head&gt;</code></p>
    <p><code>    &lt;title&gt;Request information&lt;/title&gt;</code></p>
    <p><code>   &lt;/head&gt;</code></p>
    <p><code>   &lt;body&gt;&lt;xsl:apply-templates mode="table"/&gt;&lt;/body&gt;</code></p>
    <p><code>  &lt;/html&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="*" mode="table"&gt;</code></p>
    <p><code>  &lt;h1&gt;&lt;xsl:apply-templates select="." mode="header"/&gt;&lt;/h1&gt;</code></p>
    <p><code>  &lt;table&gt;&lt;xsl:apply-templates mode="row"/&gt;&lt;/table&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="General" mode="header"&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;General information&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="Param" mode="header"&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;Request parameters&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="Session" mode="header"&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;Session parameters&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="Cookie" mode="header"&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;Cookies&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="*" mode="row"&gt;</code></p>
    <p><code>  &lt;tr&gt;</code></p>
    <p><code>   &lt;td&gt;&lt;xsl:apply-templates select="." mode="name"/&gt;&lt;/td&gt;</code></p>
    <p><code>   &lt;td&gt;&lt;xsl:value-of select="."/&gt;&lt;/td&gt;</code></p>
    <p><code>  &lt;/tr&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="*" mode="name"&gt;</code></p>
    <p><code>  &lt;xsl:value-of select="name()"/&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="General/ServerName" mode="name"&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;Server name&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="General/ServerPort" mode="name"&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;Server port&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="General/RemoteAddr" mode="name"&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;Remote address&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="General/RequestURI" mode="name"&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;Request URI&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="General/QueryString" mode="name"&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;Query string&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>Результатом этого преобразования является следующий HTML-документ, внешний вид которого полностью идентичен документу, показанному на рис. 9.13.</p>
    <subtitle>Листинг 9.26. Результирующий HTML-документ</subtitle>
    <p><code>&lt;html&gt;</code></p>
    <p><code> &lt;head&gt;</code></p>
    <p><code>  &lt;title&gt;Request information&lt;/title&gt;</code></p>
    <p><code> &lt;/head&gt;</code></p>
    <p><code> &lt;body&gt;</code></p>
    <p><code>  &lt;h1&gt;General information&lt;/h1&gt;</code></p>
    <p><code>  &lt;table&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;Server name&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;aphrodite.fzi.de&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;Server port&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;80&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;Remote address&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;127.0.0.1&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;Protocol&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;HTTP/1.1&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;Method&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;GET&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;Request URI&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;/servlet/example1&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;Query string&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;x=1&amp;amp;y=2&amp;amp;z=3&amp;amp;x=4&amp;amp;y=5&amp;amp;z=6&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>  &lt;/table&gt;</code></p>
    <p><code>  &lt;h1&gt;Request parameters&lt;/h1&gt;</code></p>
    <p><code>  &lt;table&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;z&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;3&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;z&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;6&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;y&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;2&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;y&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;5&lt;/td&gt;</code></p>
    <p><code>    &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;x&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;1&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;x&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;4&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>  &lt;/table&gt;</code></p>
    <p><code>  &lt;h1&gt;Session parameters&lt;/h1&gt;</code></p>
    <p><code>  &lt;table&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;v&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;4&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>  &lt;/table&gt;</code></p>
    <p><code>  &lt;h1&gt;Cookies&lt;/h1&gt;</code></p>
    <p><code>  &lt;table&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;content&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;apple jam&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>   &lt;tr&gt;</code></p>
    <p><code>    &lt;td&gt;JServSessionIdroot&lt;/td&gt;</code></p>
    <p><code>    &lt;td&gt;aaenbyjqc0&lt;/td&gt;</code></p>
    <p><code>   &lt;/tr&gt;</code></p>
    <p><code>  &lt;/table&gt;</code></p>
    <p><code> &lt;/body&gt;</code></p>
    <p><code>&lt;/html&gt;</code></p>
    <p>Второй вариант сервлета, конечно, не проще, чем первый, да и вряд ли он будет быстрее и экономичнее с точки зрения памяти, ведь вместо простого вывода текста в поток мы сначала создаем в памяти объектную модель документа, преобразуем ее и только затем выводим результат. Однако главное, чего удалось в этом случае добиться, — это отделение данных от их презентации.</p>
    <p>Представим, к примеру, что нам потребовалось перевести названия полей выводимого документа на русский язык — получить текст "<code>Общая информация</code>" вместо "<code>General information</code>" и так далее. В первом случае для внесения этого элементарного представления потребуется переписывать, перекомпилировать и обновлять на сервере сервлет; во втором случае все, что нужно будет сделать, — это исправить несколько строк в файле <code>stylesheet.xsl</code>.</p>
   </section>
   <section>
    <title>
     <p>Краткие выводы</p>
    </title>
    <p>В заключение хотелось бы сделать несколько комментариев относительно применения XSLT и вообще XML-технологий.</p>
    <p>Как и в любом другом случае, нужно очень тщательно взвешивать целесообразность применения в проекте тех или иных средств. К сожалению, шумиха вокруг XML имеет чисто коммерческий характер, маркетинговые службы часто выдают желаемое за действительное, объявляя XML серебряной пулей для всех проблем информационных технологий.</p>
    <p>Как мы знаем, серебряных пуль не бывает. Нужно всегда очень трезво относиться к выбору технологий, хорошо понимая их плюсы, минусы и что каждый из этих знаков будет означать для конкретного проекта. Глупо вслепую следовать моде и тенденциям, не обращая внимания на возникающие при этом издержки.</p>
    <p>С этих позиций XSLT является наименее проблемной технологией в том смысле, что если встает вопрос, использовать XSLT или нет, это уже означает: вопрос об использовании XML-технологий решен положительно. Значит, разработчики уже пошли на жертвы ресурсов памяти и процессорной мощности, которые XSLT вряд ли ужесточит. Иначе говоря, аппаратные требования не являются определяющими для использования XSLT.</p>
    <p>Другое обстоятельство, которое необходимо принимать во внимание, — это сложность самого преобразования. Базовый набор элементов XSLT вкупе с расширениями уже представляется чрезвычайно мощным средством для выполнения различных преобразований, однако в некоторых случаях даже этого может быть недостаточно. В других случаях мощь XSLT может наоборот оказаться неоправданной — например, с задачей представления внешнего вида HTML-документа в Web-браузере могут великолепно справиться каскадные таблицы стилей (CSS).</p>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 10</p>
    <p>Расширения языка XSLT</p>
   </title>
   <section>
    <title>
     <p>Что такое расширения?</p>
    </title>
    <p>Предыдущие главы этой книги были посвящены, в основном, тому, что может XSLT. Эти возможности, естественно, далеко не безграничны, да и нельзя ожидать слишком многого от специализированного языка, каким является XSLT.</p>
    <p>Вместе с тем в XSLT-преобразованиях может оказаться очень полезной функциональность традиционных языков программирования. Например, математических функций и операторов, имеющихся в XPath, явно недостаточно для выполнения сложных вычислений, которые могут потребоваться в преобразованиях. XSLT не имеет встроенных функций для обращения к базам данных, оставляют желать лучшего средства для работы с множествами, текстовыми данными, датами и временными параметрами, словом задачи, не представляющие никакой сложности в традиционных языках программирования, могут быть чрезвычайно трудоемкими в XSLT. Скажем, тригонометрические функции можно реализовать в XSLT рекурсивными вычислениями последовательностей Тейлора, но насколько проще было бы использовать функции <code>sin</code> и <code>cos</code>.</p>
    <p>Таким образом, перед разработчиками языка стояла следующая дилемма: либо дублировать функциональность традиционных языков программирования в XSLT или XPath, либо изыскивать другие средства достижения тех же результатов.</p>
    <p>Решение этой проблемы было довольно простым: вместо того, чтобы заново реализовывать все множество функций, которые только могут понадобиться при обработке документов, спецификация XSLT позволяет процессорам предоставлять интерфейсы для расширения XSLT и XPath за счет использования других языков программирования, например, Java, JavaScript или Python.</p>
    <p>Существуют два способа расширения XSLT: при помощи функций и элементов расширения. Не изменяя структуры преобразований, два эти способа позволяют использовать при обработке документов возможности традиционных языков, что часто бывает очень полезно, а иногда и просто необходимо.</p>
    <p>Рассмотрим примеры.</p>
    <p>В языке XPath нет функции, которая генерировала бы псевдослучайное значение. Следующее преобразование приводит пример решения этой задачи с помощью стандартного класса <code>Math</code> языка Java.</p>
    <subtitle>Листинг 10.1. Преобразование, использующее класс java.lang.Math</subtitle>
    <p><code>&lt;xsl:stylesheet version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transfоrm"</code></p>
    <p><code> xmlns:math="java:java.lang.Math"</code></p>
    <p><code> exclude-result-prefixes="math"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="/"&gt;</code></p>
    <p><code>  &lt;random&gt;&lt;xsl:value-of select="math:random()"/&gt;&lt;/random&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>Результатом выполнения этого преобразования будет документ вида:</p>
    <p><code>&lt;random&gt;0.0538608432986305&lt;/random&gt;</code></p>
    <p>Значение <code>0.0538608432986305</code> было получено посредством вызова метода <code>random</code> класса <code>java.lang.Math</code> и представляет собой некоторое псевдослучайное значение.</p>
    <p>В качестве примера элемента расширения можно привести элемент <code>saxon:entity-ref</code>, определенный в XSLT-процессоре Saxon. Этот элемент создает в выходящем документе сущность с указанным именем.</p>
    <subtitle>Листинг 10.2. Использование элемента расширения saxon:entity-ref</subtitle>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
    <p><code> xmlns:saxon="http://icl.com/saxon"</code></p>
    <p><code> extension-element-prefixes="saxon"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="/"&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;Everybody&lt;/xsl:text&gt;</code></p>
    <p><code>  &lt;saxon:entity-ref name="nbsp"/&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;needs&lt;/xsl:text&gt;</code></p>
    <p><code>  &lt;saxon:entity-ref name="nbsp"/&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;space&lt;/xsl:text&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>Результатом этого преобразования будет текст</p>
    <p><code>Everybody&amp;nbsp;needs&amp;nbsp;space</code></p>
    <p>Несложно понять, насколько мощным средством являются расширения. Они фактически позволяют реализовать в преобразованиях функциональность традиционных языков программирования. Иными словами, почти все то, что можно сделать в обычных языках программирования, можно сделать и в преобразованиях.</p>
    <p>Как это часто бывает, за дополнительные возможности приходится платить. Использование механизма расширений предъявляет определенные требования и накладывает некоторые ограничения.</p>
    <p>&#9633; Реализация механизма расширений в текущей версии языка целиком и полностью зависит от производителей процессоров. Вследствие этого интерфейсы расширения различных XSLT-процессоров могут отличаться даже для одного языка программирования. Это в итоге ведет к несовместимости расширений и непереносимости XSLT-решений между различными процессорами.</p>
    <p>&#9633; Возможность использования того или иного языка для написания расширений зависит от наличия интерфейса XSLT-процессора для этого языка. Не следует ожидать, что любой процессор сможет работать с расширениями, написанными на любом языке, то есть, иначе говоря, расширения привязывают преобразования к строго определенному процессору или, в лучшем случае, группе процессоров.</p>
    <p>&#9633; В то время как сам XSLT не имеет сторонних эффектов, расширения этого принципа придерживаться не обязаны. Вследствие этого преобразования, в которых есть расширения с побочными эффектами могут из-за различных методов обработки входящего документа генерировать на разных процессорах разный результат.</p>
    <p>Итак, вопрос, использовать расширения или нет — это вопрос "функциональность против переносимости", и, хотя его решение будет всегда зависеть от конкретной задачи, существуют также и довольно общие критерии оценки, которые мы приведем в следующей таблице (табл. 10.1).</p>
    <empty-line/>
    <p><emphasis><strong>Таблица 10.1</strong>. Использование расширений: критерии за и против</emphasis></p>
    <table>
     <tr>
      <th align="left">Использовать расширения стоит, если:</th>
      <th align="left">Использовать расширения не стоит, если:</th>
     </tr>
     <tr>
      <td align="left">преобразования будут выполняться на заранее известном процессоре или группе процессоров;</td>
      <td align="left">целевой процессор неизвестен. Преобразования должны быть переносимы, насколько это возможно;</td>
     </tr>
     <tr>
      <td align="left">в XSLT нет средств для выполнения требуемой задачи, либо они очень неэффективны;</td>
      <td align="left">в XSLT имеются средства для выполнения требуемой задачи;</td>
     </tr>
     <tr>
      <td align="left">преобразование должно обладать побочными эффектами;</td>
      <td align="left">преобразование может обойтись без побочных эффектов;</td>
     </tr>
     <tr>
      <td align="left">целевой процессор предоставляет интерфейс для хорошо известного разработчику языка программирования</td>
      <td align="left">интерфейс для нужного языка программирования в целевом процессоре отсутствует</td>
     </tr>
    </table>
    <p>Подводя итог, образно выражаясь, скажем, что расширения — это пушка, стрелять из которой по воробьям рекомендуется только, когда не остается ничего другого, или воробьи достаточно велики.</p>
    <p>К сожалению, не представляется возможным описать в одной главе интерфейсы расширения даже наиболее распространенных XSLT-процессоров. Вместо этого мы постараемся изложить основные принципы создания расширения, а также приведем несколько общих примеров, которые смогут послужить основой для создания частных решений.</p>
    <p>Основным языком реализации расширений, приводимых в этой главе, будет Java. Пожалуй, Java является единственным языком, интерфейсы расширений для которого достаточно стандартизированы, чтобы можно было говорить об общих подходах. Однако, если читатель не знаком с этим языком — ничего страшного, ведь основное внимание в этой главе уделяется использованию расширений в XSLT, а не написанию их в других языках и Java-код приводится только для того, чтобы сделать примеры рабочими.</p>
   </section>
   <section>
    <title>
     <p>Функции расширения</p>
    </title>
    <section>
     <p>Прежде чем описывать использование функций расширения, вспомним, как мы вызывали в преобразованиях обычные функции, например, функцию <code>concat</code>:</p>
     <p><code>&lt;xsl:value-of select="concat('para', 'bellum')"/&gt;</code></p>
     <p>Атрибут <code>select</code> содержит XPath-выражение <code>concat('para', 'bellum')</code>, которое с точки зрения синтаксиса XPath является вызовом функции и соответствует продукции <code>FunctionCall</code>:</p>
     <p><code>[XP16] FunctionCall ::= FunctionName</code></p>
     <p><code>                        '(' ( Argument ( ',' Argument ) * ) ? ')'</code></p>
     <p>Аргументами функции являются выражения, а имя может быть любым корректным XML-именем (за исключением <code>node</code>, <code>comment</code>, <code>processing-instruction</code> и <code>text</code>, которые используются для проверки типа узла):</p>
     <p><code>[XP17] Argument     ::= Expr</code></p>
     <p><code>[XP35] FunctionName ::= QName - NodeType</code></p>
     <p>В плане синтаксиса функции расширения ничем не отличаются от стандартных функций: они отвечают тем же самым грамматическим правилам. Единственное различие состоит в том, что функции стандартных библиотек XPath и XSLT принадлежат нулевому пространству имен, в то время как пространство имен функций расширения должно обязательным образом быть ненулевым. Иными словами, вызовы функций, имеющие вид <code><emphasis>имя</emphasis>(<emphasis>аргумент</emphasis>, <emphasis>аргумент</emphasis>, ...)</code>, будут считаться вызовами функций базовых библиотек, а вызовы вида <code><emphasis>префикс</emphasis>:<emphasis>имя</emphasis>(<emphasis>аргумент</emphasis>, <emphasis>аргумент</emphasis>, ...)</code> будут считаться вызовами функций расширения.</p>
     <subtitle>Пример</subtitle>
     <p>Выражение</p>
     <p><code>round(0.6)</code></p>
     <p>является вызовом функции базовой библиотеки XPath, в то время как выражение</p>
     <p><code>math:round(0.6)</code></p>
     <p>является вызовом функции расширения.</p>
     <p>Практически во всех процессорах пространство имен функции расширения является звеном, которое связывает ее с конкретной реализацией.</p>
     <subtitle>Пример</subtitle>
     <p><code>&lt;xsl:value-of select="math:round(0.6)" xmlns:math="java:java.lang.Math"/&gt;</code></p>
     <p>Элемент <code>xsl:value-of</code> вычисляет выражение <code>math:round(0.6)</code>, которое является вызовом функции расширения. Само имя функции состоит из локальной части round и префикса <code>math</code>, которому соответствует URI <code>java:java.lang.Math</code>. В большинстве XSLT-процессоров вызов такого рода будет означать обращение к статической функции <code>round</code> класса <code>java.lang.Math</code>.</p>
     <p>Простейшим случаем использования расширений в XSLT-процессорах, написанных на Java, является обращение к стандартным функциям пакетов Java.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что входящий документ описывает координаты множества точек, а преобразование создает SVG-документ, содержащий линии, которые их последовательно соединяют.</p>
     <cite>
      <subtitle>Примечание</subtitle>
      <p>SVG — это XML-язык для описания масштабируемой векторной графики (от англ. scalable vector graphics). SVG позволяет простым XML-синтаксисом описывать векторную графику. SVG-документы могут показываться в браузерах при помощи таких компонент, как Adobe SVG Viewer или Batik от Apache XML Project.</p>
     </cite>
     <subtitle>Листинг 10.3. Входящий документ</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
     <p><code>&lt;точки width="200" height="200"&gt;</code></p>
     <p><code> &lt;точка x="-50" y="-50"/&gt;</code></p>
     <p><code> &lt;точка x=" 50" y="-50"/&gt;</code></p>
     <p><code> &lt;точка x=" 50" y=" 50"/&gt;</code></p>
     <p><code> &lt;точка x="-50" y=" 50"/&gt;</code></p>
     <p><code>&lt;/точки&gt;</code></p>
     <subtitle>Листинг 10.4. Преобразование</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns="http://www.w3.org/2000/svg"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:output</code></p>
     <p><code>  indent="yes"</code></p>
     <p><code>  doctype-public="-//W3C//DTD SVG 1.0//EN"</code></p>
     <p><code>  doctype-system="http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;svg width="200" height="200"&gt;</code></p>
     <p><code>   &lt;desc&gt;Simple line-based figure&lt;/desc&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="точки"/&gt;</code></p>
     <p><code>  &lt;/svg&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="точки"&gt;</code></p>
     <p><code>  &lt;g style="stroke:black; stroke-width:2"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="точка"/&gt;</code></p>
     <p><code>  &lt;/g&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="точка"&gt;</code></p>
     <p><code>  &lt;line</code></p>
     <p><code>   x1="{@x + 100}"</code></p>
     <p><code>   y1="{@y + 100}"</code></p>
     <p><code>   x2="{following-sibling::точка[1]/@x + 100}"</code></p>
     <p><code>   y2="{following-sibling::точка[1]/@y + 100}"&gt;</code></p>
     <p><code>   &lt;xsl:if test="position() = last()"&gt;</code></p>
     <p><code>    &lt;xsl:attribute name="x2"&gt;</code></p>
     <p><code>     &lt;xsl:value-of</code></p>
     <p><code>      select="preceding-sibling::точка[last()]/@x + 100"/&gt;</code></p>
     <p><code>    &lt;/xsl:attribute&gt;</code></p>
     <p><code>    &lt;xsl:attribute name="y2"&gt;</code></p>
     <p><code>     &lt;xsl:value-of</code></p>
     <p><code>      select="preceding-sibling::точка[last()]/@y + 100"/&gt;</code></p>
     <p><code>    &lt;/xsl:attribute&gt;</code></p>
     <p><code>   &lt;/xsl:if&gt;</code></p>
     <p><code>  &lt;/line&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результатом этого преобразования является следующий SVG-документ.</p>
     <subtitle>Листинг 10.5. Выходящий SVG-документ</subtitle>
     <p><code>&lt;!DOCTYPE svg</code></p>
     <p><code> PUBLIC "-//W3C//DTD SVG 1.0//EN"</code></p>
     <p><code> "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"&gt;</code></p>
     <p><code>&lt;svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"&gt;</code></p>
     <p><code> &lt;desc&gt;Simple line-based figure&lt;/desc&gt;</code></p>
     <p><code> &lt;g style="stroke:black; stroke-width:2"&gt;</code></p>
     <p><code>  &lt;line x1="50" y1="50" x2="150" y2="50"/&gt;</code></p>
     <p><code>  &lt;line x1="150" y1="50" x2="150" y2="150"/&gt;</code></p>
     <p><code>  &lt;line x1="150" y1="150" x2="50" y2="150"/&gt;</code></p>
     <p><code>  &lt;line x1="50" y1="150" x2="50" y2="50"/&gt;</code></p>
     <p><code> &lt;/g&gt;</code></p>
     <p><code>&lt;/svg&gt;</code></p>
     <p>На рис. 10.1 приведен пример визуального представления этого документа.</p>
     <image l:href="#img_83.png"/>
     <p><strong>Рис. 10.1</strong>. Визуальное представление полученного SVG-документа</p>
     <p>Предположим теперь, что нам нужно не просто создать по данному множеству точек набор соединяющих их линий, но еще и произвести некоторые геометрические преобразования, например поворот на заданный в градусах угол &#945;.</p>
     <p>Формулы преобразования координат при повороте чрезвычайно просты:</p>
     <p><emphasis>x</emphasis> = <emphasis>x</emphasis>'&#8729;cos(&#945;) &#8722; <emphasis>y</emphasis>&#8729;sin(&#945;),</p>
     <p><emphasis>у</emphasis> = <emphasis>x</emphasis>'&#8729;sin(&#945;) + <emphasis>x</emphasis>'&#8729;cos(&#945;),</p>
     <p>где <emphasis>x</emphasis>' и <emphasis>y</emphasis>' — старые координаты точки, <emphasis>x</emphasis> и <emphasis>y</emphasis> — новые координаты точки, а &#945; — угол поворота. Единственная загвоздка состоит в том, что функций <code>sin</code> и <code>cos</code> в базовой библиотеке XPath нет.</p>
     <p>Самым простым выходом в такой ситуации является использование расширений. Например, в случае XSLT-процессора, который может использовать Java-расширения (Saxon, Xalan, Oracle XSLT Processor и так далее) надо будет лишь только объявить пространство имен вида:</p>
     <p><code>xmlns:math="java:java.lang.Math"</code></p>
     <p>и использовать функции <code>math:sin</code> и <code>math:cos</code>.</p>
     <subtitle>Листинг 10.6. Преобразование, осуществляющее поворот</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns="http://www.w3.org/2000/svg"</code></p>
     <p><code> xmlns:math="java:java.lang.Math"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:output</code></p>
     <p><code>  indent="yes"</code></p>
     <p><code>  doctype-public="-//W3C//DTD SVG 1.0//EN"</code></p>
     <p><code>  doctype-system="http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:param name="alpha" select="30"/&gt;</code></p>
     <p><code> &lt;xsl:variable name="alpha-radian" select="3.14 * ($alpha div 180)"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;svg width="200" height="200"&gt;</code></p>
     <p><code>   &lt;desc&gt;Simple line-based figure&lt;/desc&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="точки"/&gt;</code></p>
     <p><code>  &lt;/svg&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="точки"&gt;</code></p>
     <p><code>  &lt;g style="stroke:black; stroke-width:2"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="точка"/&gt;</code></p>
     <p><code>  &lt;/g&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="точка"&gt;</code></p>
     <p><code>  &lt;xsl:variable name="x1" select="@x"/&gt;</code></p>
     <p><code>  &lt;xsl:variable name="y1" select="@y"/&gt;</code></p>
     <p><code>  &lt;xsl:variable name="x2r"&gt;</code></p>
     <p><code>   &lt;xsl:choose&gt;</code></p>
     <p><code>    &lt;xsl:when test="position() = last()"&gt;</code></p>
     <p><code>     &lt;xsl:value-of select="preceding-sibling::точка[last()]/@x"/&gt;</code></p>
     <p><code>    &lt;/xsl:when&gt;</code></p>
     <p><code>    &lt;xsl:otherwise&gt;</code></p>
     <p><code>     &lt;xsl:value-of select="following-sibling::точка[1]/@x"/&gt;</code></p>
     <p><code>    &lt;/xsl:otherwise&gt;</code></p>
     <p><code>   &lt;/xsl:choose&gt;</code></p>
     <p><code>  &lt;/xsl:variable&gt;</code></p>
     <p><code>  &lt;xsl:variable name="y2r"&gt;</code></p>
     <p><code>   &lt;xsl:choose&gt;</code></p>
     <p><code>    &lt;xsl:when test="position() = last()"&gt;</code></p>
     <p><code>     &lt;xsl:value-of select="preceding-sibling::точка[last()]/@y"/&gt;</code></p>
     <p><code>    &lt;/xsl:when&gt;</code></p>
     <p><code>    &lt;xsl:otherwise&gt;</code></p>
     <p><code>     &lt;xsl:value-of select="following-sibling::точка[1]/@y"/&gt;</code></p>
     <p><code>    &lt;/xsl:otherwise&gt;</code></p>
     <p><code>   &lt;/xsl:choose&gt;</code></p>
     <p><code>  &lt;/xsl:variable&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;xsl:variable name="x2" select="number($x2r)"/&gt;</code></p>
     <p><code>  &lt;xsl:variable name="y2" select="number($y2r)"/&gt;</code></p>
     <empty-line/>
     <p><code>  &lt;line</code></p>
     <p><code>   x1="{$x1 * math:cos($alpha-radian) -</code></p>
     <p><code>        $y1 * math:sin($alpha-radian) + 100}"</code></p>
     <p><code>   y1="{$x1 * math:sin($alpha-radian) +</code></p>
     <p><code>        $y1 * math:cos($alpha-radian) + 100}"</code></p>
     <p><code>   x2="{$x2 * math:cos($alpha-radian) -</code></p>
     <p><code>        $y2 * math:sin($alpha-radian) + 100}"</code></p>
     <p><code>   y2="{$x2 * math:sin($alpha-radian) +</code></p>
     <p><code>        $y2 * math:cos($alpha-radian) + 100}"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результатом этого преобразования будет следующий документ.</p>
     <subtitle>Листинг 10.7. Результирующий SVG-документ</subtitle>
     <p><code>&lt;!DOCTYPE svg</code></p>
     <p><code> PUBLIC "-//W3C//DTD SVG 1.0//EN"</code></p>
     <p><code> "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"&gt;</code></p>
     <empty-line/>
     <p><code>&lt;svg</code></p>
     <p><code> xmlns="http://www.w3.org/2000/svg"</code></p>
     <p><code> xmlns:math="java:java.lang.Math"</code></p>
     <p><code> width="200"</code></p>
     <p><code> height="200"&gt;</code></p>
     <p><code> &lt;desc&gt;Simple line-based figure&lt;/desc&gt;</code></p>
     <p><code>  &lt;g style="stroke:black; stroke-width:2"&gt;</code></p>
     <p><code>  &lt;line</code></p>
     <p><code>   x1="81.68060041188197" y1="31.70359014757173"</code></p>
     <p><code>   x2="168.29640985242827" y2="81.68060041188197"/&gt;</code></p>
     <p><code>  &lt;line</code></p>
     <p><code>   x1="168.29640985242827" y1="81.68060041188197"</code></p>
     <p><code>   x2="118.31939958811803" y2="168.29640985242827"/&gt;</code></p>
     <p><code>  &lt;line</code></p>
     <p><code>   x1="118.31939958811803" y1="168.29640985242827"</code></p>
     <p><code>   x2="31.70359014757173" y2="118.31939958811803"/&gt;</code></p>
     <p><code>  &lt;line</code></p>
     <p><code>   x1="31.70359014757173" y1="118.31939958811803"</code></p>
     <p><code>   x2="81.68060041188197" y2="31.70359014757173"/&gt;</code></p>
     <p><code> &lt;/g&gt; </code></p>
     <p><code>&lt;/svg&gt;</code></p>
     <p>Визуальное представление этого документа демонстрирует рис. 10.2, где представлен поворот, выполненный на 30°:</p>
     <image l:href="#img_84.png"/>
     <p><strong>Рис. 10.2</strong>. Визуальное представление полученного SVG-документа</p>
     <p>Анализируя полученный документ, мы можем заметить объявление пространства имен с префиксом <code>math</code>, которое было в него включено:</p>
     <p><code>&lt;svg</code></p>
     <p><code> xmlns="http://www.w3.org/2000/svg"</code></p>
     <p><code> xmlns:math="java:java.lang.Math"</code></p>
     <p><code> width="200"</code></p>
     <p><code> height="200"&gt;</code></p>
     <p><code> ...</code></p>
     <p>Это тот самый случай, когда объявление пространства имен используется в самом преобразовании, но является лишним в выходящем документе. Для того чтобы избавиться от него, нужно просто включить префикс <code>math</code> в атрибут <code>exclude-result-prefixes</code> элемента <code>xsl:stylesheet</code>.</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns="http://www.w3.org/2000/svg"</code></p>
     <p><code> xmlns:math="java:java.lang.Math"</code></p>
     <p><code> exclude-result-prefixes="math"&gt;</code></p>
     <p><code> ...</code></p>
     <p>Поскольку мы все равно используем в этом преобразовании расширения, мы можем написать свой собственный класс, который будет выполнять вычисление новых координат точки, исключив таким образом из преобразования все математические операции.</p>
     <subtitle>Листинг 10.8. Класс, вычисляющий координаты точки после поворота</subtitle>
     <p><code>package de.fzi.xslt;</code></p>
     <empty-line/>
     <p><code>public class rot {</code></p>
     <p><code> public static double X(double x, double y, double degree) {</code></p>
     <p><code>  double radian = Math.PI * degree / 180;</code></p>
     <p><code>  return x * Math.cos(radian) - y * Math.sin(radian);</code></p>
     <p><code> }</code></p>
     <empty-line/>
     <p><code> public static double Y(double x, double y, double degree) {</code></p>
     <p><code>  double radian = Math.PI * degree / 180;</code></p>
     <p><code>  return x * Math.sin(radian) + y * Math.cos(radian);</code></p>
     <p><code> }</code></p>
     <p><code>}</code></p>
     <p>Для того чтобы использовать методы этого класса в качестве функций расширения, немного изменим объявления в элементе <code>xsl:stylesheet</code>:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns="http://www.w3.org/2000/svg"</code></p>
     <p><code> xmlns:rot="java:de.fzi.xslt.rot"</code></p>
     <p><code> exclude-result-prefixes="rot"&gt;</code></p>
     <p>Создание элемента <code>line</code> теперь может быть записано в виде:</p>
     <p><code>&lt;line</code></p>
     <p><code> x1="{rot:X($x1, $y1, $alpha) + 100}"</code></p>
     <p><code> y1="{rot:Y($x1, $y1, $alpha) + 100}"</code></p>
     <p><code> x2="{rot:X($x2, $y2, $alpha) + 100}"</code></p>
     <p><code> y2="{rot:Y($x2, $y2, $alpha) + 100}"/&gt;</code></p>
     <p>Как мы отмечали выше, интерфейсы использования функций расширения весьма различаются между разными процессорами даже в случае такого переносимого языка, как Java. Отличия могут быть и в форме вызовов функций, и в форме объявлений пространств имен. Например, в процессоре Saxon пространство имен для класса <code>de.fzi.xslt.rot</code> может быть объявлено как:</p>
     <p><code>xmlns:rot="java:de.fzi.xslt.rot"</code></p>
     <p>в Xalan — как:</p>
     <p><code>xmlns:rot="xalan://de.fzi.xslt.rot"</code></p>
     <p>в Oracle XSLT Processor — как:</p>
     <p><code>xmlns:rot="http://www.oracle.com/XSL/Transform/java/de.fzi.xslt.rot"</code></p>
     <p>При этом сами вызовы во всех трех случаях будут одинаковыми:</p>
     <p><code>rot:X($x, $y, $angle)</code></p>
     <p>для метода X или</p>
     <p><code>rot:Y($x, $y, $angle)</code></p>
     <p>для метода Y.</p>
    </section>
    <section>
     <title>
      <p>Функция <emphasis>function-available</emphasis></p>
     </title>
     <p>При использовании функций расширения всегда есть вероятность того, что это расширение в силу каких-либо причин поддерживаться данным процессором не будет. Чаще всего это случается, во-первых, когда процессор просто физически не в состоянии вызвать эту функцию (например, процессор, написанный на C++, вряд ли будет содержать средства для выполнения Java-кода), во-вторых, когда расширение недоступно (например, процессор не в состоянии найти указанный Java-класс или динамическую библиотеку), и в-третьих, когда пространство имен объявлено неверно (например, с URI <code>java:de.fzi.xslt.rot</code> вместо <code>xalan://de.fzi.xslt.rot</code>). Результатом обращения к неподдерживаемому расширению будет, естественно, ошибка.</p>
     <p>XSLT позволяет избежать подобного рода ошибок путем предварительной проверки наличия заданной функции расширения. Для этой цели служит стандартная функция <code>function-available</code> (от англ. function is available — функция доступна)</p>
     <p><code><emphasis>boolean </emphasis><strong>function-available</strong>(<emphasis>string</emphasis>)</code></p>
     <p>Функция <code>function-available</code> принимает на вход строку, представляющую имя функции и возвращает <code>true</code>, если эта функция может быть вызвана и <code>false</code> — если нет.</p>
     <p>Строковый аргумент этой функции представляет расширенное имя функции, он должен соответствовать продукции <code>QName</code>, то есть иметь вид <code><emphasis>имя</emphasis></code> или <code><emphasis>префикс</emphasis>:<emphasis>имя</emphasis></code>. В первом случае <code>function-available</code> проверяет, реализована ли в данном процессоре стандартная функция с таким именем, например <code>function-available('concat')</code> скорее всего, возвратит <code>true</code>.</p>
     <p>В случае, если аргумент <code>function-available</code> имеет вид <code><emphasis>префикс</emphasis>:<emphasis>имя</emphasis></code>, функция <code>function-available</code> проверяет доступность указанной функции расширения. Например, для того, чтобы проверить, может ли в данном контексте быть вызвана функция <code>rot:X</code>, необходимо вычислить выражение</p>
     <p><code>function-available('rot:X')</code></p>
     <p>В данном случае <code>true</code> будет означать, что функция <code>rot:X</code> может быть вызвана, <code>false</code> — что функция в силу каких-то причин недоступна.</p>
     <p>Функция <code>function-available</code> может помочь в создании преобразований, которые используют расширения, но при этом в некоторой степени сохраняют переносимость между различными процессорами. Достаточно написать несколько вариантов вызова функции расширения для каждого из процессоров, на которых преобразование должно работать, а затем использовать вариант с доступной данному процессору функцией расширения.</p>
     <subtitle>Пример</subtitle>
     <p>Для того чтобы обеспечить работоспособность расширения, реализованного классом <code>de.fzi.xslt.rot</code> в наиболее распространенных XSLT-процессорах, написанных на Java (как-то: Saxon, Xalan и Oracle XSLT Processor), прежде всего необходимо объявить соответствующие пространства имен:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns="http://www.w3.org/2000/svg"</code></p>
     <p><code> xmlns:saxon="java:de.fzi.xslt.rot"</code></p>
     <p><code> xmlns:xalan="xalan://de.fzi.xslt.rot"</code></p>
     <p><code> xmlns:oracle="http://www.oracle.com/XSL/Transform/java/de.fzi.xslt.rot"</code></p>
     <p><code> exclude-result-prefixes="saxon xalan oracle"&gt;</code></p>
     <p><code>...</code></p>
     <p>Префикс <code>saxon</code> соответствует интерфейсу расширений в XSLT-процессоре Saxon, префикс <code>xalan</code> — процессору Xalan и префикс <code>oracle</code> — Oracle XSLT Processor.</p>
     <p>Теперь осталось только найти поддерживаемый вариант расширения и произвести соответствующий вызов.</p>
     <subtitle>Листинг 10.9</subtitle>
     <p><code>&lt;xsl:choose&gt;</code></p>
     <p><code> &lt;xsl:when test="function-available('saxon:X') "&gt;</code></p>
     <p><code>  &lt;line</code></p>
     <p><code>   x1="{saxon:X($x1, $y1, $alpha) + 100}"</code></p>
     <p><code>   y1="{saxon:Y($x1, $y1, $alpha) + 100}"</code></p>
     <p><code>   x2="{saxon:X($x2, $y2, $alpha) + 100}"</code></p>
     <p><code>   y2="{saxon:Y($x2, $y2, $alpha) + 100}"/&gt;</code></p>
     <p><code> &lt;/xsl:when&gt;</code></p>
     <p><code> &lt;xsl:when test="function-available('xalan:X')"&gt;</code></p>
     <p><code>  &lt;line</code></p>
     <p><code>   x1="{xalan:X($x1, $y1, $alpha) + 100}"</code></p>
     <p><code>   y1="{xalan:Y($x1, $y1, $alpha) + 100}"</code></p>
     <p><code>   x2="{xalan:X($x2, $y2, $alpha) + 100}"</code></p>
     <p><code>   y2="{xalan:Y($x2, $y2, $alpha) + 100}"/&gt;</code></p>
     <p><code> &lt;/xsl:when&gt;</code></p>
     <p><code> &lt;xsl:when test="function-available('oracle:X')"&gt;</code></p>
     <p><code>  &lt;line</code></p>
     <p><code>   x1="{oracle:X($x1, $y1, $alpha) + 100}"</code></p>
     <p><code>   y1="{oracle:Y($x1, $y1, $alpha) + 100}"</code></p>
     <p><code>   x2="{oracle:X($x2, $y2, $alpha) + 100}"</code></p>
     <p><code>   y2="{oracle:Y($x2, $y2, $alpha) + 100}"/&gt;</code></p>
     <p><code> &lt;/xsl:when&gt;</code></p>
     <p><code> &lt;xsl:otherwise&gt;</code></p>
     <p><code>  &lt;xsl:message terminate="yes"&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;Necessary extension function is not available.&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;&amp;#xA;Supported processors are:&lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;&amp;#xA;Saxon, Xalan, Oracle XSLT Processor.&lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;/xsl:message&gt;</code></p>
     <p><code> &lt;/xsl:otherwise&gt;</code></p>
     <p><code>&lt;/xsl:choose&gt;</code></p>
     <p>В случае, если хотя бы одна из функций <code>saxon:X</code>, <code>xalan:X</code>, <code>oracle:X</code> будет доступна при обработке, она будет использована процессором для создания атрибутов элемента <code>line</code>. В противном случае, процессор прервет выполнение преобразования и выведет указанное в элементе <code>xsl:message</code> сообщение.</p>
     <p>Нельзя не согласиться с тем, что приведенный выше способ не отличается элегантностью. Реализовывать свой вариант для каждого существующего процессора может быть довольно трудоемкой задачей — но такова уж плата за возможности расширений.</p>
    </section>
    <section>
     <title>
      <p>Функция расширения<emphasis> nodeset</emphasis></p>
     </title>
     <p>Одной из самых полезных функций расширения, которая, как правило, уже штатно реализована во многих процессорах (то есть, не требует дополнительного программирования) является функция <code>nodeset</code>. Эта функция позволяет в обход прямого запрета спецификации конвертировать результирующий фрагмент дерева во множество узлов.</p>
     <p>Предположим, что мы создаем в переменной <code>rtf</code> результирующий фрагмент дерева следующего вида:</p>
     <p><code>&lt;xsl:variable name="rtf"&gt;</code></p>
     <p><code> &lt;item&gt;1&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;2&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;3&lt;/item&gt;</code></p>
     <p><code>&lt;/xsl:variable&gt;</code></p>
     <p>При попытке вычислить выражение вида <code>$rtf/item[2]</code> процессор в соответствии со спецификацией должен вывести ошибку, поскольку в этом фильтрующем выражении (<emphasis>см. продукцию</emphasis> <code>[XP20] FilterExpr</code>) переменная <code>rtf</code> должна содержать множество узлов, а не фрагмент дерева.</p>
     <p>Текущая спецификация языка XPath совершенно явно говорит о том, что ни один тип данных не может быть преобразован во множество узлов. Функция <code>nodeset</code> действует в обход этого запрещения: она принимает на вход результирующий фрагмент дерева и возвращает множество, состоящее из корневого узла этого фрагмента.</p>
     <p>В разных процессорах эта функция имеет различный синтаксис: она может носить имя <code>nodeset</code> или <code>node-set</code>, или <code>nodeSet</code>, однако семантика ее во всех случаях одинакова:</p>
     <p><code><emphasis>nodeset </emphasis><strong>nodeset</strong>(<emphasis>result-tree-fragment</emphasis>)</code></p>
     <p>Функция принимает на вход единственный аргумент, являющийся фрагментом дерева и возвращает множество узлов, состоящее из его корня.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что мы обрабатываем входящий документ, содержащий трехбуквенные коды языков.</p>
     <subtitle>Листинг 10.10. Входящий документ</subtitle>
     <p><code>&lt;items&gt;</code></p>
     <p><code> &lt;item&gt;ENG&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;FRE&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;GER&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;GRE&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;ITA&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;NOR&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;POR&lt;/item&gt;</code></p>
     <p><code> &lt;item&gt;SPA&lt;/item&gt;</code></p>
     <p><code>&lt;/items&gt;</code></p>
     <p>Фрагмент шаблона, обрабатывающий этот список, может выглядеть следующим образом:</p>
     <p><code>&lt;select name="language"&gt;</code></p>
     <p><code> &lt;xsl:for-each select="items/item"&gt;</code></p>
     <p><code>  &lt;option&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code>  &lt;/option&gt;</code></p>
     <p><code> &lt;/xsl:for-each&gt;</code></p>
     <p><code>&lt;/select&gt;</code></p>
     <p>Если в преобразовании нам понадобится доопределить входящий список кодами <code>RUS</code> и <code>UKR</code>, не исправляя входящий документ, можно поступить следующим образом:</p>
     <p>&#9633; создать в переменной фрагмент дерева, содержащий элементы <code>item</code> входящего документа плюс элементы <code>item</code>, доопределяющие этот список;</p>
     <p>&#9633; преобразовать дерево в список узлов;</p>
     <p>&#9633; обрабатывать список узлов точно так же, как мы бы обрабатывали сам входящий документ.</p>
     <p>Преобразование, реализующее эти три шага, приведено ниже.</p>
     <subtitle>Листинг 10.11. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:xalan="http://xml.apache.org/xalan"</code></p>
     <p><code> exclude-result-prefixes="xalan"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="items"&gt;</code></p>
     <p><code>  &lt;!--</code></p>
     <p><code>   | Создаем переменную tree, содержащую элементы item</code></p>
     <p><code>   | входящего документа а также два дополнительных элемента</code></p>
     <p><code>   +--&gt;</code></p>
     <p><code>  &lt;xsl:variable name="tree"&gt;</code></p>
     <p><code>   &lt;xsl:copy-of select="item"/&gt;</code></p>
     <p><code>   &lt;item&gt;RUS&lt;/item&gt;</code></p>
     <p><code>   &lt;item&gt;UKR&lt;/item&gt;</code></p>
     <p><code>  &lt;/xsl:variable&gt;</code></p>
     <p><code>  &lt;!--</code></p>
     <p><code>   | Конвертируем переменную tree во множество узлов,</code></p>
     <p><code>   | результат присваиваем переменной items</code></p>
     <p><code>   +--&gt;</code></p>
     <p><code>  &lt;xsl:variable name="items" select="xalan:nodeset($tree)"/&gt;</code></p>
     <p><code>  &lt;!--</code></p>
     <p><code>   | Обрабатываем узлы $items/item точно так же,</code></p>
     <p><code>   | как мы обрабатывали бы узлы items/item</code></p>
     <p><code>   +--&gt;</code></p>
     <p><code>  &lt;select name="language"&gt;</code></p>
     <p><code>   &lt;xsl:for-each select="$items/item"&gt;</code></p>
     <p><code>    &lt;option&gt;</code></p>
     <p><code>     &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code>    &lt;/option&gt;</code></p>
     <p><code>   &lt;/xsl:for-each&gt;</code></p>
     <p><code>  &lt;/select&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результат этого преобразования приведен на следующем листинге.</p>
     <subtitle>Листинг 10.12. Выходящий документ</subtitle>
     <p><code>&lt;select name="language"&gt;</code></p>
     <p><code> &lt;option&gt;ENG&lt;/option&gt;</code></p>
     <p><code> &lt;option&gt;FRE&lt;/option&gt;</code></p>
     <p><code> &lt;option&gt;GER&lt;/option&gt;</code></p>
     <p><code> &lt;option&gt;GRE&lt;/option&gt;</code></p>
     <p><code> &lt;option&gt;ITA&lt;/option&gt;</code></p>
     <p><code> &lt;option&gt;NOR&lt;/option&gt;</code></p>
     <p><code> &lt;option&gt;POR&lt;/option&gt;</code></p>
     <p><code> &lt;option&gt;SPA&lt;/option&gt;</code></p>
     <p><code> &lt;option&gt;USA&lt;/option&gt;</code></p>
     <p><code> &lt;option&gt;RUS&lt;/option&gt;</code></p>
     <p><code> &lt;option&gt;UKR&lt;/option&gt;</code></p>
     <p><code>&lt;/select&gt;</code></p>
     <p>Вне всякого сомнения, функция <code>nodeset</code> является одним из наиболее востребованных в XSLT расширений, ведь возможность не только создавать, но и манипулировать уже созданными древовидными структурами является чрезвычайно полезной.</p>
     <p>В качестве одного из примеров применения функции <code>nodeset</code> можно привести реализацию с ее помощью многошаговых преобразований.</p>
     <p>В качестве примера рассмотрим схему трансформации, изображенную на рис. 10.3, в которой документ А сначала нужно обработать преобразованием 1, затем полученный результат (документ В) обработать преобразованием 2. Конечным результатом цепочки преобразований в данном случае является документ С.</p>
     <image l:href="#img_85.png"/>
     <p><strong>Рис. 10.3</strong>. Двухшаговое преобразование</p>
     <p>При выполнении преобразования процессор применяет шаблоны ко множеству узлов входящего документа и выстраивает результирующее дерево. Таким образом, для того, чтобы повторно применить шаблоны к уже обработанному документу (читай: к полученному дереву), нужно просто иметь возможность преобразовывать дерево во множество узлов.</p>
     <subtitle>Пример</subtitle>
     <p>Представим себе два простых преобразования, <code>first.xsl</code> и <code>second.xsl</code>, первое из которых заменяет во входящем документе элементы <code>а</code> на элементы <code>b</code>, а второе — элементы <code>b</code> на элементы <code>с</code>.</p>
     <subtitle>Листинг 10.13. Преобразование first.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="a"&gt;</code></p>
     <p><code>  &lt;b&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code>  &lt;/b&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="@*|node()"&gt;</code></p>
     <p><code>  &lt;xsl:copy&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code>  &lt;/xsl:copy&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 10.14. Преобразование second.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="b"&gt;</code></p>
     <p><code>  &lt;c&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code>  &lt;/c&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="@*|node()"&gt;</code></p>
     <p><code>  &lt;xsl:copy&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()"/&gt;</code></p>
     <p><code>   &lt;/xsl:copy&gt;</code></p>
     <p><code>  &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Для того чтобы последовательно применить два этих преобразования к некоторому входящему документу <code>a.xml</code>, мы можем, например, дважды вызвать процессор:</p>
     <p><code>java org.apache.xalan.xslt.Process -IN a.xml -XSL first.xsl -OUT b.xml</code></p>
     <p><code>java org.apache.xalan.xslt.Process -IN b.xml -XSL second.xsl -OUT c.xml</code></p>
     <p>В результате этих вызовов XSLT-процессор Xalan сначала применит преобразование <code>first.xsl</code> к документу <code>a.xml</code> и сохранит результат в файле <code>b.xml</code>, а затем обработает полученный документ <code>b.xml</code> при помощи преобразования <code>second.xml</code> и сохранит результат в файле <code>c.xml</code>.</p>
     <p>В качестве альтернативы, например, для тех случаев, когда пакетная обработка невозможна, мы можем создать преобразование, последовательно применяющее шаблоны преобразований <code>first.xsl</code> и <code>second.xsl</code> к входящему документу. Для этого:</p>
     <p>&#9633; назначим шаблонам преобразования <code>first.xsl</code> режим <code>first</code>, а шаблонам преобразования <code>second.xsl</code> — режим <code>second</code>;</p>
     <p>&#9633; в основном шаблоне применим шаблоны режима <code>first</code> к узлам входящего документа, сохранив результат в переменной <code>b</code>;</p>
     <p>&#9633; приведем результирующее дерево, содержащееся в переменной <code>b</code> ко множеству узлов;</p>
     <p>&#9633; обработаем полученное множество узлов шаблонами режима <code>second</code>.</p>
     <p>Следующий листинг демонстрирует предложенный подход.</p>
     <subtitle>Листинг 10.5. Преобразование first-then-second.xsl</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:xalan="http://xml.apache.org/xalan"</code></p>
     <p><code> exclude-result-prefixes="xalan"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Шаблоны преобразования first --&gt;</code></p>
     <p><code> &lt;xsl:template match="a" mode="first"&gt;</code></p>
     <p><code>  &lt;b&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()" mode="first"/&gt;</code></p>
     <p><code>  &lt;/b&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="@*|node()" mode="first"&gt;</code></p>
     <p><code>  &lt;xsl:copy&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()" mode="first"/&gt;</code></p>
     <p><code>  &lt;/xsl:copy&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Шаблоны преобразования second --&gt;</code></p>
     <p><code> &lt;xsl:template match="@*|node()" mode="second"&gt;</code></p>
     <p><code>  &lt;xsl:copy&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()" mode="second"/&gt;</code></p>
     <p><code>  &lt;/xsl:copy&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="b" mode="second"&gt;</code></p>
     <p><code>  &lt;c&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="@*|node()" mode="second"/&gt;</code></p>
     <p><code>  &lt;/c&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- Основное преобразование --&gt;</code></p>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;!-- Присваиваем переменной а корень входящего документа --&gt;</code></p>
     <p><code>  &lt;xsl:variable name="a" select="/"/&gt;</code></p>
     <p><code>  &lt;!-- Выводим переменную a --&gt;</code></p>
     <p><code>  &lt;xsl:comment&gt; a: &lt;/xsl:comment&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$a"/&gt;</code></p>
     <p><code>  &lt;!-- Присваиваем переменной b результат обработки переменной a --&gt;</code></p>
     <p><code>  &lt;xsl:variable name="b"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="$a" mode="first"/&gt;</code></p>
     <p><code>  &lt;/xsl:variable&gt;</code></p>
     <p><code>  &lt;!-- Выводим переменную b --&gt;</code></p>
     <p><code>  &lt;xsl:comment&gt; b: &lt;/xsl:comment&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$b"/&gt;</code></p>
     <p><code>  &lt;!-- Присваиваем переменной с результат обработки переменной b --&gt;</code></p>
     <p><code>  &lt;xsl:variable name="c"&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="xalan:nodeset($b)" mode="second"/&gt;</code></p>
     <p><code>  &lt;/xsl:variable&gt;</code></p>
     <p><code>  &lt;!-- Выводим переменную c --&gt;</code></p>
     <p><code>  &lt;xsl:comment&gt; c: &lt;/xsl:comment&gt;</code></p>
     <p><code>  &lt;xsl:copy-of select="$c"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Ход этого преобразования лучше всего прокомментирует полученный результат.</p>
     <subtitle>Листинг 10.16. Входящий документ</subtitle>
     <p><code>&lt;а&gt;</code></p>
     <p><code> &lt;a&gt;1&lt;/a&gt;</code></p>
     <p><code> &lt;a&gt;2&lt;/a&gt;</code></p>
     <p><code>&lt;/а&gt;</code></p>
     <subtitle>Листинг 10.17. Выходящий документ</subtitle>
     <p><code>&lt;!-- а: --&gt;</code></p>
     <p><code>&lt;а&gt;</code></p>
     <p><code> &lt;a&gt;1&lt;/a&gt;</code></p>
     <p><code> &lt;a&gt;2&lt;/a&gt;</code></p>
     <p><code>&lt;/а&gt;</code></p>
     <p><code>&lt;!-- b:--&gt;</code></p>
     <p><code>&lt;b&gt;</code></p>
     <p><code> &lt;b&gt;1&lt;/b&gt;</code></p>
     <p><code> &lt;b&gt;2&lt;/b&gt;</code></p>
     <p><code>&lt;/b&gt;</code></p>
     <p><code>&lt;!-- с: --&gt;</code></p>
     <p><code>&lt;с&gt;</code></p>
     <p><code> &lt;c&gt;1&lt;/c&gt;</code></p>
     <p><code> &lt;c&gt;2&lt;/c&gt;</code></p>
     <p><code>&lt;/с&gt;</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Элементы расширения</p>
    </title>
    <section>
     <p>Другой, несколько реже используемой, но не менее мощной возможностью расширения XSLT являются элементы расширения. В отличие от обычных элементов, при выполнении преобразования элементы расширения не просто копируются в выходящее дерево. При их обработке процессор должен выполнить определенные действия. Например, многие XSLT-процессоры, написанные на Java, позволяют связывать элементы расширения с методами Java-классов.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что при выполнении преобразования в выходящий документ нам необходимо включить информацию о том, когда документ был сгенерирован — добавить элемент вида:</p>
     <p><code>&lt;p&gt;This page was generated at 10:23.&lt;/p&gt;</code></p>
     <p>Пожалуй, самым элегантным решением этой задачи будет использование элемента расширения, который копировал бы в выходящий документ текущее время. Иначе говоря, при выполнении шаблона вида:</p>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;!-- ... --&gt;</code></p>
     <p><code> &lt;p&gt;This page was generated at &lt;ext:time/&gt;.&lt;/p&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>элемент расширения <code>ext:time</code> должен быть заменен текущим временем. Ниже мы приведем пример реализации этого элемента для процессора Xalan.</p>
     <p>Интерфейс программирования расширений в Xalan требует, чтобы для каждого элемента расширения был определен метод вида:</p>
     <p><code><emphasis>тип элемент</emphasis>(org.apache.xalan.extensions.XSLProcessorContext context,</code></p>
     <p><code>            org.apache.xalan.templates.ElemExtensionCall elem)</code></p>
     <p>где <code><emphasis>тип</emphasis></code> — тип возвращаемого значения, а <code><emphasis>элемент</emphasis></code> — локальная часть имени элемента расширения. Поскольку мы создаем элемент с локальной частью имени time и строковым типом возвращаемых данных, прототип нашего метода будет выглядеть как:</p>
     <p><code>public String time(XSLProcessorContext context,</code></p>
     <p><code>                   ElemExtensionCall elem)</code></p>
     <p>Два аргумента, которые передаются методу элемента расширения, описывают контекст преобразования (<code>XSLProcessorContext</code>) и параметры вызова элемента расширения (<code>ElemExtensionCall</code>). Чуть позже мы покажем, как можно использовать эти объекты для создания более функциональных элементов расширения; пока же продолжим с элементом <code>ext:time</code>.</p>
     <p>Следующим шагом мы создадим класс расширения <code>ext.java</code>, в котором реализуем описанный выше метод <code>time</code>.</p>
     <subtitle>Листинг 10.18 Класс ext.java</subtitle>
     <p><code>package de.fzi.xslt;</code></p>
     <empty-line/>
     <p><code>import java.util.Date;</code></p>
     <p><code>import java.text.SimpleDateFormat;</code></p>
     <p><code>import org.apache.xalan.extensions.XSLProcessorContext;</code></p>
     <p><code>import org.apache.xalan.templates.ElemExtensionCall;</code></p>
     <empty-line/>
     <p><code>public class ext {</code></p>
     <empty-line/>
     <p><code> public String time(XSLProcessorContext context,</code></p>
     <p><code>  ElemExtensionCall elem) {</code></p>
     <p><code>  SimpleDateFormat df = new SimpleDateFormat("HH:mm");</code></p>
     <p><code>  return df.format(new Date());</code></p>
     <p><code> }</code></p>
     <p><code>}</code></p>
     <p>Равно как и в случае с функциями расширения, связующим звеном между элементами и Java-имплементацией их семантики служат пространства имен. В нашем случае класс <code>de.fzi.xslt.ext</code> может быть связан с префиксом пространства имен <code>ext</code> следующим объявлением:</p>
     <p><code>xmlns:ext="xalan://de.fzi.xslt.ext"</code></p>
     <p>Однако это еще не все. Для того чтобы элементы определенного пространства имен воспринимались процессором как элементы расширения, необходимо также явно указать префиксы этих пространств в атрибуте <code>extension-element-prefixes</code> элемента <code>xsl:stylesheet</code>:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> ...</code></p>
     <p><code> extension-element-prefixes="ext"&gt;</code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>В итоге наше преобразование будет иметь следующий вид.</p>
     <subtitle>Листинг 10.19. Преобразование, использующее элемент расширения</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:ext="xalan://de.fzi.xslt.ext"</code></p>
     <p><code> extension-element-prefixes="ext"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;!-- ... --&gt;</code></p>
     <p><code>  &lt;p&gt;This page was generated at &lt;ext:time/&gt;.&lt;/p&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результатом этого преобразования будет документ вида:</p>
     <p><code>&lt;p&gt;This page was generated at 11:56.&lt;/p&gt;</code></p>
     <p>Функциональность предложенного выше элемента расширения может быть легко расширена. Например, мы можем создать элемент <code>ext:date</code>, который будет выводить текущую дату или время в формате, зависящем от значения его атрибута <code>pattern</code>.</p>
     <subtitle>Листинг 10.20. Класс ext.java реализация элемента ext:date</subtitle>
     <p><code>package de.fzi.xslt;</code></p>
     <empty-line/>
     <p><code>import java.util.Date;</code></p>
     <p><code>import java.text.SimpleDateFormat;</code></p>
     <p><code>import org.apache.xalan.extensions.XSLProcessorContext;</code></p>
     <p><code>import org.apache.xalan.templates.ElemExtensionCall;</code></p>
     <empty-line/>
     <p><code>public class ext{</code></p>
     <p><code> public String date(XSLProcessorContext context, ElemExtensionCall elem) {</code></p>
     <p><code>  SimpleDateFormat df;</code></p>
     <empty-line/>
     <p><code>  // Получаем значение атрибута pattern элемента расширения</code></p>
     <p><code>  String pattern = elem.getAttribute("pattern");</code></p>
     <p><code>  // Если атрибут pattern не определен,</code></p>
     <p><code>  // используем образец форматирования, определенный по умолчанию</code></p>
     <p><code>  if (pattern == null)</code></p>
     <p><code>   df = new SimpleDateFormat();</code></p>
     <p><code>  // Если атрибут pattern определен, используем его значение</code></p>
     <p><code>  // в качестве образца форматирования</code></p>
     <p><code>  else</code></p>
     <p><code>   df = new SimpleDateFormat(pattern);</code></p>
     <p><code>  return df.format(new Date());</code></p>
     <p><code> }</code></p>
     <p><code>}</code></p>
     <p>В преобразовании этот элемент мы можем использовать как:</p>
     <p><code>&lt;p&gt;This page was generated at &lt;ext:date pattern="HH:mm"/&gt; on</code></p>
     <p><code>&lt;ext:date pattern="dd/MM/yyyy"/&gt;.&lt;/p&gt;</code></p>
     <p>или:</p>
     <p><code>&lt;p&gt;This page was generated on &lt;ext:date/&gt;.&lt;/p&gt;</code></p>
     <p>В первом случае результатом будет:</p>
     <p><code>&lt;p&gt;This page was generated at 12:11 on 08/10/2001.&lt;/p&gt;</code></p>
     <p>Во втором:</p>
     <p><code>&lt;p&gt;This page was generated on 08.10.01 12:11.&lt;/p&gt;</code></p>
     <p>Естественно, семантика элементов расширения не ограничивается простым копированием в выходящий документ заданных значений. Элементы расширения могут выполнять гораздо более сложные функции, ограниченные, пожалуй, лишь только воображением разработчика. При этом элементы расширения на удивление удачно вписываются в структуру самого преобразования, ведь принцип их использования не сильно отличается от принципа использования самих элементов XSLT.</p>
    </section>
    <section>
     <title>
      <p>Функция <emphasis>element-available</emphasis></p>
     </title>
     <p><code><emphasis>boolean </emphasis><strong>element-available</strong>(<emphasis>string</emphasis>)</code></p>
     <p>Функция <code>element-available</code> совершенно аналогична функции <code>function-available</code>: она служит для проверки доступности в преобразовании того или иного элемента. Строковый параметр <code>element-available</code> задает расширенное имя элемента; функция возвращает <code>true</code>, если элемент с таким именем доступен, <code>false</code> — если нет.</p>
     <subtitle>Пример</subtitle>
     <p>Предположим, что преобразование, созданное нами для процессора Xalan с использованием элемента расширения <code>ext:date</code>, будет выполняться на каком-либо другом процессоре. В этом случае велика вероятность того, что вследствие несовместимости механизмов расширений это преобразование завершится ошибкой — "чужой" процессор просто не сможет выполнить элемент <code>ext:date.</code></p>
     <p>Во избежание этого, мы можем использовать функцию <code>element-available</code> для проверки доступности элемента <code>ext:date</code> до его вызова.</p>
     <subtitle>Листинг 10.21. Преобразование, использующее функцию element-available</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:ext="xalan://de.fzi.xslt.ext"</code></p>
     <p><code> extension-element-prefixes="ext"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;result&gt;</code></p>
     <p><code>   &lt;xsl:if test="element-available('ext:date')"&gt;</code></p>
     <p><code>    &lt;p&gt;This page was generated at &lt;ext:date pattern="HH:mm"/&gt; on &lt;ext:date pattern="dd/MM/yyyy"/&gt;.&lt;/p&gt;</code></p>
     <p><code>   &lt;/xsl:if&gt;</code></p>
     <p><code>  &lt;/result&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    </section>
    <section>
     <title>
      <p>Элемент<emphasis> xsl:fallback</emphasis></p>
     </title>
     <p>Другим способом обработки исключительных ситуаций, связанных с невозможностью выполнить тот или иной элемент преобразования, является использование элемента <code>xsl:fallback</code>. Синтаксическая конструкция этого элемента следующая:</p>
     <p><code>&lt;xsl:fallback&gt;</code></p>
     <p><code> &lt;!-- Содержимое: шаблон --&gt;</code></p>
     <p><code>&lt;/xsl:fallback&gt;</code></p>
     <p>Элемент <code>xsl:fallback</code> включается в "критическую" инструкцию, то есть в элемент, который может быть неизвестен процессору. В случае, если критическая инструкция отрабатывается нормально, содержимое <code>xsl:fallback</code> попросту игнорируется. Иначе, если процессор в силу некоторых причин не может выполнить критическую инструкцию, вместо нее он будет выполнять содержимое дочернего элемента <code>xsl:fallback</code>.</p>
     <subtitle>Пример</subtitle>
     <p>На тот случай, если процессор не сможет выполнить наш элемент расширения <code>ext:date</code>, мы можем "подстраховать" его следующим образом:</p>
     <p><code>&lt;ext:date pattern="HH:mm"&gt;</code></p>
     <p><code> &lt;xsl:fallback&gt;unknown time&lt;/xsl:fallback&gt;</code></p>
     <p><code>&lt;/ext:date&gt;</code></p>
     <p>В этом случае шаблон</p>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;!-- ... --&gt;</code></p>
     <p><code> &lt;p&gt;This page was generated at &lt;ext:date pattern="HH:yy"&gt;</code></p>
     <p><code>  &lt;xsl:fallback&gt;unknown time&lt;/xsl:fallback&gt;</code></p>
     <p><code> &lt;/ext:date&gt;.&lt;/p&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>в случае невозможности выполнить <code>ext:date</code> выведет</p>
     <p><code>&lt;p&gt;This page was generated at unknown time.&lt;/p&gt;</code></p>
     <p>Заметим, что <code>xsl:fallback</code> применим не только для обработки исключительных ситуаций, связанных с элементами расширения. Наборы доступных процессору элементов XSLT будут также меняться от версии к версии, и <code>xsl:fallback</code> вполне пригодится для обеспечения обратной совместимости. Например, если в версии XSLT 2.0 будет определен элемент <code>xsl:for-each-group</code>, то <code>xsl:fallback</code> можно использовать при создании альтернативного варианта для процессоров, которые еще не поддерживают новую версию:</p>
     <p><code>&lt;xsl:for-each-group select="item" group-by="@number"&gt;</code></p>
     <p><code> &lt;!-- ... --&gt;</code></p>
     <p><code> &lt;xsl:fallback&gt;</code></p>
     <p><code>  &lt;xsl:for-each select="item[generate-id(.)=</code></p>
     <p><code>   generate-id(key('item', @number))]"&gt;</code></p>
     <p><code>   &lt;!-- ... --&gt;</code></p>
     <p><code>  &lt;/xsl:for-each&gt;</code></p>
     <p><code> &lt;/xsl:fallback&gt;</code></p>
     <p><code>&lt;/xsl:for-each&gt;</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Инициатива EXSLT</p>
    </title>
    <p>Функции и элементы расширения с лихвой восполняют ограниченность языков XSLT и XPath, предоставляя возможности обычных императивных языков там, где они необходимы. Между тем, как показывает практика, задачи, которые приходится решать при помощи расширений, как правило, совершенно стандартны — например, разобранная выше функция nodeset, так или иначе реализована почти во всех XSLT-процессорах.</p>
    <p>Инициатива EXSLT была порождена естественным желанием разработчиков иметь в своих XSLT-преобразованиях стандартные расширения и не дублировать усилия по решению общих проблем. В рамках EXSLT создаются стандартные библиотеки расширений XSLT для различных процессоров. Кроме того, EXSLT активно поддерживается многими разработчиками XSLT-процессоров с тем, чтобы обеспечить переносимость преобразований, использующих EXSLT-расширения.</p>
    <p>Для конечного пользователя EXSLT — это множество библиотек расширений, которые можно загрузить с сайта <strong>http://www.exslt.org</strong>. Помимо этого, EXSLT-расширения уже являются встроенными для некоторых процессоров. Например, в процессоре Saxon реализовано большинство элементов и функций расширения EXSLT.</p>
    <p>На данном этапе разработанные в рамках EXSLT библиотеки включают в себя следующие модули.</p>
    <p>&#9633; <code>Common</code> — общие функции и элементы расширения. Включает функции <code>exslt:node-set</code> и <code>exslt:object-type</code> и элемент <code>exslt:document</code>.</p>
    <p>&#9633; <code>Math</code> — математические функции.</p>
    <p>&#9633; <code>Sets</code> — функции для работы с множествами узлов (как-то: пересечение, разность и так далее).</p>
    <p>&#9633; <code>Functions</code> — элементы для определения пользовательских функций.</p>
    <p>&#9633; <code>Dates and Times</code> — элементы и функции для работы с временными параметрами.</p>
    <p>&#9633; <code>Strings</code> — модуль для работы со строками.</p>
    <p>&#9633; <code>Regular Expressions</code> — функции для работы с регулярными выражениями.</p>
    <p>EXSLT покрывает большинство стандартных задач расширений — поэтому, прежде, чем браться за разработку собственных модулей расширения, следует проверить — нет ли уже реализованных аналогов. Кроме того, библиотеки EXSLT могут послужить хорошим примером программирования расширений.</p>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 11</p>
    <p>Готовые решения</p>
   </title>
   <section>
    <title>
     <p>Группировка</p>
    </title>
    <p>Мы уже рассматривали задачу группировки, когда разбирали устройство и функционирование ключей — это была та самая задача, в которой из документа вида.</p>
    <subtitle>Листинг 11.1 Входящий документ</subtitle>
    <p><code>&lt;items&gt;</code></p>
    <p><code> &lt;item source="a" name="A"/&gt;</code></p>
    <p><code> &lt;item source="b" name="B"/&gt;</code></p>
    <p><code> &lt;item source="a" name="C"/&gt;</code></p>
    <p><code> &lt;item source="c" name="D"/&gt;</code></p>
    <p><code> &lt;item source="b" name="E"/&gt;</code></p>
    <p><code> &lt;item source="b" name="F"/&gt;</code></p>
    <p><code> &lt;item source="c" name="G"/&gt;</code></p>
    <p><code> &lt;item source="a" name="H"/&gt;</code></p>
    <p><code>&lt;/items&gt;</code></p>
    <p>нужно было получить документ вида.</p>
    <subtitle>Листинг 11.2. Требуемый результат</subtitle>
    <p><code>&lt;sources&gt;</code></p>
    <p><code> &lt;source name="а"&gt;</code></p>
    <p><code>  &lt;item source="a" name="A"/&gt;</code></p>
    <p><code>  &lt;item source="a" name="C"/&gt;</code></p>
    <p><code>  &lt;item source="a" name="H"/&gt;</code></p>
    <p><code> &lt;/source&gt;</code></p>
    <p><code> &lt;source name="b"&gt;</code></p>
    <p><code>  &lt;item source="b" name="B"/&gt;</code></p>
    <p><code>  &lt;item source="b" name="E"/&gt;</code></p>
    <p><code>  &lt;item source="b" name="F"/&gt;</code></p>
    <p><code> &lt;/source&gt;</code></p>
    <p><code> &lt;source name="c"&gt;</code></p>
    <p><code>  &lt;item source="c" name="D"/&gt;</code></p>
    <p><code>  &lt;item source="c" name="G"/&gt;</code></p>
    <p><code> &lt;/source&gt;</code></p>
    <p><code>&lt;/sources&gt;</code></p>
    <p>Легко понять, почему такая задача называется задачей группировки: требуется сгруппировать элементы <code>item</code> по значениям одного из своих атрибутов.</p>
    <p>Напомним вкратце решение, которое было тогда предложено. При обработке первого объекта каждой группы мы создавали элемент <code>source</code>, в который включали все элементы <code>item</code>, принадлежащие этой группе. Для определения первого элемента мы использовали выражение</p>
    <p><code>preceding-sibling::item[@source=current()/@source]</code></p>
    <p>которое возвращало непустое множество только тогда, когда элемент не был первым в группе.</p>
    <p>В этом разделе мы приведем гораздо более эффективное и остроумное решение задачи группировки, впервые предложенное Стивом Мюнхом (Steve Muench), техническим гуру из Oracle Corporation. Оно основывается на двух посылках.</p>
    <p>&#9633; Мы можем выбрать множество узлов по их свойствам при помощи ключей.</p>
    <p>&#9633; Мы можем установить, является ли узел первым узлом множества в порядке просмотра документа при помощи функции <code>generate-id</code>.</p>
    <p>С первым пунктом все, пожалуй, ясно — выбор множества узлов по определенному критерию — это самое прямое предназначение ключей. Второй же пункт оставляет легкое недоумение: функция <code>generate-id</code> вроде бы предназначена только для генерации уникальных значений.</p>
    <p>Для того чтобы развеять все сомнения, напомним, как ведет себя эта функция, если аргументом является множество узлов. В этом случае <code>generate-id</code> возвращает уникальный идентификатор <emphasis>первого</emphasis> в порядке просмотра документа узла переданного ей множества. Значит для того, чтобы проверить, является ли некий узел первым узлом группы, достаточно сравнить его уникальный идентификатор со значением выражения <code>generate-id($<emphasis>group</emphasis>)</code>, где <code>$<emphasis>group</emphasis></code> — множество узлов этой группы.</p>
    <p>С учетом приведенных выше возможностей группирующее преобразование переписывается удивительно элегантным образом.</p>
    <subtitle>Листинг 11.3. Группирующее преобразование</subtitle>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:key name="src" match="item" use="@source"/&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="items"&gt;</code></p>
    <p><code>  &lt;sources&gt;</code></p>
    <p><code>   &lt;xsl:apply-templates</code></p>
    <p><code>    select="item[generate-id(.)=generate-id(key('src', @source))]"/&gt;</code></p>
    <p><code>  &lt;/sources&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="item"&gt;</code></p>
    <p><code>  &lt;source name="{@source}"&gt;</code></p>
    <p><code>   &lt;xsl:copy-of select="key('src', @source)"/&gt;</code></p>
    <p><code>  &lt;/source&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <p>Результат выполнения этого преобразования уже был приведен в листинге 11.2.</p>
   </section>
   <section>
    <title>
     <p>Перечисление узлов</p>
    </title>
    <p>Функции <code>name</code> и <code>local-name</code> предоставляют возможности для работы с документом, имена элементов и атрибутов в котором заранее неизвестны. Например, если шаблон определен как:</p>
    <p><code>&lt;xsl:template match="*[starts-with(local-name(), 'чеб')]"&gt;</code></p>
    <p><code> ...</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>то обрабатываться им будут все элементы, локальные части имен которых начинаются на <code>"чеб"</code> (например, <code>"чебуреки"</code>, <code>"Чебоксары"</code>, <code>"чебурашка"</code>).</p>
    <p>Следующее преобразование демонстрирует, как при помощи функции <code>local-name</code> и ключей сосчитать количество элементов и атрибутов документа с различными именами.</p>
    <subtitle>Листинг 11.4. Входящий документ</subtitle>
    <p><code>&lt;foo bar="1"&gt;</code></p>
    <p><code> &lt;bar foo="2"/&gt;</code></p>
    <p><code> &lt;bar bar="3"/&gt;</code></p>
    <p><code> &lt;foo foo="4"&gt;</code></p>
    <p><code>  &lt;bar bar="5"/&gt;</code></p>
    <p><code>  &lt;bar foo="6"/&gt;</code></p>
    <p><code> &lt;/foo&gt;</code></p>
    <p><code>&lt;/foo&gt;</code></p>
    <subtitle>Листинг 11.5. Преобразование</subtitle>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;!-- Выводим информацию в текстовом виде --&gt;</code></p>
    <p><code> &lt;xsl:output method="text"/&gt;</code></p>
    <empty-line/>
    <p><code> &lt;!--</code></p>
    <p><code>  | Создаем ключ, отображающий узлы атрибутов и элементов</code></p>
    <p><code>  | в их локальные части имен.</code></p>
    <p><code>  +--&gt;</code></p>
    <p><code> &lt;xsl:key name="node" match="*" use="local-name()"/&gt;</code></p>
    <p><code> &lt;xsl:key name="node" match="@*" use="local-name()"/&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="*|@*"&gt;</code></p>
    <p><code>  &lt;xsl:variable name="name" select="local-name()"/&gt;</code></p>
    <p><code>  &lt;!--</code></p>
    <p><code>   | Если узел является первым узлом группы (первым встретившимся</code></p>
    <p><code>   | узлом документа с данным именем), выводим информацию о</code></p>
    <p><code>   | количестве узлов в группе (количество узлов с таким же именем).</code></p>
    <p><code>   +--&gt;</code></p>
    <p><code>  &lt;xsl:if test="generate-id(.) = generate-id(key('node', $name))"&gt;</code></p>
    <p><code>   &lt;xsl:text&gt;Node '&lt;/xsl:text&gt;</code></p>
    <p><code>   &lt;xsl:value-of select="local-name()"/&gt;</code></p>
    <p><code>   &lt;xsl:text&gt;' found &lt;/xsl:text&gt;</code></p>
    <p><code>   &lt;xsl:value-of select="count(key('node', $name))"/&gt;</code></p>
    <p><code>   &lt;xsl:text&gt; times.&amp;#xA;&lt;/xsl:text&gt;</code></p>
    <p><code>  &lt;/xsl:if&gt;</code></p>
    <p><code>  &lt;!-- Рекурсивно обрабатываем дочерний элемент и атрибуты --&gt;</code></p>
    <p><code>  &lt;xsl:apply-templates select="*|@*"/&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <subtitle>Листинг 11.6. Выходящий документ</subtitle>
    <p><code>Node 'foo' found 5 times.</code></p>
    <p><code>Node 'bar' found 7 times.</code></p>
   </section>
   <section>
    <title>
     <p>Именованный шаблон как функция</p>
    </title>
    <p>Сложно переоценить возможности механизмов расширений языка XSLT. Они позволяют сочетать простоту и гибкость обработки XML-документов при помощи элементов XSLT и выражений XPath. Практически любая функция, которая отсутствует в XSLT, может быть написана на подходящем языке программирования и подключена к процессору.</p>
    <p>Но как уже отмечалось ранее, функции расширения ограничивают переносимость преобразований. Во-первых, функции расширения одного процессора совсем необязательно будут присутствовать в другом процессоре — скорее наоборот. Во-вторых, не приходится надеяться, что пользовательские модули, написанные на одном языке или с использованием одного интерфейса, смогут использоваться любым процессором. Поэтому часто перед разработчиком стоит проблема решить определенную задачу, используя только стандартные функции и элементы XSLT.</p>
    <p>В этом разделе мы рассмотрим возможность использования именованных шаблонов в качестве функций, которые принимают на вход несколько параметров и возвращают некоторое вычисленное значение.</p>
    <p>Использование именованных шаблонов как функций обуславливается следующими тезисами.</p>
    <p>&#9633; Именованный шаблон можно вызывать вне зависимости от того, какая часть документа обрабатывается в данный момент.</p>
    <p>&#9633; Именованному шаблону можно передавать параметры.</p>
    <p>&#9633; Результат выполнения именованного шаблона можно присваивать переменной.</p>
    <p>Вызов именованного шаблона выполняется элементом <code>xsl:call-template</code>, в атрибуте <code>name</code> которого указывается имя вызываемого шаблона. Такой вызов не зависит от того, какая часть документа обрабатывается в данный момент и может производиться по необходимости.</p>
    <p>Параметры именованному шаблону передаются точно так же, как и обычному — при помощи элементов <code>xsl:with-param</code>, которые могут быть включены в вызывающий элемент <code>xsl:call-template</code>. Примером вызова именованного шаблона с параметрами может быть конструкция вида</p>
    <p><code>&lt;xsl:call-template name="foo"&gt;</code></p>
    <p><code> &lt;xsl:with-param name="x" select="1"/&gt;</code></p>
    <p><code> &lt;xsl:with-param name="y" select="2"/&gt;</code></p>
    <p><code>&lt;/xsl:call-template&gt;</code></p>
    <p>которая вызывает шаблон с именем <code>foo</code> и передает ему параметр <code>x</code> со значением, равным <code>1</code> и параметр <code>y</code> со значением, равным <code>2</code>.</p>
    <p>Вызов именованного шаблона может также производиться при инициализации переменной — внутри элемента xsl:variable. В этом случае с переменной связывается результирующий фрагмент дерева, возвращаемый именованным шаблоном.</p>
    <subtitle>Пример</subtitle>
    <p>В качестве примера приведем простой шаблон, который вычисляет квадрат переданного ему параметра <code>x</code>:</p>
    <p><code>&lt;xsl:template name="sqr"&gt;</code></p>
    <p><code> &lt;xsl:param name="x"/&gt;</code></p>
    <p><code> &lt;xsl:value-of select="$x * $x"/&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Для того чтобы присвоить переменной <code>у</code> квадрат числа <code>6</code> мы можем записать следующее:</p>
    <p><code>&lt;xsl:variable name="y"&gt;</code></p>
    <p><code> &lt;xsl:call-template name="sqr"&gt;</code></p>
    <p><code>  &lt;xsl:with-param name="x" select="6"/&gt;</code></p>
    <p><code> &lt;/xsl:call-template&gt;</code></p>
    <p><code>&lt;/xsl:variable&gt;</code></p>
    <p>Обратим внимание, что значение переменной <code>y</code> будет иметь вовсе не численный тип. Несмотря на то, что элемент</p>
    <p><code>&lt;xsl:value-of select="$y"/&gt;</code></p>
    <p>выведет строку "<code>36</code>", переменная у содержит не число, а дерево, и <code>36</code> лишь является результатом конвертации в строку при выполнении <code>xsl:value-of</code>.</p>
    <p>Для того чтобы присвоить переменной результат выполнения именованного шаблона в виде булевого значения, строки или числа, следует воспользоваться промежуточной переменной для явного преобразования типов.</p>
    <subtitle>Пример</subtitle>
    <p>После выполнения действий</p>
    <p><code>&lt;xsl:variable name="result"&gt;</code></p>
    <p><code> &lt;xsl:call-template name="sqr"&gt;</code></p>
    <p><code>  &lt;xsl:with-param name="x" select="6"/&gt;</code></p>
    <p><code> &lt;/xsl:call-template&gt;</code></p>
    <p><code>&lt;/xsl:variable&gt;</code></p>
    <p><code>&lt;xsl:variable name="sqr-string" select="string($result)"/&gt;</code></p>
    <p><code>&lt;xsl:variable name="sqr-number" select="number($result)"/&gt;</code></p>
    <p>переменные <code>sqr-string</code> и <code>sqr-number</code> будут содержать строковое и численное значение результата вычисления соответственно.</p>
    <p>Немного сложнее обстоит дело с булевым типом. При приведении дерева к булевому типу результатом всегда будет "истина", поэтому такое преобразование необходимо выполнить в два шага: сначала преобразовать дерево в число, только затем число в булевый тип.</p>
    <subtitle>Пример</subtitle>
    <p>В следующем преобразовании шаблон с именем <code>less-than</code> сравнивает значения параметров <code>x</code> и <code>y</code>. Переменной <code>less-than</code> присваивается булевое значение результата сравнения.</p>
    <subtitle>Листинг 11.7. Вычисление булевого значения функции</subtitle>
    <p><code>&lt;xsl:stylesheet</code></p>
    <p><code> version="1.0"</code></p>
    <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template match="/"&gt;</code></p>
    <p><code>  &lt;xsl:variable name="result"&gt;</code></p>
    <p><code>   &lt;xsl:call-template name="less-than"&gt;</code></p>
    <p><code>    &lt;xsl:with-param name="x" select="2"/&gt;</code></p>
    <p><code>    &lt;xsl:with-param name="y" select="1"/&gt;</code></p>
    <p><code>   &lt;/xsl:call-template&gt;</code></p>
    <p><code>  &lt;/xsl:variable&gt;</code></p>
    <p><code>  &lt;xsl:variable name="less-than" select="boolean(number($result))"/&gt;</code></p>
    <p><code>  &lt;xsl:value-of select="$less-than"/&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code> &lt;xsl:template name="less-than"&gt;</code></p>
    <p><code>  &lt;xsl:param name="x"/&gt;</code></p>
    <p><code>  &lt;xsl:param name="y"/&gt;</code></p>
    <p><code>  &lt;xsl:value-of select="number($x &amp;lt; $y)"/&gt;</code></p>
    <p><code> &lt;/xsl:template&gt;</code></p>
    <empty-line/>
    <p><code>&lt;/xsl:stylesheet&gt;</code></p>
    <subtitle>Пример</subtitle>
    <p>Простым примером шаблона-функции может быть шаблон, который форматирует дату в нужном виде, например 7 августа 93 года как "<code>07-Aug-1993</code>".</p>
    <p>В качестве параметров этот шаблон будет принимать численные значения дня, месяца и года. Год, имеющий значение меньшее 25, мы будем считать принадлежащим новому тысячелетию.</p>
    <subtitle>Листинг 11.8. Шаблон, форматирующий дату</subtitle>
    <p><code>&lt;xsl:template name="format-date"&gt;</code></p>
    <p><code> &lt;xsl:param name="day"/&gt;</code></p>
    <p><code> &lt;xsl:param name="month"/&gt;</code></p>
    <p><code> &lt;xsl:param name="year"/&gt;</code></p>
    <p><code> &lt;xsl:value-of select="format-number($day, '00')"/&gt;</code></p>
    <p><code> &lt;xsl:text&gt;-&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;xsl:choose&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 1"&gt;Jan&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 2"&gt;Feb&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 3"&gt;Mar&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 4"&gt;Apr&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 5"&gt;May&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 6"&gt;Jun&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 7"&gt;Jul&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 8"&gt;Aug&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when-test="$month = 9"&gt;Sen&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 10"&gt;Oct&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 11"&gt;Nov&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:when test="$month = 12"&gt;Dec&lt;/xsl:when&gt;</code></p>
    <p><code> &lt;/xsl:choose&gt;</code></p>
    <p><code> &lt;xsl:text&gt;-&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;xsl:choose&gt;</code></p>
    <p><code>  &lt;xsl:when test="$year &amp;lt;= 25"&gt;</code></p>
    <p><code>   &lt;xsl:value-of select="format-number($year +2000, '0000')"/&gt;</code></p>
    <p><code>  &lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:otherwise&gt;</code></p>
    <p><code>   &lt;xsl:value-of select="format-number($year, '0000')"/&gt;</code></p>
    <p><code>  &lt;/xsl:otherwise&gt;</code></p>
    <p><code> &lt;/xsl:choose&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
   </section>
   <section>
    <title>
     <p>Рекурсия</p>
    </title>
    <p>Отсутствие в XSLT <emphasis>изменяемых</emphasis> переменных (оценим красоту этой тавтологии) как, впрочем, и многое другое, делает этот язык совершенно непохожим на многие классические языки программирования. В этом разделе мы опишем рекурсию [Кормен и др. 2000, Кнут 2000] — чрезвычайно простую, но в то же время исключительно мощную технику, которая в большинстве случаев компенсирует нехватку в XSLT переменных и других процедурных конструкций.</p>
    <p>Не вдаваясь в строгие определения дискретной математики, можно сказать, что рекурсия это всего лишь описание объекта или вычисления в терминах самого себя. Пожалуй, самым простым примером рекурсии является факториал, функция, которая математически определяется как:</p>
    <p>0!=1</p>
    <p><emphasis>n</emphasis>!=<emphasis>n</emphasis>&#215;(<emphasis>n</emphasis>-1)!</p>
    <p>Программа на процедурном языке (например, таком, как Java), вычисляющая факториал совершенно тривиальна:</p>
    <p><code>int factorial(int n) {</code></p>
    <p><code> if (n == 0) return 1;</code></p>
    <p><code> else return n * factorial(n-1);</code></p>
    <p><code>}</code></p>
    <p>Попробуем запрограммировать факториал на XSLT. Мы уже научились создавать собственные функции (вернее, конструкции, похожие на них) с помощью одних только именованных шаблонов, значит написать функцию, которая бы вызывала сама себя, будет не так уж и сложно.</p>
    <subtitle>Листинг 11.9. Именованный шаблон, вычисляющий факториал</subtitle>
    <p><code>&lt;xsl:template name="factorial"&gt;</code></p>
    <p><code> &lt;xsl:param name="n"/&gt;</code></p>
    <p><code> &lt;xsl:choose&gt;</code></p>
    <p><code>  &lt;xsl:when test="$n=0"&gt;1&lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:otherwise&gt;</code></p>
    <p><code>   &lt;xsl:variable name="n-1"&gt;</code></p>
    <p><code>    &lt;xsl:call-template name="factorial"&gt;</code></p>
    <p><code>     &lt;xsl:with-param name="n" select="$n-1"/&gt;</code></p>
    <p><code>    &lt;/xsl:call-template&gt;</code></p>
    <p><code>   &lt;/xsl:variable&gt;</code></p>
    <p><code>   &lt;xsl:value-of select="$n * number($n-1)"/&gt;</code></p>
    <p><code>  &lt;/xsl:otherwise&gt;</code></p>
    <p><code> &lt;/xsl:choose&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Вызвав этот шаблон с параметром <code>n</code> равным <code>6</code> следующим образом:</p>
    <p><code>&lt;xsl:call-template name="factorial"&gt;</code></p>
    <p><code> &lt;xsl:with-param name="n" select="number(6)"/&gt;</code></p>
    <p><code>&lt;/xsl:call-template&gt;</code></p>
    <p>мы получим текстовый узел, значение которого будет равно "<code>720</code>".</p>
    <p>Очевидным требованием к рекурсивным функциям является возможность выхода из рекурсии. Если бы в определении факториала не было указано, что 0!=1, вычисления так бы и продолжались без конца.</p>
    <p>Главным минусом рекурсии является требовательность к ресурсам. Каждый раз, при вызове именованного шаблона, процессор должен будет каким-то образом сохранять в памяти передаваемые ему формальные параметры. Например, если мы попробуем сосчитать факториал от 170, процессору понадобится держать в памяти сразу 170 чисел. Безусловно, в случае с факториалом это не является большой проблемой — точность 64-битных чисел исчерпается гораздо раньше, чем закончится память, но в случае хранения в переменных действительно больших объемов информации (например, частей деревьев) такая угроза существует. Кроме того, рекурсивные решения, как правило, работают медленнее, чем решения, не использующие рекурсию.</p>
    <p>Так в чем же смысл использования рекурсии? Дело в том, что вследствие определенных ограничений (связанных, в частности с неизменяемыми переменными) в XSLT существуют задачи, которые не могут быть реализованы иначе кроме как через рекурсию. Самым характерным примером такой задачи являются циклы.</p>
   </section>
   <section>
    <title>
     <p>Циклы</p>
    </title>
    <section>
     <p>Цикл в общем смысле слова это повторение одних и тех же действий несколько раз. Если говорить об XSLT, то цикл это многократное выполнение одного и того же шаблона. Для подавляющего большинства случаев в преобразованиях достаточно бывает использовать такие элементы, как <code>xsl:apply-templates</code> и <code>xsl:for-each</code>, которые заставляют процессор выполнять одни и те же действия несколько раз в контексте каждого из узлов определенного множества.</p>
     <p>Весомым ограничением такого рода циклической обработки является невозможность генерировать множества узлов. В текущей версии языка никакой другой тип не может быть приведен ко множеству узлов, значит, в любое из них могут входить только те узлы, которые изначально присутствуют в одном из обрабатываемых документов. Это означает, что ни <code>xsl:apply-templates</code>, ни <code>xsl:for-each</code> не могут быть использованы для того, чтобы реализовать простые <code>while</code>- или <code>for</code>-циклы для <emphasis>произвольных</emphasis> множеств.</p>
    </section>
    <section>
     <title>
      <p>Цикл <emphasis>while</emphasis></p>
     </title>
     <p>Наиболее примитивной циклической конструкцией во многих языках программирования является цикл <code>while</code> (англ. пока). Цикл <code>while</code>, как правило, имеет следующий вид:</p>
     <p><code>пока</code></p>
     <p><code> верно <emphasis>условие</emphasis></code></p>
     <p><code>выполнять</code></p>
     <p><code> <emphasis>действия</emphasis></code></p>
     <p>В качестве примера <code>while</code>-цикла напишем на языке Java программу вычисления факториала в итеративном стиле:</p>
     <p><code>int factorial(int n) {</code></p>
     <p><code> int i = n;</code></p>
     <p><code> int result = 1;</code></p>
     <p><code> while (i != 0) {</code></p>
     <p><code>  result = result * i;</code></p>
     <p><code>  i--;</code></p>
     <p><code> }</code></p>
     <p><code> return result;</code></p>
     <p><code>}</code></p>
     <p>В этой функции <code><emphasis>условием</emphasis></code> является отличие значения переменной <code>i</code> от 0, а действиями — умножение значения переменной <code>result</code> на значение переменной <code>i</code>, и уменьшение значения этой переменной на 1.</p>
     <p>Цикл <code>while</code> не может быть запрограммирован в XSLT итеративно потому как действия, как правило, изменяют значения переменных, в контексте которых вычисляется условие, определяющее, продолжать выполнение цикла или нет. Дадим другую общую запись цикла <code>while</code>, выделив изменение переменных:</p>
     <p><code>пока</code></p>
     <p><code> верно <emphasis>условие</emphasis>(x<sub>1</sub>,x<sub>2</sub>, ...,x<sub>n</sub>)</code></p>
     <p><code>выполнить</code></p>
     <p><code> x<sub>1</sub>' := <emphasis>функция</emphasis><sub>1</sub>(x<sub>1</sub>,x<sub>2</sub>,...,x<sub>n</sub>)</code></p>
     <p><code> х<sub>2</sub>' := <emphasis>функция</emphasis><sub>2</sub>(x<sub>1</sub>,x<sub>2</sub>,...,x<sub>n</sub>)</code></p>
     <p><code> ...</code></p>
     <p><code> x<sub>n</sub>' := <emphasis>функция</emphasis><sub>n</sub>(x<sub>1</sub>,x<sub>2</sub>,...,x<sub>n</sub>)</code></p>
     <p><code><emphasis> действия</emphasis>(x<sub>1</sub>,x<sub>2</sub>,...,х<sub>n</sub>)</code></p>
     <p><code> x<sub>1</sub> := x<sub>1</sub>'</code></p>
     <p><code> x2 := x<sub>2</sub>'</code></p>
     <p><code> ...</code></p>
     <p><code> x<sub>n</sub> := x<sub>n</sub>'</code></p>
     <p><code>иначе</code></p>
     <p><code> вернуть <emphasis>результат</emphasis>(x<sub>1</sub>,...,х<sub>n</sub>)</code></p>
     <p>Переопределение значений переменных <code>x</code><sub>1</sub>, … , <code>х</code><sub>n</sub> в этом случае выполняют <code>n</code> функций: <code><emphasis>функция</emphasis></code><sub>1</sub> …, <code><emphasis>функция</emphasis></code><sub>n</sub>. И если изменить значение переменной мы не могли, переопределить связанное с ней значение мы вполне в состоянии, добавив в контекст новый параметр или переменную с тем же именем.</p>
     <p>Теперь мы можем записать весь цикл <code>while</code> как одну рекурсию:</p>
     <p><code>while(x<sub>1</sub>, ..., x<sub>n</sub>) ::=</code></p>
     <p><code> если</code></p>
     <p><code>  выполняется <emphasis>условие</emphasis>(x<sub>1</sub>, ..., x<sub>n</sub>)</code></p>
     <p><code> то</code></p>
     <p><code><emphasis>  действия</emphasis>(x<sub>1</sub>, ..., х<sub>n</sub>)</code></p>
     <p><code>  while(<emphasis>функция</emphasis><sub>1</sub>(x<sub>1</sub>, ..., х<sub>n</sub>),</code></p>
     <p><code><emphasis>   функция</emphasis><sub>2</sub>(x<sub>1</sub>, ..., х<sub>n</sub>),</code></p>
     <p><code>   ...,</code></p>
     <p><code><emphasis>   функция</emphasis><sub>n</sub>(x<sub>1</sub>, ..., x<sub>n</sub>))</code></p>
     <p><code> иначе</code></p>
     <p><code><emphasis>  результат</emphasis>(x<sub>1</sub>, ..., х<sub>n</sub>)</code></p>
     <p>Теперь уже совершенно очевидно, как <code>while</code>-цикл должен выглядеть в преобразовании.</p>
     <subtitle>Листинг 11.10. Шаблон цикла while в общем виде</subtitle>
     <p><code>&lt;xsl:template name="while"&gt;</code></p>
     <p><code> &lt;xsl:param name="x1"/&gt;</code></p>
     <p><code> &lt;!-- ... --&gt; </code></p>
     <p><code> &lt;xsl:param name="xn"/&gt;</code></p>
     <p><code> &lt;xsl:choose&gt;</code></p>
     <p><code>  &lt;xsl:when test="условие($x1,...,$xn)"&gt;</code></p>
     <p><code>   &lt;!-- Действия --&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="while"&gt;</code></p>
     <p><code>    &lt;xsl:with-param name="x1" select="функция_1($x1, ... $xn) "/&gt;</code></p>
     <p><code>    &lt;!-- ... --&gt;</code></p>
     <p><code>    &lt;xsl:with-param name="xn" select="функция_n($x1, ... $xn) "/&gt;</code></p>
     <p><code>   &lt;/xsl:call-template&gt;</code></p>
     <p><code>  &lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:otherwise&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="результат($x1, ..., $xn)"/&gt;</code></p>
     <p><code>  &lt;/xsl:otherwise&gt;</code></p>
     <p><code> &lt;/xsl:choose&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>В качестве примера приведем <code>while</code>-цикл для программы, вычисляющей факториал. Java-код был следующим:</p>
     <p><code>while (i != 0) {</code></p>
     <p><code> result = result * i;</code></p>
     <p><code> i--;</code></p>
     <p><code>}</code></p>
     <p>В этом цикле участвуют две переменные — <code>i</code> и <code>result</code>. Функции, использующиеся в этом цикле, запишутся следующим образом:</p>
     <p><code><emphasis>условие</emphasis>($1, $result)      ::= ($i != 0)</code></p>
     <p><code><emphasis>функция</emphasis><sub>i</sub>($i, $result)     ::= ($i - 1)</code></p>
     <p><code><emphasis>функция</emphasis><sub>result</sub>($i, $result) ::= ($i * $result)</code></p>
     <p><code><emphasis>результат</emphasis>($I, $result)    ::= ($result)</code></p>
     <p>Именованный шаблон для этого случая будет иметь вид.</p>
     <subtitle>Листинг 11.11. Пример шаблона цикла while</subtitle>
     <p><code>&lt;xsl:template name="while"&gt;</code></p>
     <p><code> &lt;xsl:param name="i"/&gt;</code></p>
     <p><code> &lt;xsl:param name="result"/&gt;</code></p>
     <p><code> &lt;xsl:choose&gt;</code></p>
     <p><code>  &lt;xsl:when test="$i != 0"&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="while"&gt;</code></p>
     <p><code>    &lt;xsl:with-param name="i" select="$i — 1"/&gt;</code></p>
     <p><code>    &lt;xsl:with-param name="result" select="$result * $i"/&gt;</code></p>
     <p><code>   &lt;/xsl:call-template&gt;</code></p>
     <p><code>  &lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:otherwise&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="$result"/&gt;</code></p>
     <p><code>  &lt;/xsl:otherwise&gt;</code></p>
     <p><code> &lt;/xsl:choose&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Вызвать этот шаблон можно следующим образом:</p>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;xsl:call-template name="while"&gt;</code></p>
     <p><code>  &lt;xsl:with-param name="i" select="6"/&gt;</code></p>
     <p><code>  &lt;xsl:with-param name="result" select="1"/&gt;</code></p>
     <p><code> &lt;/xsl:call-template&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>Результатом будет, естественно, число <code>720</code>.</p>
    </section>
    <section>
     <title>
      <p>Цикл <emphasis>for</emphasis></p>
     </title>
     <p>Частным случаем цикла <code>while</code> является цикл <code>for</code>. В разных языках программирования <code>for</code> имеет различную семантику; мы будем рассматривать циклы <code>for</code> вида</p>
     <p><code>for (int i = 0; i &lt; n; i++) { ... }</code></p>
     <p>в языках Java и С или</p>
     <p><code>for i := 0 to n-1 do begin ... end;</code></p>
     <p>в Pascal. Иными словами, нас будет интересовать циклическое выполнение определенных действий при изменении значения некоторой переменной (называемой иногда индексом цикла) в интервале целых чисел от 0 до n включительно.</p>
     <p>Цикл <code>for</code> может быть определен через <code>while</code> с использованием следующих условных и изменяющих функций:</p>
     <p><code><emphasis>условие</emphasis>($i, $n,$x1,...,$хk)      :: = ($i &lt; $n)</code></p>
     <p><code><emphasis>функция</emphasis><sub>i</sub>($i, $n, $x1, ... , $xk) ::= ($i + 1)</code></p>
     <p><code><emphasis>функция</emphasis><sub>n</sub>($i, $n, $x1, ..., $xk)  :: = ($n)</code></p>
     <p>Шаблон цикла <code>for</code> в общем виде будет выглядеть как.</p>
     <subtitle>Листинг 11.12. Шаблон цикла for в общем виде</subtitle>
     <p><code>&lt;xsl:template name="for"&gt;</code></p>
     <p><code> &lt;xsl:param name="i" select="0"/&gt;</code></p>
     <p><code> &lt;xsl:param name="n"/&gt;</code></p>
     <p><code> &lt;!-- Другие переменные --&gt;</code></p>
     <p><code> &lt;xsl:param name="x1"/&gt;</code></p>
     <p><code> &lt;!-- ... --&gt;</code></p>
     <p><code> &lt;xsl:param name="xk"/&gt;</code></p>
     <p><code> &lt;xsl:choose&gt;</code></p>
     <p><code>  &lt;xsl:when test="$i &amp;lt; $n"&gt;</code></p>
     <p><code>   &lt;!-- Действия --&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="for"&gt;</code></p>
     <p><code>    &lt;xsl:with-param name="i" select="$i + 1"/&gt;</code></p>
     <p><code>    &lt;xsl:with-param name="n" select="$n"/&gt;</code></p>
     <p><code>    &lt;!-- Другие переменные --&gt;</code></p>
     <p><code>    &lt;xsl:with-param" name="x1" select <emphasis>функция</emphasis><sub>1</sub>($i, $n, $x1, ..., $xk) "/&gt;</code></p>
     <p><code>    &lt;!-- ... --&gt;</code></p>
     <p><code>    &lt;xsl:with-param name="xk" select="<emphasis>функция</emphasis><sub>k</sub>($i, $n, $x1, ..., $xk)"/&gt;</code></p>
     <p><code>   &lt;/xsl:call-template&gt;</code></p>
     <p><code>  &lt;/xsl:when&gt;</code></p>
     <p><code>  &lt;xsl:otherwise&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="<emphasis>результат</emphasis>($i,$n,$x1,...,$xk)"/&gt;</code></p>
     <p><code>  &lt;/xsl:otherwise&gt;</code></p>
     <p><code> &lt;/xsl:choose&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>В качестве примера цикла <code>for</code> приведем шаблон, вычисляющий <code>n</code> первых чисел Фибоначчи.</p>
     <p>Числа Фибоначчи — это рекуррентная последовательность вида</p>
     <p><code>1 1 2 3 5 8 13 21 ...</code></p>
     <p>и так далее, где каждое последующее число определяется как сумма двух предыдущих.</p>
     <p>Для вычисления <code>n</code> первых чисел Фибоначчи мы можем использовать две переменные <code>current</code> и <code>last</code>, соответствующих текущему число и числу, полученному на предыдущем шаге соответственно. Функции, переопределяющие эти переменные, совершенно очевидны:</p>
     <p><code><emphasis>функция</emphasis><sub>last</sub>($i, $n, $last, $current)   ::= ($current)</code></p>
     <p><code><emphasis>функция</emphasis><sub>current</sub>($i, $n, $last, $current) ::= ($current + $last)</code></p>
     <p>Поскольку в данном случае нам не нужно возвращать результат, нужно лишь циклически выводить очередное число Фибоначчи, шаблон <code>for</code> может быть немного упрощен использованием элемента <code>xsl:if</code> вместо <code>xsl:choose</code>.</p>
     <subtitle>Листинг 11.13. Шаблон, вычисляющий числа Фибоначчи</subtitle>
     <p><code>&lt;xsl:template name="for"&gt;</code></p>
     <p><code> &lt;xsl:param name="i" select="0"/&gt;</code></p>
     <p><code> &lt;xsl:param name="n"/&gt;</code></p>
     <p><code> &lt;xsl:param name="last" select="0"/&gt;</code></p>
     <p><code> &lt;xsl:param name="current" select="1"/&gt;</code></p>
     <p><code> &lt;xsl:if test="$i &amp;lt; $n"&gt;</code></p>
     <p><code>  &lt;xsl:text&gt; &lt;/xsl:text&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="$current"/&gt;</code></p>
     <p><code>  &lt;xsl:call-template name="for"&gt;</code></p>
     <p><code>   &lt;xsl:with-param name="i" select="$i + 1"/&gt;</code></p>
     <p><code>   &lt;xsl:with-param name="n" select="$n"/&gt;</code></p>
     <p><code>   &lt;xsl:with-param name="last" select="$current"/&gt;</code></p>
     <p><code>   &lt;xsl:with-param name="current" select="$last + $current"/&gt;</code></p>
     <p><code>  &lt;/xsl:call-template&gt;</code></p>
     <p><code> &lt;/xsl:if&gt; </code></p>
     <p><code>/xsl:template&gt;</code></p>
     <p>Вызванный в основном шаблоне как:</p>
     <p><code>&lt;xsl:template match="/"&gt;</code></p>
     <p><code> &lt;xsl:call-template name="for"&gt;</code></p>
     <p><code>  &lt;xsl:with-param name="n" select="6"/&gt;</code></p>
     <p><code> &lt;/xsl:call-template&gt;</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>этот шаблон создаст в выходящем документе последовательность:</p>
     <p><code>1 1 2 3 5 8</code></p>
     <p>Приведем еще более простой пример, в котором элемент <code>option</code> выводится заданное число раз.</p>
     <subtitle>Листинг 11.14. Вывод 10 элементов option</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform'"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:call-template name="for"&gt;</code></p>
     <p><code>   &lt;xsl:with-param name="n" select="10"/&gt;</code></p>
     <p><code>  &lt;/xsl:call-template&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template name="for"&gt;</code></p>
     <p><code>  &lt;xsl:param name="i" select="0"/&gt;</code></p>
     <p><code>  &lt;xsl:param name="n"/&gt;</code></p>
     <p><code>  &lt;xsl:if test="$i &amp;lt; $n"&gt;</code></p>
     <p><code>   &lt;option&gt;</code></p>
     <p><code>    &lt;xsl:value-of select="$i"/&gt;</code></p>
     <p><code>   &lt;/option&gt;</code></p>
     <p><code>   &lt;xsl:call-template name="for"&gt;</code></p>
     <p><code>    &lt;xsl:with-param name="i" select="$i + 1"/&gt;</code></p>
     <p><code>    &lt;xsl:with-param name="n" select="$n"/&gt;</code></p>
     <p><code>   &lt;/xsl:call-template&gt;</code></p>
     <p><code>  &lt;/xsl:if&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг 11.15 Выходящий документ</subtitle>
     <p><code>&lt;option&gt;0&lt;/option&gt;</code></p>
     <p><code>&lt;option&gt;1&lt;/option&gt;</code></p>
     <p><code>&lt;option&gt;2&lt;/option&gt;</code></p>
     <p><code>&lt;option&gt;3&lt;/option&gt;</code></p>
     <p><code>&lt;option&gt;4&lt;/option&gt;</code></p>
     <p><code>&lt;option&gt;5&lt;/option&gt;</code></p>
     <p><code>&lt;option&gt;6&lt;/option&gt;</code></p>
     <p><code>&lt;option&gt;7&lt;/option&gt;</code></p>
     <p><code>&lt;option&gt;8&lt;/option&gt;</code></p>
     <p><code>&lt;option&gt;9&lt;/option&gt;</code></p>
     <p>Пожалуй, этим примером мы и закончим рассмотрение рекурсии. Осталось лишь добавить, что при всей своей простоте и вычислительной мощи, рекурсия является гораздо более требовательной к ресурсам техникой программирования, чем обычная итеративная обработка. Поэтому всегда следует тщательно оценивать, во что может вылиться использование рекурсии. В любом случае следует избегать глубоких рекурсий (функций, количество рекурсивных вызовов в которых может быть большим) и рекурсий, неэкономно использующих память.</p>
     <p>Кроме того, большинство действий, выполнение которых в XSLT затруднено, в классических языках программирования выполняется, как правило, намного легче и эффективней. Поэтому, каждый раз, когда стоит вопрос об использовании рекурсии, наряду с ней следует рассматривать такую альтернативу, как использование расширений XSLT, написанных на обычном императивном языке.</p>
    </section>
    <section>
     <title>
      <p>Метод Пиза для for-цикла</p>
     </title>
     <p>Для простых <code>for</code>-циклов, которые должны выполниться строго определенное число раз, вместо рекурсии можно использовать весьма остроумный метод, предложенный Венделлом Пизом (Wendell Piez, Mullberry Technologies, Inc). Суть метода состоит в том, что хоть мы и не можем сгенерировать множество узлов, выбрать множество с определенным количеством узлов нам вполне по силам.</p>
     <p>Для начала выберем какое-нибудь множество узлов документа преобразования:</p>
     <p><code>&lt;xsl:variable name="set" select="document('')//node()"/&gt;</code></p>
     <p>Затем для повторения определенных действий несколько раз используем конструкцию вида</p>
     <p><code>&lt;xsl:for-each select="$set[position() &amp;lt;= $number]"&gt;</code></p>
     <p><code> &lt;!-- Действия --&gt;</code></p>
     <p><code>&lt;/xsl:for-each&gt;</code></p>
     <p>где <code>number</code> указывает требуемое число итераций.</p>
     <p>При использовании метода Пиза следует учитывать следующие особенности.</p>
     <p>&#9633; Множество узлов <code>set</code> не должно быть слишком большим — иначе его выбор будет неэффективным. </p>
     <p>&#9633; Множество узлов <code>set</code> обязательно должно содержать число итераций (<code>number</code>) узлов.</p>
     <p>В целом же метод Пиза — классический пример эффективного применения инструментов не по назначению.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Операции над множествами</p>
    </title>
    <p>Рассматривая такой тип данных, как множества узлов, мы отмечали ограниченность операций, которые можно с ними производить. В частности, XSLT не предоставляет стандартных операторов для определения принадлежности одного множества другому, нахождения пересечений, разности множеств и так далее. Возможности, которые были представлены при описании этого типа данных, основанные на использовании оператора равенства, на самом деле реализуют далеко не математические операции над множествами.</p>
    <p>В этом разделе мы рассмотрим иной подход к реализации операций над множествами, основанный на очень простом определении принадлежности узла множеству. Узел <code>node</code> принадлежит множеству <code>nodeset</code> тогда и только тогда, когда выполняется равенство</p>
    <p><code>count($nodeset) = count($node | $nodeset)</code></p>
    <p>Учитывая это обстоятельство, операции над множествами можно представить, как показано в табл. 11.1. Результирующее множество выделено штриховкой.</p>
    <empty-line/>
    <p><emphasis><strong>Таблица 11.1</strong>. Операции над множествами</emphasis></p>
    <table>
     <tr>
      <th align="left">Операция</th>
      <th align="left">Графическое представление</th>
      <th align="left">XPath-выражение</th>
     </tr>
     <tr>
      <td align="left">Объединение</td>
      <td align="left"><image l:href="#img_86.png"/></td>
      <td align="left"><code>$A | $B</code></td>
     </tr>
     <tr>
      <td align="left">Пересечение</td>
      <td align="left"><image l:href="#img_87.png"/></td>
      <td align="left"><code>$А[count(.|$B)=count($B)]</code></td>
     </tr>
     <tr>
      <td align="left">Разность</td>
      <td align="left"><image l:href="#img_88.png"/></td>
      <td align="left"><code>$A[count(.|$B)!=count($B)]</code></td>
     </tr>
     <tr>
      <td align="left">Симметрическая разность</td>
      <td align="left"><image l:href="#img_89.png"/></td>
      <td align="left"><code>$A[count(.|$B)!=count($B)] | $B[count(.|$A)!=count($A)]</code></td>
     </tr>
    </table>
    <p>Приведенные выше методы были разработаны Майклом Кеем (Michael Kay, Software AG), Оливером Беккером (Oliver Becker, Humboldt-Universitat zu Berlin), Кеном Холманом (Ken Holman, Crane Softwrights Ltd.) и публикуются с любезного разрешения авторов.</p>
   </section>
   <section>
    <title>
     <p>Перенос строк и элементы<emphasis> BR</emphasis></p>
    </title>
    <p>Большинству читателей, скорее всего, хорошо знаком такой элемент языка HTML, как <code>BR</code>, который используется для обозначения разрыва строки. В обычных текстовых файлах для той же самой цели используются символы с кодами <code>#xA</code>, <code>#xD</code> или их комбинации в зависимости от платформы. При совместном использовании неразмеченного текста и HTML часто возникает задача преобразования символов перевода строки в элементы <code>BR</code> и наоборот.</p>
    <p>Замену элемента <code>BR</code> на текстовый узел, содержащий перевод строки, можно проиллюстрировать следующим тривиальным шаблоном.</p>
    <subtitle>Листинг 11.16. Шаблон замены элементов BR на перенос строки</subtitle>
    <p><code>&lt;xsl:template match="BR"&gt;</code></p>
    <p><code> &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Гораздо сложнее написать шаблон, делающий обратную операцию, — замену символов переноса строки на элементы BR. В XSLT нет встроенного механизма для замены подстроки в строке (тем более на элемент), поэтому нам придется создать для этой цели собственный шаблон.</p>
    <p>Для этой цели мы можем воспользоваться функциями <code>substring-before</code> и <code>substring-after</code>. Функция <code>substring-before($str, $search-for)</code> возвратит часть строки <code>str</code>, которая предшествует первому вхождению в нее подстроки <code>search-for</code>, а функция <code>substring-after($str, $search-for)</code> — последующую часть. То есть заменить <emphasis>первое</emphasis> вхождение можно шаблоном вида</p>
    <p><code>&lt;!-- ... --&gt;</code></p>
    <p><code>&lt;xsl:value-of select = "substring-before($str, $search-for)"/&gt;</code></p>
    <p><code>&lt;xsl:copy-of select = "$replace-with"/&gt;</code></p>
    <p><code>&lt;xsl:value-of select = "substring-after($str, $search-for)"/&gt;</code></p>
    <p><code>&lt;!-- ... --&gt;</code></p>
    <p>Для того же, чтобы заменить <emphasis>все</emphasis> вхождения, достаточно рекурсивно повторить операцию замены первого вхождения с той частью строки, которая следует за ним. Приведем шаблон, который выполняет эту операцию.</p>
    <subtitle>Листинг 11.17. Шаблон для замены подстроки в строке</subtitle>
    <p><code>&lt;xsl:template name="replace" match="text()" mode="replace"&gt;</code></p>
    <p><code> &lt;xsl:param name="str" select="."/&gt;</code></p>
    <p><code> &lt;xsl:param name="search-for" select="'&amp;#xA;'"/&gt;</code></p>
    <p><code> &lt;xsl:param name="replace-with"&gt;</code></p>
    <p><code>  &lt;xsl:element name="BR"/&gt;</code></p>
    <p><code>  &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;</code></p>
    <p><code> &lt;/xsl:param&gt;</code></p>
    <p><code> &lt;xsl:choose&gt;</code></p>
    <p><code>  &lt;xsl:when test="contains($str, $search-for)"&gt;</code></p>
    <p><code>   &lt;xsl:value-of select="substring-before($str, $search-for)"/&gt;</code></p>
    <p><code>   &lt;xsl:copy-of select="$replace-with"/&gt;</code></p>
    <p><code>   &lt;xsl:call-template name="replace"&gt;</code></p>
    <p><code>    &lt;xsl:with-param name="str"</code></p>
    <p><code>     select="substring-after($str, $search-for)"/&gt;</code></p>
    <p><code>    &lt;xsl:with-param name="search-for" select="$search-for"/&gt;</code></p>
    <p><code>    &lt;xsl:with-param name="replace-with " select="$replace-with"/&gt;</code></p>
    <p><code>   &lt;/xsl:call-template&gt;</code></p>
    <p><code>  &lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:otherwise&gt;</code></p>
    <p><code>   &lt;xsl:value-of select="$str"/&gt;</code></p>
    <p><code>  &lt;/xsl:otherwise&gt;</code></p>
    <p><code> &lt;/xsl:choose&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Шаблон, приведенный в этом листинге, может быть вызван двумя способами: элементом <code>xsl:apply-templates</code> в режиме <code>replace</code> (в этом случае он будет обрабатывать текстовые узлы выбранного множества), или при помощи именного вызова элементом <code>xsl:call-template</code>. Шаблон принимает на вход три параметра.</p>
    <p>&#9633; Параметр <code>str</code>, содержащий строку, в которой нужно произвести замену. По умолчанию этому параметру присваивается текстовое значение текущего узла.</p>
    <p>&#9633; Параметр <code>search-for</code>, содержащий подстроку, которую требуется найти и заменить в строке <code>str</code>. По умолчанию замене будут подлежать символы переноса строки, "<code>&amp;#хА;</code>".</p>
    <p>&#9633; Параметр <code>replace-with</code>, содержащий объект, на который следует заменять подстроки <code>search-for</code>. По умолчанию эти подстроки будут заменяться на элемент <code>BR</code> и следующий за ним перенос строки, добавленный для лучшей читаемости.</p>
    <p>В качестве примера отформатируем содержание следующего элемента:</p>
    <p><code>&lt;pre&gt;One little rabbit</code></p>
    <p><code>Two little rabbits</code></p>
    <p><code>Three little rabbits&lt;/pre&gt;</code></p>
    <p>Запишем шаблон для обработки элемента <code>pre</code>:</p>
    <p><code>&lt;xsl:template match="pre"&gt;</code></p>
    <p><code> &lt;xsl:copy&gt;</code></p>
    <p><code>  &lt;xsl:apply-templates mode="replace"/&gt;</code></p>
    <p><code> &lt;/xsl:copy&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Результат его выполнения будет иметь следующий вид:</p>
    <p><code>&lt;pre&gt;One little rabbit&lt;BR/&gt;</code></p>
    <p><code>Two little rabbits&lt;BR/&gt;</code></p>
    <p><code>Three little rabbits&lt;/pre&gt;</code></p>
   </section>
   <section>
    <title>
     <p>Данные, разделенные запятыми (CSV)</p>
    </title>
    <p>Рекурсивную методику замены, которую мы представили выше, можно использовать для того, чтобы разметить данные, разделенные запятыми (или CSV, comma-separated values). CSV — это старый простой формат представления данных, в котором они просто перечисляются через запятую, например:</p>
    <p><code>a, b, с, d, e, f, g</code></p>
    <p>и так далее. Формат CSV был одним из первых шагов к созданию языков разметки: данные в нем <emphasis>уже</emphasis> размечались запятыми.</p>
    <p>Покажем на простом примере, как можно преобразовать CSV-данные в XML-документ. Пусть входящий документ выглядит как:</p>
    <p><code>&lt;data&gt;a, b, с, d, e, f&lt;/data&gt;</code></p>
    <p>Для того чтобы решение было как можно более общим, вынесем создание XML-разметки для каждого из элементов этой последовательности в отдельный шаблон:</p>
    <p><code>&lt;xsl:template name="item"&gt;</code></p>
    <p><code> &lt;xsl:param name="item"/&gt;</code></p>
    <p><code> &lt;item&gt;&lt;xsl:copy-of select="$item"/&gt;&lt;/item&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Тогда головной размечающий шаблон запишется в виде.</p>
    <subtitle>Листинг 11.18. Шаблон, размечающий данные в строковом формате</subtitle>
    <p><code>&lt;xsl:template name="markup" match="text()" mode="CSV"&gt;</code></p>
    <p><code> &lt;xsl:param name="str" select="."/&gt;</code></p>
    <p><code> &lt;xsl:param name="delimiter" select="','"/&gt;</code></p>
    <p><code> &lt;xsl:choose&gt;</code></p>
    <p><code>  &lt;xsl:when test="contains($str,$delimiter)"&gt;</code></p>
    <p><code>   &lt;xsl:call-template name="item"&gt;</code></p>
    <p><code>    &lt;xsl:with-param name="item"</code></p>
    <p><code>     select="substring-before($str, $delimiter)"/&gt;</code></p>
    <p><code>   &lt;/xsl:call-template&gt;</code></p>
    <p><code>   &lt;xsl:call-template name="markup"&gt;</code></p>
    <p><code>    &lt;xsl:with-param name="str"</code></p>
    <p><code>     select="substring-after($str, $delimiter)"/&gt;</code></p>
    <p><code>   &lt;/xsl:call-template&gt;</code></p>
    <p><code>   &lt;xsl:with-param name="delimiter" select="$delimiter"/&gt;</code></p>
    <p><code>  &lt;/xsl:when&gt;</code></p>
    <p><code>  &lt;xsl:otherwise&gt;</code></p>
    <p><code>   &lt;xsl:call-template name="item"&gt;</code></p>
    <p><code>    &lt;xsl:with-param name="item" select="$str"/&gt;</code></p>
    <p><code>   &lt;/xsl:call-template&gt;</code></p>
    <p><code>  &lt;/xsl:otherwise&gt;</code></p>
    <p><code> &lt;/xsl:choose&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>На вход шаблон markup принимает два параметра — <code>str</code>, строка, которую нужно разметить (по умолчанию — значение текущего узла) и <code>delimiter</code> — строка, разделяющая отдельные значения в <code>str</code> (по умолчанию — запятая "<code>,</code>").</p>
    <p>Шаблон, форматирующий содержимое элемента <code>data</code>, будет в таком случае выглядеть следующим образом:</p>
    <p><code>&lt;xsl:template match="data"&gt;</code></p>
    <p><code> &lt;xsl:copy&gt;</code></p>
    <p><code>  &lt;xsl:apply-templates mode="CSV"/&gt;</code></p>
    <p><code> &lt;/xsl:copy&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Результат этого преобразования будет иметь следующий вид:</p>
    <p><code>&lt;data&gt;</code></p>
    <p><code> &lt;item&gt;a&lt;/item&gt;</code></p>
    <p><code> &lt;item&gt; b&lt;/item&gt;</code></p>
    <p><code> &lt;item&gt; c&lt;/item&gt;</code></p>
    <p><code> &lt;item&gt; d&lt;/item&gt;</code></p>
    <p><code> &lt;item&gt; e&lt;/item&gt;</code></p>
    <p><code> &lt;item&gt; f&lt;/item&gt;</code></p>
    <p><code>&lt;/data&gt;</code></p>
    <p>Обратим внимание на то, что в элементах <code>item</code> присутствуют лишние пробелы, которые в начальной последовательности шли за запятыми. Избавиться от них можно, указав в качестве разделяющей строки символ "<code>, </code>":</p>
    <p><code>&lt;xsl:template match="data"&gt;</code></p>
    <p><code> &lt;xsl:copy&gt;</code></p>
    <p><code>  &lt;xsl:apply-templates mode="CSV"&gt;</code></p>
    <p><code>   &lt;xsl:with-param name="delimiter" select="', '"/&gt;</code></p>
    <p><code>  &lt;/xsl:apply-templates&gt;</code></p>
    <p><code> &lt;/xsl:copy&gt;</code></p>
    <p><code>&lt;/xsl:template&gt;</code></p>
    <p>Результатом, как и следовало ожидать, будет:</p>
    <p><code>&lt;data&gt;</code></p>
    <p><code> &lt;item&gt;a&lt;/item&gt;</code></p>
    <p><code> &lt;item&gt;b&lt;/item&gt;</code></p>
    <p><code> &lt;item&gt;c&lt;/item&gt;</code></p>
    <p><code> &lt;item&gt;d&lt;/item&gt;</code></p>
    <p><code> &lt;item&gt;e&lt;/item&gt;</code></p>
    <p><code> &lt;item&gt;f&lt;/item&gt;</code></p>
    <p><code>&lt;/data&gt;</code></p>
    <p>Кстати сказать, того же эффекта можно было добиться, изменив шаблон <code>item</code>, который отвечает за XML-представление каждого из элементов последовательности.</p>
   </section>
  </section>
  <section>
   <title>
    <p>Глава 12</p>
    <p>Развитие технологий</p>
   </title>
   <section>
    <p>Как известно, успех технологии зависит не только от того, насколько продумана и проработана она была. Ее широкое распространение невозможно без поддержки и заинтересованности ведущих производителей программного обеспечения. В этом смысле XSLT очень повезло: имплементациями языка с самых ранних черновых вариантов занимались такие крупные разработчики, как Microsoft, Oracle, IBM, Adobe, Lotus и многие другие. Поддержка Apache XML Project помогла XSLT завоевать популярность и среди open-source сообщества (open-source — разработки с "открытым" исходным кодом).</p>
    <p>Так или иначе, сейчас следует лишь констатировать стабильный рост популярности XSLT. Количество XSLT-процессоров уже исчисляется десятками, а число разработчиков — пожалуй, что и тысячами.</p>
    <p>Повышенный интерес помог в чрезвычайно короткий срок (менее года) изучить на практике недостатки и достоинства нового языка и приступить к разработке последующих версий, которые бы учитывали эти практические результаты. В декабре 2000 года была выпущена версия 1.1,. в которой было не только исправлено большинство основных проблем первой версии XSLT, но и включены очень важные дополнения — такие, например, как определение интерфейсов расширений для языков Java и JavaScript/ECMAScript. В августе 2001 года версии 1.1 дали статус Final Draft и положили на полку — она никогда не будет стандартом (технической рекомендацией Консорциума W3).</p>
    <p>Нужно сказать, что по количеству доработок и дополнений версия XSLT 1.1 могла вполне претендовать на роль нового стандарта XSLT. Однако, в такой напряженной области информационных технологий, как XML, приходится считаться с другими разработками, ибо все они взаимосвязаны. На решение прекратить продвижение XSLT 1.1 и перейти к 2.0 во многом повлияли такие проекты, как XML Schema и XQuery.</p>
    <p>XML Schema — это долгожданный XML-язык, описывающий структуру XML-документа, своего рода более мощный вариант DTD. XML Schema, в частности, позволяет описывать простые и сложные типы данных элементов и атрибутов, ограничивать количества повторений, определять в XML-документах первичные и внешние ключи и многое другое. Помимо этого, XML Schema определяется в XML-синтаксисе, что позволяет использовать для обработки схем стандартные XML-инструменты. Спецификация XML Schema получила статус технической рекомендации Консорциума W3 в мае 2001 года.</p>
    <p>XQuery — это текущий проект W3C по созданию языка запросов для XML-документов. В основу XQuery легло множество предыдущих исследований в области языков запросов для полуструктурированных данных — пожалуй, стоит упомянуть такие, как Quilt, XML-QL и Lorel. Почти все старые языки запросов для XML были университетскими исследовательскими проектами; в XQuery же заинтересованы такие гиганты, как Microsoft и Software AG.</p>
    <p>Следует пояснить, каким образом XML Schema и XQuery влияют на XSLT — казалось бы, их области применения несколько различаются. Напомним, что весомая часть функциональности XSLT зависит от языка XPath, который используется также и в XPointer. Как оказалось, XPath важен не только для XSLT и XPointer, но и для XQuery. Модель XML-документа, описанная в первой версии XPath, оказалась мощной, легко реализуемой и понятной абстракцией физической сущности XML и поэтому ее было решено использовать также и в XQuery. В следующей своей инкарнации эта модель будет выделена в отдельную спецификацию — "XQuery 1.0 and XPath 2.0 Data Model" ("Модель данных XQuery 1.0 и XPath 2.0"). Функции и операторы также будут выделены в отдельный документ — "XQuery 1.0 and XPath 2.0 Functions and Operators Version 1.0" ("Операторы и функции в XQuery 1.0 и XPath 2.0, версия 1.0").</p>
    <p>Принятие XML Schema также оказывает определенное влияние на XPath. В схемах ХМL-документов можно определять типы данных атрибутов и элементов. Соответственно, семантика XPath выражений должна отражать эту метаинформацию: например, оператор сложения "<code>+</code>" будет вести себя по-разному на строковых и числовых операндах.</p>
    <subtitle>Пример</subtitle>
    <p>Рассмотрим выражение <code>int/x + int/y</code> на простейшем документе:</p>
    <p><code>&lt;int&gt;</code></p>
    <p><code> &lt;x&gt;2&lt;/x&gt;</code></p>
    <p><code> &lt;y&gt;2&lt;/y&gt;</code></p>
    <p><code>&lt;/int&gt;</code></p>
    <p>В первой версии XPath результатом вычисления <code>int/x + int/у</code> в любом случае будет <code>4</code>. Между тем, старшие версии могут учитывать метаинформацию о типе обрабатываемых данных и возвращать <code>4</code> в случае числовых операндов и <code>"22"</code> в случае строковых.</p>
    <p>На момент написания этих строк работа над XSLT 2.0 и XPath 2.0 идет полным ходом. Конечно, пока еще рано заглядывать вперед и раскрывать секреты рабочей группы XSL, однако, основываясь на опубликованных спецификациях XLST 1.1 и требованиях к версии XSLT 2.0, кое-какие выводы сделать все же можно.</p>
   </section>
   <section>
    <title>
     <p>Отличия XSLT 1.1 от XSLT 1.0</p>
    </title>
    <section>
     <title>
      <p>Отсутствие result tree fragment</p>
     </title>
     <p>Главное и наиболее существенное отличие XSLT 1.1 от XSLT 1.0 состоит в том, что тип данных, известный в XSLT 1.0 как result tree fragment (результирующий фрагмент дерева) в XSLT 1.1. отсутствует. Вместо него в версии 1.1 используется множество узлов, состоящее из единственного корневого узла результирующего фрагмента.</p>
     <p>На первый взгляд, разница между двумя этими методами представления фрагментов деревьев минимальна. Но если принять во внимание положения языка XPath о том, что ни один тип данных не может быть преобразован во множество узлов, разница эта оказывается огромной. Получается, что, несмотря на то, что результирующий фрагмент и множество, состоящее из его корня, представляют одни и те же данные и структуры, с фрагментом нельзя делать многое из того, что можно делать с множеством узлов.</p>
     <subtitle>Пример</subtitle>
     <p>В преобразованиях часто бывает необходимо использовать массивы статических данных, и логично было бы присваивать их переменным, чтобы использовать затем в выражениях. К несчастью, простое создание фрагмента дерева в переменной мало помогает. Конструкция</p>
     <p><code>&lt;xsl:variable name="colors"&gt;</code></p>
     <p><code> &lt;color&gt;#0E0E0E&lt;/color&gt;</code></p>
     <p><code> &lt;color&gt;#FFFFFF&lt;/color&gt;</code></p>
     <p><code>&lt;/xsl:variable&gt;</code></p>
     <p>создает в переменной <code>colors</code> результирующий фрагмент дерева. В соответствии со спецификацией XPath 1.0 выражение <code>$colors/color[1]</code> будет некорректным, поскольку типом <code>colors</code> является результирующий фрагмент дерева, который не может быть напрямую преобразован во множество узлов. Иными словами, совершенно логичное и оправданное выражение не является корректным. Конечно, существуют способы обойти этот запрет — с помощью расширений и тому подобного, но нельзя не согласиться с тем, что результирующие фрагменты являются самой большой занозой в XSLT 1.0.</p>
     <p>XSLT 1.1 исправляет этот просчет. Переменная <code>colors</code>, определенная выше, будет иметь своим значение не фрагмент дерева, а множество из одного, корневого, узла этого фрагмента и ее можно использовать везде, где только можно использовать тип данных <code>node-set</code>.</p>
    </section>
    <section>
     <title>
      <p>Несколько выходящих документов</p>
     </title>
     <p>Как известно, преобразование в XSLT 1.0 имеет один основной входящий документ (плюс документы, доступные при помощи функции <code>document</code>) и ровно один выходящий документ. То есть, для того, чтобы сгенерировать на основе одного входящего документа несколько выходящих следует просто выполнить несколько преобразований.</p>
     <p>Следуя многочисленным запросам программистов, почти все разработчики XSLT-процессоров предоставили в своих продуктах возможность генерировать несколько выходящих документов непосредственно из одного преобразования. Элемент <code>xsl:document</code>, добавленный в XSLT 1.1, сделал эту возможность стандартной.</p>
     <subtitle>Пример</subtitle>
     <p>Самым простым применением <code>xsl:document</code> является разбиение одного документа на несколько. Например, имея документ вида</p>
     <p><code>&lt;book&gt;</code></p>
     <p><code> &lt;chapter&gt;Text 1&lt;/chapter&gt;</code></p>
     <p><code> &lt;chapter&gt;Text 2&lt;/chapter&gt;</code></p>
     <p><code> &lt;chapter&gt;Text 3&lt;/chapter&gt;</code></p>
     <p><code>&lt;/book&gt;</code></p>
     <p>мы можем выделить элементы <code>chapter</code> в отдельные файлы, а в самом выходящем документе создать оглавление со ссылками.</p>
     <subtitle>Листинг 12.1. Преобразование, использующее элемент xsl:document</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.1"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <p><code> &lt;xsl:template match="book"&gt;</code></p>
     <p><code>  &lt;xsl:copy&gt;</code></p>
     <p><code>   &lt;xsl:apply-templates select="chapter"/&gt;</code></p>
     <p><code>  &lt;/xsl:copy&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code> &lt;xsl:template match="chapter"&gt;</code></p>
     <p><code>  &lt;chapter href="chapter{position()}.xml"/&gt;</code></p>
     <p><code>  &lt;xsl:document href="chapter{position()}.xml"&gt;</code></p>
     <p><code>   &lt;xsl:copy-of select="."/&gt;</code></p>
     <p><code>  &lt;/xsl:document&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Результатом этого преобразования будут следующие четыре документа.</p>
     <subtitle>Листинг 12.2. Главный выходящий документ преобразования</subtitle>
     <p><code>&lt;book&gt;</code></p>
     <p><code> &lt;chapter href="chapter1.xml"/&gt;</code></p>
     <p><code> &lt;chapter href="chapter2.xml"/&gt;</code></p>
     <p><code> &lt;chapter href="chapter3.xml"/&gt;</code></p>
     <p><code>&lt;/book&gt;</code></p>
     <subtitle>Листинг 12.3. Документ chapter1.xml</subtitle>
     <p><code>&lt;chapter&gt;Text 1&lt;/chapter&gt;</code></p>
     <subtitle>Листинг 12.4. Документ chapter2.xml</subtitle>
     <p><code>&lt;chapter&gt;Text 2&lt;/chapter&gt;</code></p>
     <subtitle>Листинг 12.5. Документ chapter3.xml</subtitle>
     <p><code>&lt;chapter&gt;Text 3&lt;/chapter&gt;</code></p>
    </section>
    <section>
     <title>
      <p>Дополнительные возможности по расширению</p>
     </title>
     <p>В XSLT 1.1 был введен элемент <code>xsl:script</code>, предоставляющий дополнительные возможности для создания и использования функций расширения. При помощи <code>xsl:script</code> функции расширения могут быть явным образом определены в самом преобразовании.</p>
     <subtitle>Пример</subtitle>
     <p>В процессоре, который поддерживает скриптовые языки типа JavaScript, исходный код функций расширения может включаться в само преобразование, например.</p>
     <subtitle>Листинг 12.6. Преобразование, включающее функцию расширения</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.1"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:js="javascript:code"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:script language="javascript" implements-prefix="js"&gt;</code></p>
     <p><code>  function iff(arg1, arg2, arg3) {</code></p>
     <p><code>   if (arg1) {</code></p>
     <p><code>    return arg2;</code></p>
     <p><code>   } else {</code></p>
     <p><code>    return arg3;</code></p>
     <p><code>   }</code></p>
     <p><code>  }</code></p>
     <p><code> &lt;/xsl:script&gt;</code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Атрибут <code>implements-prefix</code> (англ. implements prefix — реализует префикс) связывает определяемую функцию с некоторым пространством имен (как мы отмечали ранее, все функции расширения должны принадлежать ненулевым пространствам имен). При вызове функций из этого пространства имен в XPath-выражениях, процессор будет искать их определения в элементах <code>xsl:script</code>, которые реализуют соответствующий префикс.</p>
     <p>Атрибут <code>language</code> определяет язык программирования, в котором написано расширение. Очевидно, язык влияет на то, как будет выполняться расширение — например, должен ли процессор интерпретировать содержимое <code>xsl:script</code> или следует загрузить внешний Java-класс. Естественно, не следует ожидать, что любой процессор сможет выполнять расширения, написанные на произвольных языках программирования — как правило, разработчики XSLT-средств в документации к своим продуктам оговаривают, какие языки расширения они поддерживают. Как следствие, преобразование, использующее расширения, написанные на "непонятном" процессору языке, либо не будут выполнены вообще, либо будут выполнены некорректно.</p>
     <p>Помимо двух обязательных атрибутов <code>implements-prefix</code> и <code>language</code>, в элемент <code>xsl:script</code> могут быть включены атрибуты <code>src</code> и <code>archive</code>, которые указывают физическое местоположение кода расширения.</p>
    </section>
    <section>
     <title>
      <p>"Внешние" типы данных</p>
     </title>
     <p>Четыре основных типа данных языка XPath (булевый, численный, строковый типы и множества узлов) в первой версии XSLT были расширены типом результирующего фрагмента дерева. В некотором смысле, фрагменты деревьев были "внешним" типом по отношению к XPath, но, тем не менее, многие из функций базовой библиотеки с успехом с этим типом работали.</p>
     <p>В XSLT 1.1 была впервые представлена поддержка произвольных внешних типов данных. Функции расширения могут возвращать и оперировать любыми типами данных. Например, в XSLT-процессорах, написанных на Java, в случае использования расширений в качестве значений часто используются произвольные классы.</p>
     <subtitle>Пример</subtitle>
     <p>Форматирование текущей даты и времени, которое было продемонстрировано в <emphasis>главе 10</emphasis> элементом <code>ext:date</code>, может быть переписано при помощи функций расширения следующим образом.</p>
     <subtitle>Листинг 12.7. Использование внешних типов данных в преобразовании</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.1"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:Date="java:java.util.Date"</code></p>
     <p><code> xmlns:SimpleDateFormat="java.text.SimpleDateFormat"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:variable name="df" select="SimpleDateFormat:new('HH:mm')"/&gt;</code></p>
     <p><code> &lt;xsl:variable name="now" select="Date:new()"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="SimpleDateFormat:format($df, $now)"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Пространства имен с префиксами <code>Date</code> и <code>SimpleDateFormat</code> определяют привязку к Java-классам <code>java.util.Date</code> и <code>java.text.SimpleDateFormat</code> соответственно (в этом примере мы используем формат URI пространств имен, принятый в процессоре Saxon).</p>
     <p>Объявление</p>
     <p><code>&lt;xsl:variable name="df" select="SimpleDateFormat:new('HH:mm')"/&gt;</code></p>
     <p>присваивает переменной <code>df</code> результат выполнения конструктора класса <code>SimpleDateFormat</code> со строковым параметром <code>"HH:mm"</code>, что эквивалентно Java-коду</p>
     <p><code>SimpleDateFormat df = new SimpleDateFormat("НН:mm");</code></p>
     <p>Иными словами, переменной <code>df</code> был присвоен "внешний" тип данных <code>java.text.SimpleDateFormat</code>. Аналогично, переменная now содержит данные типа <code>java.util.Date</code>. Фактически, этим переменным были присвоены экземпляры соответствующих классов.</p>
     <p>Выражение <code>SimpleDateFormat:format($df, $now)</code>, использованное в этом преобразовании, представляет собой ни что иное, как применение метода <code>format</code> экземпляра класса <code>SimpleDateFormat</code>, присвоенного переменной <code>df</code> к экземпляру класса <code>Date</code>, присвоенного переменной <code>now</code>. В переводе на Java:</p>
     <p><code>df.format(now);</code></p>
     <p>Надо сказать, что оперирование внешними типами — отнюдь не нововведение XSLT 1.1. Во многих процессорах интерфейсы расширения позволяют функциям возвращать произвольные типы данных. Важно, что теперь эта возможность закреплена в официальном документе Консорциума W3, и следует полагать, что и из второй версии языка она никуда не денется.</p>
    </section>
    <section>
     <title>
      <p>Стандартные интерфейсы расширений</p>
     </title>
     <p>Важным дополнением в XSLT 1.1 по сравнению с первой версией языка является определение стандартных интерфейсов расширения для языков IDL, JavaScript/ECMAScript и Java на основе интерфейсов DOM2.</p>
     <p>Одна из проблем, с которыми всегда приходится сталкиваться при работе с расширениями, является проблема переносимости. Вследствие того, что интерфейсы привязки к конкретным языкам программирования отдали в первой версии на усмотрение разработчиков процессоров, несовместимость интерфейсов не позволяет гарантировать работоспособность расширений при переходе с одного процессора на другой (даже если речь идет о процессорах одного типа, например, написанных на языке Java процессорах Saxon, Xalan и Oracle XSLT Processor).</p>
     <p>Ситуация, действительно, довольно досадная. С одной стороны, и XSLT, и Java являются переносимыми языками, с другой стороны, их сочетание в случае использования расширений оказывается непереносимым даже на Java-платформах. Стандартные интерфейсы, выработанные в XSLT 1.1, по всей вероятности, намного упростят положение вещей — ведь если написанное единожды Java-расширение будет работать на всех Java-платформах, этого уже будет достаточно, для того чтобы смело использовать всю мощь расширений.</p>
    </section>
    <section>
     <title>
      <p>Другие изменения</p>
     </title>
     <p>Помимо приведенных выше отличий версии 1.1 от первой версии языка, новый вариант включает в себя также некоторые другие добавления и исправления:</p>
     <p>&#9633; добавлена расширенная поддержка пространств имен при преобразовании;</p>
     <p>&#9633; добавлена поддержка XML Base;</p>
     <p>&#9633; добавлена возможность использования параметров при вызове шаблонов элементом <code>xsl:apply-imports</code>;</p>
     <p>&#9633; расширено множество атрибутов элементов XSLT, которые могут содержать шаблоны значений атрибутов;</p>
     <p>&#9633; добавлено определение лексикографического порядка (наподобие <code>'а' &lt; 'b' </code>&#8594;<code> true</code>);</p>
     <p>&#9633; добавлено сравнение строк без учета регистра символов;</p>
     <p>&#9633; добавлены операторы для проверки порядка следования узлов в документе;</p>
     <p>&#9633; исправлены обнаруженные ошибки.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Отличия XSLT 2.0 от XSLT 1.1</p>
    </title>
    <section>
     <p>Прежде чем приступить к описанию отличий второй версии XSLT от версии 1.1 (и, соответственно, 1.0), следует сделать одно существенное замечание. Лицензионные соглашения Консорциума W3 не позволяют раскрывать широкой общественности внутренние материалы рабочих групп W3C до того, как они будут официально опубликованы. Потому, строго говоря, все, что будет ниже сказано о версии 2.0 — это не более чем совокупность гипотез, пожеланий и выводов, сделанных на основе спецификации XSLT 1.1 и требований к XSLT 2.0 и XPath 2.0. Эти документы доступны публично.</p>
    </section>
    <section>
     <title>
      <p>Изменения в XPath 2.0</p>
     </title>
     <p>Разрабатываемая версия языка XPath, вследствие интеграции с XQuery, очевидно, претерпит серьезные изменения. Новая спецификация уже сейчас разбита на два документа: документ, описывающий модель данных и документ, описывающий функции и операторы. Поэтому на данный момент сложно делать точный прогноз относительно того, что же получится в итоге. Мы ограничимся перечислением основных требований:</p>
     <p>&#9633; поддержка группы XML-стандартов: определение модели в терминах XML Information Set, выделение общего синтаксиса и семантики с XQuery 1.0;</p>
     <p>&#9633; переопределение операторов сравнения на множествах;</p>
     <p>&#9633; определение операторов пересечения и разности множеств;</p>
     <p>&#9633; расширение множества агрегатных функций (наподобие <code>sum</code>, <code>count</code>, <code>min</code>, <code>max</code> — функций, работающих на множествах);</p>
     <p>&#9633; возможность использования выражений, возвращающих множества узлов в качестве шагов выборки, например <code>/a/(b|c)/d</code> вместо <code>/а/b/d | /a/c/d</code>;</p>
     <p>&#9633; введение оператора аналогичного оператору <code>?</code> в Java и С (выражение <code>a ? b : с</code>, где <code>а</code> имеет булевый тип, возвращает <code>b</code>, если <code>a</code> — "истина" и <code>с</code>, если <code>a</code> — "ложь");</p>
     <p>&#9633; дополнительные строковые функции как-то: замена подстроки, выравнивание, изменение регистра символов;</p>
     <p>&#9633; поддержка регулярных выражений;</p>
     <p>&#9633; поддержка примитивных типов XML Schema;</p>
     <p>&#9633; использование информации о структуре документа, определенной в его схеме;</p>
     <p>&#9633; поддержка экспоненциальной нотации чисел (наподобие <code>2Е10</code> = 1024);</p>
     <p>&#9633; поддержка функций приведения и преобразования (аналог <code>CAST</code> и <code>CONVERT</code> из SQL).</p>
    </section>
    <section>
     <title>
      <p>Выбор шаблонов для элементов пространства имен, определенного по умолчанию</p>
     </title>
     <p>Одним из значительных неудобств первой версии XSLT была невозможность сменить пространство имен, определенное по умолчанию для паттернов. То есть, если шаблон будет определен как</p>
     <p><code>&lt;xsl:template match="foo"&gt;</code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>то обрабатывать он будет только те элементы <code>foo</code>, которые принадлежат нулевому пространству имен. Для элемента</p>
     <p><code>&lt;bar:foo xmlns:bar="urn:bar-namespace"/&gt;</code></p>
     <p>придется писать шаблон вида</p>
     <p><code>&lt;xsl:template match="ns:foo" xmlns:ns="urn:bar-namespace"&gt;</code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/xsl:template&gt;</code></p>
     <p>В случае целого документа принадлежащего ненулевому пространству имен, определения подобного рода могут оказаться слишком громоздкими. Решение этой проблемы может быть очень простым и элегантным.</p>
     <subtitle>Листинг 12.8. Изменение пространства имен для паттерна</subtitle>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="2.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns="urn:bar-namespace"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="foo"&gt;</code></p>
     <p><code>  ...</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>В элементе xsl:stylesheet пространство имен с URI <code>"urn:bar-namespace"</code> определяется как пространство имен по умолчанию и паттерн <code>foo</code> соответствует элементу с локальной частью имени <code>"foo"</code> и URI пространства имен <code>"urn:bar-namespace"</code>.</p>
    </section>
    <section>
     <title>
      <p>Средства для форматирования даты и времени</p>
     </title>
     <p>В первых версиях XSLT элемент <code>xsl:decimal-format</code> и функция <code>format-number</code> обеспечивали форматирование чисел при их текстовом отображении. К сожалению, подобных инструментов для форматирования даты предусмотрено не было.</p>
     <p>Поскольку связка элемента, определяющего именованный формат и функции, выполняющей форматирование, оказалась очень удачной, по всей вероятности, подобную схему мы будем наблюдать и в версии 2.0. Скорее всего, связка для форматирования даты и времени будет состоять из элемента <code>xsl:date-format</code> и функции <code>format-date</code>.</p>
    </section>
    <section>
     <title>
      <p>Функции<emphasis> id</emphasis> и<emphasis> key</emphasis> на внешних документах</p>
     </title>
     <p>В XSLT 1.1 функции <code>id</code> и <code>key</code> возвращают множества узлов документа, который содержит текущий узел преобразования. То есть для того, чтобы использовать ключи или уникальные идентификаторы для выбора узлов внешнего документа, необходимо сначала сменить контекст, например:</p>
     <p><code>&lt;xsl:for-each select="document('ext.xml')"&gt;</code></p>
     <p><code> &lt;xsl:copy-of select="key('name', 'value')"/&gt;</code></p>
     <p><code>&lt;/xsl:for-each&gt;</code></p>
     <p>Требования ко второй версии XSLT предполагают упрощение работы с ключами и уникальными идентификаторами на внешних документах.</p>
    </section>
    <section>
     <title>
      <p>Включение неразбираемых внешних сущностей в виде текста</p>
     </title>
     <p>В первых версиях XSLT отсутствовала возможность включения внешних сущностей, не разбирая их как XML-документы. Без помощи расширений было невозможно включить в выходящий документ простой внешний текстовый файл. Между тем, вполне подходящим решением была бы функция типа <code>unparsed-entity</code>, которая по данному URI возвращала бы содержимое ресурса в виде строки. Естественно, при этом необходимо учитывать кодировку внешней сущности и Unicode-символы, которые не могут присутствовать в XML (например, управляющие символы).</p>
    </section>
    <section>
     <title>
      <p>Использование именованных сущностей вместо кодов символов</p>
     </title>
     <p>Это требование связано с желанием пользователей видеть в выходящем документе вместо сущности <code>&amp;#xA0;</code> ее более привычный вариант <code>&amp;nbsp;</code>. В настоящее время приходится прибегать ко всяким хитростям вроде</p>
     <p><code>&lt;xsl:text disable-output-escaping="yes"&gt;&amp;amp;nbsp;&lt;/xsl:text&gt;</code></p>
     <p>совсем не гарантирующим, кстати, что в выходящем файле окажется именно <code>&amp;nbsp;</code>.</p>
     <p>В самом преобразовании сущности можно определять в DTD-заголовке следующим образом:</p>
     <p><code>&lt;!DOCTYPE xsl:stylesheet [</code></p>
     <p><code> &lt;!ENTITY nbsp "&amp;#хА0;"&gt;</code></p>
     <p><code>]&gt;</code></p>
     <p><code>&lt;xsl:stylesheet ... &gt;</code></p>
     <p><code> ...</code></p>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Однако на выходящий документ эти определения никоим образом не сказываются.</p>
    </section>
    <section>
     <title>
      <p>Обращение ссылок по<emphasis> ID</emphasis>/<emphasis>IDREF</emphasis></p>
     </title>
     <p>Функция <code>id</code> позволяет отыскать в документе элементы по заданным значениями <code>ID</code>-атрибутов. Это особенно полезно при работе с <code>IDREF</code>-атрибутами, которые ссылаются на <code>ID</code>-атрибуты: можно с легкостью выбрать элементы, на которые ссылается текущий элемент. Новым требованием к XSLT 2.0 является возможность "обращать" такого рода ссылки — то есть находить элементы, которые ссылаются на данный элемент (включают определенные значения в свои <code>IDREF</code>-атрибуты).</p>
    </section>
    <section>
     <title>
      <p>Другие требования</p>
     </title>
     <p>В числе прочих требований, предъявленных к XSLT 2.0, можно перечислить следующие:</p>
     <p>&#9633; поддержка группировки;</p>
     <p>&#9633; поддержка Unicode-нормализации строк;</p>
     <p>&#9633; сортировка узлов в соответствии с информацией о их типах, сообщенной XML-схемой документа;</p>
     <p>&#9633; создание и копирование узлов с учетом информации об их типах;</p>
     <p>&#9633; создание пространства имен с вычисляемым префиксом и URI.</p>
    </section>
   </section>
  </section>
  <section>
   <title>
    <p>Приложение 1</p>
    <p>Обзор XSLT-процессоров</p>
   </title>
   <section>
    <p>Здесь даны необходимые сведения по всем существующим XSLT-процессорам, достаточные для того, чтобы сориентировать разработчика и помочь ему выбрать наиболее подходящий инструмент. Перечислим основные факторы, которые мы будем учитывать для каждого из рассматриваемых процессоров:</p>
    <p>&#9633; поддерживаемые программные или языковые платформы;</p>
    <p>&#9633; поддержка расширений;</p>
    <p>&#9633; полнота реализации;</p>
    <p>&#9633; популярность;</p>
    <p>&#9633; скорость.</p>
    <p>Несмотря на то, что XSLT-процессоры являются довольно сложными программами, в подавляющем большинстве они распространяются по бесплатным лицензиям. Как следствие, ценовой показатель не является в данном случае определяющим.</p>
   </section>
   <section>
    <title>
     <p>Популярность XSLT-процессоров</p>
    </title>
    <p>Немаловажным фактором при выборе XSLT-процессора является его популярность: ведь чем более распространен процессор, тем больше возможность учитывать опыт предыдущих разработок и тем меньше вероятность найти грабли, на которые до этого еще не наступили другие.</p>
    <p>На рис. П1.1 представлены результаты опросов, проведенных нами среди русскоязычных XML-разработчиков. В опросе принимали участие посетители сайта <strong>http://www.xmlhack.ru</strong> и подписчики конференции <strong>fido7.ru.xml</strong>. Параметр, приведенный в процентах, показывает, какая часть опрошенных использует этот процессор.</p>
    <image l:href="#img_90.png"/>
    <p><strong>Рис. П1.1</strong>. Популярность основных XSLT-процессоров</p>
    <p>Как и следовало ожидать, что наиболее популярным XSLT-процессором для решений на платформе Win32 является собственная разработка Microsoft — процессор MSXML. На Java-платформах самым популярным средством является Xalan, который разрабатывался в Apache XML Project.</p>
   </section>
   <section>
    <title>
     <p>Производительность XSLT-процессоров</p>
    </title>
    <p>Другим важным параметром, который следует учитывать при выборе процессора, является производительность или скорость выполнения преобразований. От производительности процессора зависит реальность использования XSLT в решениях, требующих быстрого времени реакции (например, на Web-серверах).</p>
    <p>Производительность процессоров очень нелегко оценить. Во-первых, дело приходится иметь с различными программными и языковыми платформами, производительность которых различается уже сама по себе. Во-вторых, вследствие применения различных алгоритмов, эффективность процессоров может неодинаково проявляться на различных типах преобразований (например, на преобразовании <emphasis>А</emphasis> процессор I может быть быстрее процессора II, а на преобразовании <emphasis>В</emphasis> — медленнее). В-третьих, не все процессоры полностью и правильно реализуют возможности XSLT, то есть далеко не все преобразования будут выполняться на всех процессорах одинаково. Наконец, из всего времени обработки сложно выделить время, потраченное собственно на преобразование (а не на разбор и сериализацию XML).</p>
    <p>Вследствие этого ни одна из оценок производительности не может претендовать на абсолютную достоверность. Впрочем, этого и не требуется — нам важно сориентироваться среди существующих процессоров по скорости, а для этого будет достаточно и приблизительных данных.</p>
    <p>С любезного разрешения Кевина Джонса (Kevin Jones) и DataPower, Inc, мы опубликуем результаты двух исследований производительности XSLT-процессоров, основанных на сравнительном анализе времени выполнения контрольного набора примеров. Сами примеры и исходную статистическую информацию можно найти на следующих Web-сайтах:</p>
    <p>&#9633; <strong>http://www.datapower.com/XSLTMark</strong></p>
    <p>&#9633; <strong>http://www.tfi-technology.com/xml/xslbench.html</strong></p>
    <p>Мы приведем результаты этих исследований, выразив их в процентах (рис. П1.2 и П1.3). Относительную оценку в 100% имеет процессор с наивысшей скоростью, 50% — процессор, который оказался в два раза медленнее и так далее.</p>
    <image l:href="#img_91.png"/>
    <p><strong>Рис. П1.2</strong>. Оценка производительности XSLT-процессоров в соответствии с XSLBench</p>
    <image l:href="#img_92.png"/>
    <p><strong>Рис. П1.3</strong>. Оценка производительности XSLT-процессоров в соответствии с XSLTMark</p>
    <cite>
     <subtitle>Замечание</subtitle>
     <p>К моменту выхода книги в свет эта информация, скорее всего, потеряет свою актуальность — появятся новые процессоры, а старые будут переработаны. Несмотря на это, в глобальной перспективе расстановка сил вряд ли изменится, и поэтому приведенные данные могут быть полезны при выборе процессора и в будущем.</p>
    </cite>
   </section>
   <section>
    <title>
     <p>Библиотека Microsoft XML Parser</p>
    </title>
    <section>
     <p>Основные характеристики. &#9633; Платформы: MS Windows.</p>
     <p>&#9633; Расширения: функции расширения на JavaScript и VBScript.</p>
     <p>&#9633; Полнота реализации: один из наиболее проработанных процессоров.</p>
     <p>&#9633; Разработчик: Microsoft Corporation.</p>
     <p>&#9633; URL: <strong>http://msdn.microsoft.com/xml</strong>.</p>
     <p>Продукт, названный Microsoft XML Parser, на самом деле далеко не только парсер. MSXML — это базовый компонент, объединяющий DOM/SAX-парсер, XSLT-процессор и некоторые другие инструменты. Мы будем рассматривать только XSLT-функциональность.</p>
     <p>Компания Microsoft начала проявлять интерес к XSLT уже на самых ранних этапах разработки языка - когда он еще не был выделен из родительской технологии XSLT. Прототип процессора, предложенный Microsoft, был одной из первых рабочих реализаций XSLT. К сожалению, в этом прототипе был реализован ранний диалект языка, не совместимый со стандартной версией XSLT. Он получил большое распространение вместе с браузерами Internet Explorer 4.0, 5.0 и 5.5, и, как результат, множество программистов и по сей день работают с нестандартной версией XSLT, которая описывается пространством имен <code>"http://www.w3.org/TR/WD-xsl"</code>. Поддержка стандартного XSLT была реализована в версии MSXML 3.0, которая вышла в марте 2000 года (более полная, production-версия появилась чуть позже, осенью).</p>
     <p>Ранний вариант XSLT, реализованный в MSXML 2.0 и ниже, имеет схожие с XSLT 1.0 принципы, но также и целый ряд несовместимых отличий. Следует скорее сказать, что WD-xsl — это другой язык и программировать на нем тоже следует по-другому. Для того чтобы использовать стандартный XSLT в MSXML, следует обновить этот компонент, загрузив новую версию с Web-сайта Microsoft. Однако, и это еще не все. Дело в том, что Microsoft не отказалась от старой нестандартной версии и MSXML 3.0 поддерживает ее наравне с XSLT 1.0. Более того, по умолчанию, MSXML устанавливается в так называемом side-by-side режиме (англ. side-by-side - бок о бок). Это означает, что вновь установленный компонент не замещает предыдущую версию полностью. Поэтому устанавливать MSXML следует в режиме замены — по окончанию установки следует воспользоваться утилитой xmlinst.exe, также доступной с Web-сайта Microsoft для того, чтобы полностью заменить старую версию.</p>
     <p>Типичными симптомами не до конца обновленной версии MSXML является следующее:</p>
     <p>&#9633; при попытке выполнить корректные преобразования, определенные в пространстве имен с URI <code>"http://www.w3.org/1999/XSL/Transform"</code>, не происходит ничего или выдается ошибка;</p>
     <p>&#9633; при попытке выполнить те же преобразования, исправив URI на <code>"http://www.w3.org/TR/WD-xsl"</code>, процессор пытается выполнить преобразование, но выдает ошибку о некорректности преобразования (в то время как оно работает на других процессорах);</p>
     <p>&#9633; в преобразованиях не работают переменные, именованные шаблоны, шаблоны значений атрибутов, ключи и импортирование.</p>
     <p>В случае обнаружения подобных признаков единственным советом является обновление версии MSXML в режиме замены.</p>
     <cite>
      <subtitle>Предупреждение</subtitle>
      <p>Перед установкой MSXML3 рекомендуется внимательно ознакомиться с документацией на предмет возможности установки в режиме замены. Некоторые программные продукты (такие, как SQL Server и Biztalk Server) используют старую версию XSLT-процессора, и обновление в режиме замены приведет к нестабильности их работы.</p>
     </cite>
    </section>
    <section>
     <title>
      <p>Использование</p>
     </title>
     <p>Так как MSXML уже давно превратился в стандартный компонент Windows, использовать его можно разными способами - например, в собственных приложениях или как ISAPI-расширение. При разработке XSLT-преобразований MSXML, как правило, применяется либо совместно с браузером Internet Explorer, либо как самостоятельная утилита командной строки.</p>
     <p>Первый способ заключается в том, что с XML-документом посредством инструкции <code>xml-stylesheet</code> ассоциируется преобразование и Internet Explorer отображает результат преобразования.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг П1.1. Входящий документ source.xml</subtitle>
     <p><code>&lt;?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?&gt;</code></p>
     <p><code>&lt;date&gt;18.10.2001&lt;/date&gt;</code></p>
     <subtitle>Листинг П1.2. Преобразование stylesheet.xsl</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;html&gt;</code></p>
     <p><code>   &lt;head&gt;</code></p>
     <p><code>    &lt;title&gt;Today is page&lt;/title&gt;</code></p>
     <p><code>   &lt;/head&gt;</code></p>
     <p><code>   &lt;body&gt;</code></p>
     <p><code>    &lt;xsl:apply-templates select="date"/&gt;</code></p>
     <p><code>   &lt;/body&gt;</code></p>
     <p><code>  &lt;/html&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="date"&gt;</code></p>
     <p><code>  &lt;H1&gt;</code></p>
     <p><code>   &lt;xsl:text&gt;Сегодня &lt;/xsl:text&gt;</code></p>
     <p><code>   &lt;xsl:value-of select="."/&gt;</code></p>
     <p><code>  &lt;/H1&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>Документ source.xml будет отображен в браузере Internet Explorer следующим образом (рис. П1.4).</p>
     <image l:href="#img_93.png"/>
     <p><strong>Рис. П1.4</strong>. Документ source.xml, отображенный браузером Internet Explorer</p>
     <p>Другим, вариантом является использование утилиты командной строки <code>msxsl.exe</code>, которая также доступна на Web-сайте MSDN. Эта утилита есть не более чем оболочка для MSXML, позволяющая вызывать основной компонент из командной строки.</p>
     <p>Использование <code>msxsl.exe</code> совершенно стандартно: для применения преобразования <code>stylesheet.xsl</code> к документу <code>source.xml</code> и вывода результата в файле <code>result.xml</code> нужно выполнить следующую команду:</p>
     <p><code>msxsl.exe source.xml stylesheet.xsl -о result.xml</code></p>
    </section>
    <section>
     <title>
      <p>Расширения</p>
     </title>
     <p>MSXML поддерживает пользовательские функции расширения, которые могут быть написаны на скриптовых языках VBScript и JScript и включены непосредственно в сами преобразования.</p>
     <subtitle>Пример</subtitle>
     <subtitle>Листинг П1.3. Входящий документ</subtitle>
     <p><code>&lt;?xml version="1.0" encoding="windows-1251"?&gt;</code></p>
     <p><code>&lt;page&gt;Сегодня &lt;date/&gt;.&lt;/page&gt;</code></p>
     <subtitle>Листинг П1.4. Преобразование</subtitle>
     <p><code>&lt;xsl:stylesheet version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:msxsl="urn:schemas-microsoft-com:xslt"</code></p>
     <p><code> xmlns:ext="urn:extension-functions"</code></p>
     <p><code> exclude-result-prefixes="msxsl ext"&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:output encoding="windows-1251"/&gt;</code></p>
     <empty-line/>
     <p><code> &lt;msxsl:script</code></p>
     <p><code>  language="JavaScript"</code></p>
     <p><code>  implements-prefix="ext"&gt;</code></p>
     <p><code>  function date() {</code></p>
     <empty-line/>
     <p><code>   now = new Date;</code></p>
     <empty-line/>
     <p><code>   return now.getDate() + '.' +</code></p>
     <p><code>    (now.getMonth() + 1) + '.' +</code></p>
     <p><code>    now.getYear();</code></p>
     <p><code>  }</code></p>
     <p><code> &lt;/msxsl:script&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="/"&gt;</code></p>
     <p><code>  &lt;html&gt;</code></p>
     <p><code>   &lt;head&gt;</code></p>
     <p><code>    &lt;title&gt;Today is page&lt;/title&gt;</code></p>
     <p><code>   &lt;/head&gt;</code></p>
     <p><code>   &lt;body&gt;</code></p>
     <p><code>    &lt;xsl:apply-templates/&gt;</code></p>
     <p><code>   &lt;/body&gt;</code></p>
     <p><code>  &lt;/html&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template match="date"&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="ext:date()"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <subtitle>Листинг П1.5. Выходящий документ</subtitle>
     <p><code>&lt;html&gt;</code></p>
     <p><code> &lt;head&gt;</code></p>
     <p><code>  &lt;META</code></p>
     <p><code>   http-equiv="Content-Type"</code></p>
     <p><code>   content="text/html;</code></p>
     <p><code>   charset=windows-1251"&gt;</code></p>
     <p><code>  &lt;title&gt;Today is page&lt;/title&gt;</code></p>
     <p><code> &lt;/head&gt;</code></p>
     <p><code> &lt;body&gt;Сегодня 18.10.2001.&lt;/body&gt;</code></p>
     <p><code>&lt;/html&gt;</code></p>
     <p>Как и во многих других процессорах, в MSXML предусмотрена функция расширения <code>node-set</code>, которая преобразует результирующий фрагмент дерева во множество узлов. Функция <code>node-set</code> принадлежит пространству имен с URI "<code>urn:schemas-microsoft-com:xslt</code>", и стандартным сценарием ее использования будет примерно следующий:</p>
     <p><code>&lt;xsl:stylesheet</code></p>
     <p><code> version="1.0"</code></p>
     <p><code> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code></p>
     <p><code> xmlns:msxsl="urn:schemas-microsoft-com:xslt"</code></p>
     <p><code> exclude-result-prefixes="msxsl "&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- ... --&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:variable name="tree"&gt;</code></p>
     <p><code>  &lt;!-- Переменная, содержащая результирующий фрагмент дерева --&gt;</code></p>
     <p><code>  &lt;item&gt;A&lt;/item&gt;</code></p>
     <p><code>  &lt;item&gt;B&lt;/item&gt;</code></p>
     <p><code> &lt;/xsl:variable&gt;</code></p>
     <empty-line/>
     <p><code> &lt;!-- ... --&gt;</code></p>
     <empty-line/>
     <p><code> &lt;xsl:template ... &gt;</code></p>
     <p><code>  &lt;!-- Обращение к $tree, как ко множеству узлов --&gt;</code></p>
     <p><code>  &lt;xsl:value-of select="msxsl:node-set($tree)/item[1]"/&gt;</code></p>
     <p><code> &lt;/xsl:template&gt;</code></p>
     <empty-line/>
     <p><code>&lt;/xsl:stylesheet&gt;</code></p>
     <p>К сожалению, текущая версия MSXML не поддерживает расширение пользовательскими элементами.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Процессор Xalan</p>
    </title>
    <section>
     <p>Основные характеристики.</p>
     <p>&#9633; Платформы: Java, С++.</p>
     <p>&#9633; Расширения: функции и элементы расширения.</p>
     <p>&#9633; Полнота реализации: один из наиболее проработанных процессоров. &#9633; Разработчик: Apache XML Project.</p>
     <p>&#9633; URL: <strong>http://xml.apache.org</strong>.</p>
     <p>Xalan — это очень известный XSLT-процессор, созданный в рамках Apache XML Project для языковых платформ Java и С++. Xalan, как и остальные продукты Apache XML Project, поставляется с открытым исходным кодом и открытым API, что делает его очень привлекательным для интеграции в другие приложения.</p>
    </section>
    <section>
     <title>
      <p>Использование</p>
     </title>
     <p>По сути дела, Xalan Java и Xalan C++ — это библиотеки, позволяющие использовать XSLT-преобразования в собственных проектах. Xalan Java поддерживает набор интерфейсов TrAX (от англ. transformation API for XML — программный интерфейс преобразований для XML), определяющий стандартные модели и методы преобразования XML-документов в Java-программах.</p>
     <p>Помимо этого, и Xalan Java и Xalan С++ предусматривают возможность выполнения преобразований из командной строки. Для Xalan Java стандартный вызов будет выглядеть так:</p>
     <p><code>java org.apache.xalan.xslt.Process -in source.xml -xsl stylesheet.xsl -OUT result.xml</code></p>
     <p>Если при попытке выполнения этой команды выдается сообщение вида:</p>
     <p><code>Exception in thread "main" java.lang.NoClassDefFoundError:</code></p>
     <p><code>org/apache/xalan/xslt/Process</code></p>
     <p>это означает, что библиотека <code>xalan.jar</code> не прописана в переменной окружения <code>CLASSPATH</code>, запустить Xalan в этом случае можно, указав <code>xalan.jar</code> в параметрах явным образом:</p>
     <p><code>java -cp xalan.jar org.apache.xalan.xslt.Process -in source.xml -xsl stylesheet.xsl -out result.xml</code></p>
     <p>Библиотека Xalan С++ имеет несколько вариантов для платформ Windows 32, Linux, AIX, HP-UX и Solaris, каждый из которых включает также скомпилированную утилиту TestXSLT, позволяющую выполнять преобразования из командной строки:</p>
     <p><code>TestXSLT -in source.xml -xsl stylesheet.xsl -out result.xml</code></p>
    </section>
    <section>
     <title>
      <p>Расширения</p>
     </title>
     <p>Xalan С++ позволяет вызывать в XSLT-преобразовании пользовательские функции расширения, написанные на языке С. Кроме того, в дополнение к базовым функциям XSLT, Xalan С++ реализует несколько наиболее часто используемых функций, например, функцию <code>nodeset</code>. В текущей версии (1.2) Xalan С++ не поддерживает элементы расширения.</p>
     <p>Возможности расширения Xalan Java намного богаче. Xalan Java, как и Xalan С++, реализует дополнительную библиотеку функций (которая по сравнению с Xalan С++ также намного шире). Помимо этого, Xalan Java позволяет создавать функции и элементы расширения на Java и других языках программирования.</p>
     <p>Остановимся на последнем пункте более подробно. Xalan позволяет использовать библиотеку BSF (от англ. bean scripting framework — система скриптовых языков для bean-компонент). BSF — это библиотека, которая позволяет использовать скриптовые языки в Java-приложениях и апплетах. На данный момент BSF позволяет реализовывать в Xalan Java расширения на следующих скриптовых языках:</p>
     <p>&#9633; Mozilla Rhino (фактически, еще один вариант JavaScript);</p>
     <p>&#9633; NetRexx;</p>
     <p>&#9633; BML;</p>
     <p>&#9633; JPython;</p>
     <p>&#9633; Jacl;</p>
     <p>&#9633; PerlScript;</p>
     <p>&#9633; VBScript;</p>
     <p>&#9633; JavaScript.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Процессор Saxon</p>
    </title>
    <section>
     <p>Основные характеристики.</p>
     <p>&#9633; Платформы: Java.</p>
     <p>&#9633; Расширения: функции и элементы расширения на Java.</p>
     <p>&#9633; Полнота реализации: практически идеальная.</p>
     <p>&#9633; Разработчик: Майкл Кей.</p>
     <p>&#9633; URL: <strong>http://saxon.sourceforge.net</strong>.</p>
     <p>XSLT-процессор Saxon был разработан и до сих пор поддерживается единственным человеком — Майклом Кеем (Michael Kay), который в настоящий момент является редактором спецификации XSLT 2.0. Процессор Saxon, так же как и Xalan, является бесплатным open-source продуктом.</p>
     <p>На Web-сайте Saxon доступны два варианта процессора — полный Saxon и облегченная версия, скомпилированная для Windows — Instant Saxon, которая занимает всего 400 килобайт в архиве, но практически не уступает полной версии по функциональности.</p>
     <p>Следует особым образом подчеркнуть полноту реализации Saxon. Майкл Кей является известным специалистом по XSLT, который много времени уделяет консультированию разработчиков в списке-рассылке XSL List. Столь плотная работа с конечными пользователями позволяет ему быстро реагировать на информацию о допущенных ошибках и несоответствиях. Как результат, разработанный и поддерживаемый им процессор считается образцом соответствия стандарту XSLT. В целом, Saxon можно описать как выдающийся продукт от выдающегося человека.</p>
    </section>
    <section>
     <title>
      <p>Использование</p>
     </title>
     <p>Легкий вариант, Instant Saxon представляет собой утилиту командной строки <code>saxon.exe</code>, с помощью которой можно применять преобразования к XML-документам:</p>
     <p><code>saxon.exe -о result.xml source.xml stylesheet.xsl</code></p>
     <p>Полная версия Saxon (включающая также исходный код) тоже может использоваться как утилита командной строки:</p>
     <p><code>java com.icl.saxon.stylesheet -о result.xml source.xml stylesheet.xsl</code></p>
     <p>Как и в случае с Xalan, библиотеку <code>saxon.jar</code> придется либо включить в переменную окружения <code>CLASSPATH</code>, либо указывать явным образом</p>
     <p><code>java -cp saxon.jar com.icl.saxon.StyleSheet -o result.xml source.xml stylesheet.xsl</code></p>
     <p>Между тем, Saxon — это далеко не только процессор командной строки. Saxon предоставляет очень мощные возможности для использования в собственных проектах. В частности, Saxon поддерживает TrAX (Transformation API for XML), о котором мы говорили чуть выше, позволяет применять пользовательские парсеры и сериализаторы, предоставляет API для Java и многое другое.</p>
    </section>
    <section>
     <title>
      <p>Расширения</p>
     </title>
     <p>Расширения для Saxon могут быть созданы на языке Java в виде функций и элементов. Saxon отличает возможность использования Java-функций расширения, написанных для других Java-процессоров (в частности Xalan и Oracle XSLT Processor).</p>
     <p>Для программирования элементов расширения Saxon предоставляет интерфейс <code>com.icl.saxon.style.ExtensionElementFactory</code>, который несколько отличается от подхода, предложенного в Xalan. В Xalan элементу расширения соответствует функция класса, в то время как в Saxon элементу расширения соответствует "фабрика классов", <code>ExtensionElementFactory</code>, возвращающая по данному имени элемента класс-наследник <code>com.icl.saxon.style.StyleElement</code>, соответствующий экземпляру элемента.</p>
     <p>Помимо описанных выше возможностей, базовая библиотека функций XPath расширена в Saxon большим количеством функций, облегчающих работу со строками, множествами, датами и так далее. Saxon также включает некоторые из расширений, предложенные инициативой EXSLT.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Библиотека Oracle XDK</p>
    </title>
    <section>
     <p>Основные характеристики.</p>
     <p>&#9633; Платформы: Java, C/C++, PL/SQL.</p>
     <p>&#9633; Расширения: поддержка функций расширения.</p>
     <p>&#9633; Полнота реализации: сравнительно хорошая (уступает Saxon и MSXML).</p>
     <p>&#9633; Разработчик: Oracle Corporation.</p>
     <p>&#9633; URL: <strong>http://technet.oracle.com/tech/xml/</strong>.</p>
     <p>Так же как и MSXML, Oracle XDK (от англ. XML Development Kit - комплект для XML-разработки) состоит из нескольких компонентов, предназначенных для разработки XML-приложений на Java, С, С++ и PL/SQL. Библиотека Oracle XDK включает XML-парсер, реализующий DOM и SAX интерфейсы, XSLT-процессор, генератор классов и процессор для XML Schema. Java-версия XDK также включает XSQL-сервлет и утилиту XML SQL (в сокращении — XSU), которые являются основой решений Oracle для обеспечения XML-функциональности в базах данных. XSU предоставляет возможности для экспорта и импорта реляционных данных в виде XML, а сервлет XSQL позволяет использовать возможности XSU в клиент-серверных приложениях (в частности — на Web-серверах). Примечательно, что XSU и XSQL работают не только с базой данных Oracle, но и с любыми другими базами данных, которые поддерживают JDBC-доступ. Oracle XDK разработан под руководством Стива Мюнха (Steve Muench), который также является очень известным специалистом по XML.</p>
     <p>Главным образом в Oracle XDK нас интересует библиотека, отвечающая за выполнение XSLT-преобразований — Oracle XSLT Processor. Этот компонент включен во все языковые версии XDK: существует вариант для Java, С, С++ и даже для PL/SQL (что позволяет выполнять преобразования внутри базы данных Oracle).</p>
     <p>Относительно проработанности Oracle XSLT Processor можно сказать следующее: XSLT 1.0 поддерживается полностью (или почти полностью), однако периодически попадаются мелкие ошибки, которые оперативно исправляются в следующих релизах. XSLT-процессор играет важную роль в Web-решениях Oracle и потому его поддержке и отладке уделяется большое внимание.</p>
    </section>
    <section>
     <title>
      <p>Использование</p>
     </title>
     <p>Главной областью применения Oracle XSLT Processor является его использование совместно с технологиями XSQL и XSU для обеспечения Web-доступа к реляционным данным. Кроме этого, Oracle XSLT Processor легко интегрируется в другие приложения и также может выполняться из командной строки. Например, в Java-версии Oracle XDK для выполнения преобразования следует запустить команду:</p>
     <p><code>java oracle.xml.parser.v2.oraxsl source.xml stylesheet.xsl result.xml</code></p>
     <p>Если выдается сообщение о ненайденном классе, можно попробовать следующий вариант:</p>
     <p><code>java -cp xmlparserv2.jar oracle.xml.parser.v2.oraxsl source.xml stylesheet.xsl result.xml</code></p>
     <p>Можно также воспользоваться утилитой пакетной обработки <code>oraxsl</code>:</p>
     <p><code>oraxsl source.xml stylesheet.xsl result.xml</code></p>
    </section>
    <section>
     <title>
      <p>Расширения</p>
     </title>
     <p>Java-версия Oracle XSLT Processor может расширяться пользовательскими функциями, написание которых, в принципе, ничем не отличаются от стандартных методов создания Java-функций расширения.</p>
     <p>К сожалению, Oracle XSLT Processor не поддерживает пользовательские элементы расширения. Стандартных дополнений базовой библиотеки функций XPath и XSLT также не предусмотрено.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Процессор Sablotron</p>
    </title>
    <section>
     <p>Основные данные процессора.</p>
     <p>&#9633; Платформы: С++, Perl, PHP, Python.</p>
     <p>&#9633; Расширения: нет.</p>
     <p>&#9633; Полнота реализации: XSLT 1.0 и XPath 1.0 реализованы не полностью.</p>
     <p>&#9633; Разработчик: Ginger Alliance.</p>
     <p>&#9633; URL: <strong>http://www.gingerall.com</strong>.</p>
     <p>XSLT-процессор Sablotron, разработанный в Ginger Alliance, — это еще один пример весьма успешного open source проекта в области XML-технологий. Sablotron — это библиотека для преобразования XML-документов, которая построена (вернее, почти построена) в соответствии со спецификациями XSLT, XPath и DOM. Процессор Sablotron изначально написан на С++ и компилируется под несколько платформ, в числе которых Linux, Windows 32, Solaris, HP-UX, FreeBSD, OpenBSD, OpenServer и UnixWare. Открытый код также позволяет переносить Sablotron под другие платформы, так что этот список, вполне возможно, будет расширен.</p>
     <p>К сожалению, реализация XSLT и XPath в Sablotron вызывает определенные нарекания. В текущей версии (0.71) Sablotron далеко не полностью поддерживает эти стандарты: например, в путях выборки не работают оси навигации <code>following</code> и <code>preceding</code>, некоторые функции (как то: <code>id</code>, <code>lang</code>, <code>unparsed-entity-uri</code>) не реализованы вообще, многие из функций и элементов реализованы не до конца или работают не в полном соответствии со спецификациями. В общем, соответствие Sablotron стандартам оставляет желать лучшего, хотя и в таком виде он является вполне функциональным процессором.</p>
    </section>
    <section>
     <title>
      <p>Использование</p>
     </title>
     <p>Особую популярность процессору Sablotron'у придает наличие для него расширений под языки Perl, PHP и Python. Долгое время Sablotron был единственным XSLT-процессором, который существовал для Perl, и поэтому Perl-программистам для выполнения XSLT-преобразований не оставалось ничего, кроме как использовать Sablotron.</p>
     <p>Помимо интерфейсов для С++, Perl, Python и PHP, для Sablotron также существует утилита для выполнения преобразований из командной строки <code>sabcmd</code>:</p>
     <p><code>sabcmd stylesheet.xsl source.xml result.xml</code></p>
    </section>
   </section>
   <section>
    <title>
     <p>Процессор xt</p>
    </title>
    <section>
     <p>Характеристики процессора.</p>
     <p>&#9633; Платформы: Java.</p>
     <p>&#9633; Расширения: функции расширения, некоторые элементы расширения.</p>
     <p>&#9633; Полнота реализации: практически полностью реализует XSLT версии PR-xslt-19991008.</p>
     <p>&#9633; Разработчик: Джеймс Кларк (James Clark).</p>
     <p>&#9633; URL: <strong>http://www.jclark.com/xml/xt.html</strong>.</p>
     <p>Без всякого сомнения, xt является легендарным процессором. Он был написан Джеймсом Кларком - человеком, чей вклад в технологию XSLT сложно переоценить. Кларк был редактором первой версии XSLT, а его процессор xt был одним из первых прототипов, реализующих новый язык. На xt практическим способом было проверено, множество идей, касающихся XSLT, ведь мало создать мощный язык — нужно еще и позаботиться о том, чтобы его можно было реализовать на практике в интерпретаторах, процессорах и компиляторах.</p>
     <p>Процессор xt, безусловно, сыграл свою роль в развитии технологии XSLT. К сожалению, Джеймс Кларк более не продолжает этот проект. Версия от 5 ноября 1999 года является последней версией xt. Она все еще доступна на Web-сайте <strong>http://www.jclark.com/xml/xt.html</strong>, но более не поддерживается.</p>
     <p>В последней (если не сказать, финальной) версии xt язык XSLT реализован в почти полном соответствии с версией PR-xslt-19991008. Буквы PR в этом коде означают "proposed recommendation" (англ. предлагаемая рекомендация). PR - это одна из последних стадий принятия нового стандарта в Консорциуме W3, так что можно сказать, что xt реализует почти стандартную версию XSLT. Процессор xt имеет ряд ограничений и недоработок, но уже поздно надеяться, что они будут когда-либо исправлены.</p>
    </section>
    <section>
     <title>
      <p>Использование</p>
     </title>
     <p>Как и любой другой XSLT-процессор, написанный на Java, xt можно без труда использовать в Java-проектах. Помимо этого, xt можно использовать в качестве сервлета и из командной строки.</p>
     <p>Сервлет-версия xt реализована в классе <code>com.jclark.xsl.sax.XSLservlet</code> и может выполняться на контейнерах, поддерживающих Java Servlet API версии 2.1 и выше.</p>
     <p>Версия xt для командной строки позволяет выполнять преобразования посредством следующей команды:</p>
     <p><code>java -Dcom.jdark.xsl.sax.parser=<emphasis>SAX-драйвер</emphasis> com.jclark.xsl.sax.Driver source.xml stylesheet.xsl result.xml</code></p>
     <p>В этой команде параметр SAX-драйвер указывает на класс, который xt будет использовать в качестве SAX-парсера для разбора входящего документа.</p>
     <p>Для платформы Windows32 процессор xt поставляется также в уже скомпилированной версии. Его запуск в этом случае выглядит как</p>
     <p><code>xt source.xml stylesheet.xsl result.xml</code></p>
    </section>
    <section>
     <title>
      <p>Расширения</p>
     </title>
     <p>В xt реализован стандартный метод вызова Java-функций расширения (если быть до конца откровенными, Кларк фактически и придумал этот "стандартный" способ). Функции реализуются в Java-классах, которые затем подключаются при помощи URI пространств имен.</p>
     <p>Сверх этого, xt также реализует несколько дополнительных функций для операций над множествами (<code>xt:node-set</code>, <code>xt:intersection</code> и <code>xt:difference</code>) и дополнительный элемент <code>xt:document</code>, который позволяет выводить результат преобразования сразу в несколько выходящих файлов. Позже эта же концепция была реализована в некоторых других процессорах и перенесена в версию XSLT 1.1.</p>
    </section>
   </section>
   <section>
    <title>
     <p>Библиотека libxslt</p>
    </title>
    <section>
     <p>Основные характеристики.</p>
     <p>&#9633; Платформы: C/Gnome, Perl, Python.</p>
     <p>&#9633; Расширения: функции и элементы расширения.</p>
     <p>&#9633; Полнота реализации: практически полное соответствие XSLT 1.0.</p>
     <p>&#9633; Разработчик: Даниел Вейлард (Daniel Veillard).</p>
     <p>&#9633; URL: <strong>http://xmlsoft.org/XSLT/</strong>.</p>
     <p>Наравне с Saxon и xt, библиотека libxslt является еще одним примером того, насколько сильным может быть open-source продукт, даже если он создается, в основном, одним человеком. Библиотека libxslt изначально создавалась для поддержки XSLT-преобразований в проекте Gnome. Для разбора XML, работы с древовидными структурами и вычисления XPath-выражений libxslt использует другую Gnome-библиотеку: libxml. Библиотека libxslt написана практически на чистом ANSI С (языке С стандарта ANSI) и работает на таких платформах, как Linux, Unix и Windows32.</p>
    </section>
    <section>
     <title>
      <p>Использование</p>
     </title>
     <p>Прежде всего, как C-библиотеку, libxslt можно подключать к собственным модулям посредством документированного API, а также при помощи разработанных врапперов использовать в Perl и Python-программах. Поскольку по степени совместимости и разработанности libxslt явно превосходит Sablotron, думается, что в скором времени он станет гораздо более популярным.</p>
     <p>В libxslt также включена утилита <code>xsltproc</code>, которая обеспечивает для libxslt интерфейс командной строки:</p>
     <p><code>xsltproc -о result.xml stylesheet.xsl source.xml</code></p>
     <p>В языках Perl и Python libxslt используется при помощи модулей <code>XML::LibXSLT</code> и <code>libxsltmod</code> соответственно.</p>
    </section>
    <section>
     <title>
      <p>Расширения</p>
     </title>
     <p>Другим преимуществом libxslt по сравнению с Sablotron является возможность использования расширений, причем как в виде функций, так и в виде элементов. Функции и элементы расширения в libxslt оформляются в виде C-функций, затем регистрируются в процессоре перед вызовом и используются в преобразованиях так же, как и в случае с Java — посредством пространств имен.</p>
     <p>В дополнение к этому, в libxslt по умолчанию также реализовано множество общепринятых расширений — в частности, многие из функций, предложенных в процессоре Saxon и инициативе EXSLT.</p>
    </section>
   </section>
  </section>
  <section>
   <title>
    <p>Приложение 2</p>
    <p>Краткий справочник элементов и атрибутов XSLT</p>
   </title>
   <section>
    <title>
     <p>Обозначения</p>
    </title>
    <p>Ниже перечислены обозначения, используемые в данной книге.</p>
    <p>&#9633; <code><strong>attribute</strong></code></p>
    <p>Обязательный атрибут.</p>
    <p>&#9633; <code>attribute</code></p>
    <p>Необязательный атрибут.</p>
    <p>&#9633; <code>attribute="<emphasis>строка</emphasis>"</code></p>
    <p>Атрибут со строковым параметром.</p>
    <p>&#9633; <code>attribute="{<emphasis>строка</emphasis>}"</code></p>
    <p>Атрибут со строковым параметром, значение которого является шаблоном значения атрибута.</p>
    <p>&#9633; <code>attribute="yes" | "no"</code></p>
    <p>Атрибут с вариантами значений.</p>
    <p>&#9633; <code>attribute={ "yes" | "no" }</code></p>
    <p>Атрибут с вариантами значений, которые могут быть заданы шаблонами значений атрибутов.</p>
    <p>&#9633; <code>&lt;!-- Содержимое: шаблон --&gt;</code></p>
    <p>Содержимым элемента является шаблон.</p>
    <p>&#9633; <code>&lt;!-- Содержимое: несколько элементов xsl:import ... --&gt;</code></p>
    <p>Элемент содержит последовательность из нуля или более элементов <code>xsl:import</code>.</p>
    <p>&#9633; <code>&lt;!-- Содержимое: один или более элемент xsl:when ... --&gt;</code></p>
    <p>Элемент содержит последовательность из одного или более элементов <code>xsl:when</code>.</p>
    <p>&#9633; <code>&lt;!-- Содержимое: ... опциональный элемент xsl:otherwise --&gt;</code></p>
    <p>Элемент содержит элемент <code>xsl:otherwise</code>, который может быть пропущен.</p>
   </section>
   <section>
    <title>
     <p>Элементы</p>
    </title>
    <p>В табл. П2.1 приведены описания основных элементов XSLT.</p>
    <empty-line/>
    <p><emphasis><strong>Таблица П2.1</strong>. Описание основных элементов XSLT</emphasis></p>
    <table>
     <tr>
      <th align="left">Элемент</th>
      <th align="left">Описание</th>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:apply-imports/&gt;</code></td>
      <td align="left">Инструкция. Применяет шаблонные правила, которые содержатся в импортированных преобразованиях</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:apply-templates select="<emphasis>выражение</emphasis>" mode="<emphasis>режим</emphasis>"&gt; &lt;!-- Содержимое: несколько элементов xsl:sort или xsl:with-param --&gt; &lt;/xsl:apply-templates&gt;</code></td>
      <td align="left">Инструкция. Применяет шаблонные правила к множеству узлов, возвращаемому выражением, записанным в атрибуте <code>select</code>. •<code> select</code> — содержит выражение, возвращающее множество узлов для обработки; • <code>mode</code> — указывает режим, в котором должны применяться шаблоны</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:attribute <strong>name</strong>="{<emphasis>имя</emphasis>}"</code></td>
      <td align="left">Инструкция. Создает в выходящем документе узел атрибута. •<code> <strong>name</strong></code> — определяет имя атрибута; •<code> namespace</code> — URI пространства имен создаваемого атрибута</td>
     </tr>
     <tr>
      <td align="left"><code>namespace="{<emphasis>пространство имен</emphasis>}"&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:attribute&gt;</code></td>
      <td/>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:attribute-set <strong>name</strong>="<emphasis>имя</emphasis>" use-attribute-sets="<emphasis>имена</emphasis>"&gt; &lt;!-- Содержимое: несколько элементов xsl:attribute --&gt; &lt;/xsl:attribute-set&gt;</code></td>
      <td align="left">Элемент верхнего уровня. Определяет именованный набор атрибутов. •<code> <strong>name</strong></code> — содержит имя набора атрибутов; •<code> use-attribute-sets</code> — перечисляет через пробелы имена наборов атрибутов, которые следует включить в определяемый набор</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:call-template <strong>name</strong>="<emphasis>имя</emphasis>"&gt; &lt;!-- Содержимое: несколько элементов xsl:with-param --&gt; &lt;/xsl:call-template&gt;</code></td>
      <td align="left">Инструкция. Вызов именованного шаблона. • <code><strong>name</strong></code> — имя вызываемого шаблона</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:choose&gt; &lt;!-- Содержимое: один или более элемент xsl:when, опциональный элемент xsl:otherwise --&gt; &lt;/xsl:choose&gt;</code></td>
      <td align="left">Инструкция. Выполняет содержимое одного из субэлементов в зависимости от условий</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:comment&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:comment&gt;</code></td>
      <td align="left">Инструкция. Создает в выходящем документе узел комментария</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:copy use-attribute-sets="<emphasis>имена</emphasis>"&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:copy&gt;</code></td>
      <td align="left">Инструкция. Создает в выходящем документе копию текущего узла. Копии дочерних узлов не создаются. • <code>use-attribute-sets</code> — перечисляет именованные наборы атрибутов, которые следует добавить в создаваемый узел</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:copy-of <strong>select</strong>="<emphasis>выражение</emphasis>"/&gt;</code></td>
      <td align="left">Инструкция. Копирует в выходящий документ результат вычисления выражения. • <code><strong>select</strong></code> — содержит выражение, результат которого нужно скопировать</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:decimal-format name="<emphasis>имя</emphasis>" decimal-separator="<emphasis>символ</emphasis>" grouping-separator="<emphasis>символ</emphasis>" infinity="<emphasis>строка</emphasis>" minus-sign="<emphasis>символ</emphasis>" NaN="<emphasis>строка</emphasis>" percent="<emphasis>символ</emphasis>" per-mille="<emphasis>символ</emphasis>" zero-digit="<emphasis>символ</emphasis>" digit="<emphasis>символ</emphasis>" pattern-separator="<emphasis>символ</emphasis>"/&gt;</code></td>
      <td align="left">Элемент верхнего уровня. Определяет именованный набор параметров для формата числа. • <code>name</code> — имя. Если <code>name</code> отсутствует, формат числа определяется по умолчанию; • <code>decimal-separator</code> — символ, разделяющий целую и дробную часть; • <code>grouping-separator</code> — символ, разделяющий группы цифр целой части числа; • <code>infinity</code> — строка, соответствующая бесконечности; • <code>minus-sign</code> — символ отрицания; • <code>NaN</code> — строка, соответствующая нечислу; • <code>percent</code> — символ процента; • <code>per-mille</code> — символ промилле; • <code>zero-digit</code> — символ нуля; • <code>digit</code> — символ, помечающий позицию необязательной цифры; • <code>pattern-separator</code> — символ, разделяющий положительный и отрицательный образцы форматирования</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:element <strong>name</strong>="{<emphasis>имя</emphasis>}" namespace="{<emphasis>пространство имен</emphasis>}" use-attribute-sets="<emphasis>имена</emphasis>"&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:element&gt;</code></td>
      <td align="left">Инструкция. Создает в выходящем документе элемент. • <code><strong>name</strong></code> — имя элемента; • <code>namespace</code> — URI пространства имен создаваемого элемента; • <code>use-attribute-sets</code> — перечисляет имена наборов атрибутов, которые надо включить в создаваемый элемент</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:fallback&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:fallback&gt;</code></td>
      <td align="left">Инструкция. Выполняется при невозможности выполнить родительскую инструкцию</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:for-each <strong>select</strong>="выражение"&gt; &lt;!-- Содержимое: несколько элементов xsl:sort, шаблон --&gt; &lt;/xsl:for-each&gt;</code></td>
      <td align="left">Инструкция. Выполняет содержащийся шаблон для каждого из узлов множества. • <code><strong>select</strong></code> — содержит выражение, возвращающее перебираемое множество узлов</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:if <strong>test</strong>="<emphasis>выражение</emphasis>" &gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:if&gt;</code></td>
      <td align="left">Инструкция. Выполняет или не выполняет дочерний шаблон в зависимости от заданного условия. • <code><strong>test</strong></code> — содержит выражение проверяемого условия</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:import <strong>href</strong>="<emphasis>URI</emphasis>"/&gt;</code></td>
      <td align="left">Элемент верхнего уровня. Импортирует указанный шаблон. • <code><strong>href</strong></code> — URI импортируемого шаблона</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:include <strong>href</strong>="<emphasis>URI</emphasis>"/&gt;</code></td>
      <td align="left">Элемент верхнего уровня. Включает указанный шаблон. • <code><strong>href</strong></code> — URI включаемого шаблона</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:key <strong>name</strong>="<emphasis>имя</emphasis>" <strong>match</strong>="<emphasis>паттерн</emphasis>" <strong>use</strong>="<emphasis>выражение</emphasis>"/ &gt;</code></td>
      <td align="left">Элемент верхнего уровня. Определяет именованный ключ. • <code><strong>name</strong></code> — имя ключа; • <code><strong>match</strong></code> — выбирает узлы, для которых будут определяться значения ключа; • <strong>use</strong> — выражение, значение которого будет значением ключа для каждого из узлов</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:message terminate="yes" | "no"&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:message&gt;</code></td>
      <td align="left">Инструкция. Указывает процессору на то, что нужно вывести сообщение. • terminate — определяет, следует ли прервать обработку после вывода сообщения или нет</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:namespace-alias <strong>stylesheet-prefix</strong>="<emphasis>префикс</emphasis>" | "#default" <strong>result-prefix</strong>="<emphasis>префикс</emphasis>" | "#default"/&gt;</code></td>
      <td align="left">Элемент верхнего уровня. Определяет псевдоним для префикса. • <code><strong>stylesheet-prefix</strong></code> — префикс в преобразовании; • <code><strong>result-prefix</strong></code> — префикс в результирующем документе</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:number level="single" | "multiple" | "any" count="<emphasis>паттерн</emphasis>" from="<emphasis>паттерн</emphasis>" value="<emphasis>выражение</emphasis>" format="{<emphasis>строка</emphasis>}" lang="{<emphasis>токен</emphasis>}" letter-value={ "alphabetic" | "traditional" } grouping-separator="{<emphasis>символ</emphasis>}" grouping-size="{<emphasis>число</emphasis>}"/&gt;</code></td>
      <td align="left">Инструкция. Выводит номер в соответствии с заданными критериями. • <code>level</code> — на каких уровнях нумеровать узлы; • <code>count</code> — какие узлы учитывать при нумерации; • <code>from</code> — в какой части документа нумеровать узлы; • <code>value</code> — выражение, вычисляющее номер. • <code>format</code> — форматирующая строка номера; • <code>lang</code> — язык для алфавитных последовательностей; • <code>letter-value</code> — алфавитная или традиционная нумерация; • <code>grouping-separator</code> — разделяющий символ групп цифр номера; •<code> grouping-size</code> — количество цифр в группах цифр номера </td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:otherwise&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:otherwise&gt;</code></td>
      <td align="left">Субэлемент элемента <code>xsl:choose</code>. Выполняется в элементе <code>xsl:choose</code>, если ни одно из других условий не верно.</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:output method="xml" | "html" | "text" | " <emphasis>префикс</emphasis>:<emphasis>имя</emphasis>" version="<emphasis>токен</emphasis>" encodings="<emphasis>строка</emphasis>" omit-xml-declaration="yes" | "no" standalone="yes" | "no" doctype-public="<emphasis>строка</emphasis>" doctype-system="<emphasis>строка</emphasis>" cdata-section-elements="<emphasis>имена</emphasis>" indent="yes" | "no" media-type="<emphasis>строка</emphasis>"/&gt;</code></td>
      <td align="left">Элемент верхнего уровня. Определяет параметры вывода результирующего документа. • <code>method</code> — метод сериализации; • <code>version</code> — версия языка сериализации; • <code>encoding</code> — кодировка выходящего документа; • <code>omit-xml-declaration</code> — опустить декларацию XML; • <code>standalone</code> — самостоятельный или несамостоятельный документ; • <code>doctype-public</code> — публичный идентификатор типа документа; • <code>doctype-system</code> — системный идентификатор типа документа; • <code>cdata-section-elements</code> — элементы, содержимое которых следует выводить как секции CDATA; • <code>indent</code> — индентация (вывод отступов); • <code>media-type</code> — медиа-тип</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:param <strong>name</strong>="<emphasis>имя</emphasis>" select="<emphasis>выражение</emphasis>"&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:param&gt;</code></td>
      <td align="left">Инструкция, элемент верхнего уровня. Определяет параметр преобразования или шаблонного правила. • <code><strong>name</strong></code> — имя параметра; • <code>select</code> — выражение, задающее значение параметра</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:preserve-space <strong>elements</strong>="токены"/&gt;</code></td>
      <td align="left">Элемент верхнего уровня. Определяет элементы входящего документа, в которых следует сохранять текстовые узлы, содержащие только пробельные символы. • <code><strong>elements</strong></code> — перечисляет элементы, в которых пробельные символы должны быть сохранены</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:processing-instruction <strong>name</strong>="{<emphasis>имя</emphasis>}"&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:processing-instruction&gt;</code></td>
      <td align="left">Инструкция. Создает узел инструкции по обработке. • <code><strong>name</strong></code> — определяет имя целевого приложения создаваемой инструкции</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:sort select="<emphasis>выражение</emphasis>" lang="{<emphasis>токен</emphasis>}" data-type={ "text" | "number" | "<emphasis>префикс</emphasis>:<emphasis>имя</emphasis>" } order={ "ascending" | "descending" } case-order={ "upper-first" | "lower-first"}/&gt;</code></td>
      <td align="left">Субэлемент элементов <code>xsl:apply-templates</code> и xsl<code>:for-each</code>. • <code>select</code> — выражения для сортировки; • <code>lang</code> — язык сортировки; • <code>data-type</code> — тип данных сортировки; • <code>order</code> — порядок сортировки; • <code>case-order</code> — упорядоченность строчных и прописных букв</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:strip-space <strong>elements</strong>="<emphasis>токены</emphasis>"/&gt;</code></td>
      <td align="left">Элемент верхнего уровня. Определяет элементы входящего документа, в которых следует удалять текстовые узлы, содержащие только пробельные символы. •<code> <strong>elements</strong></code> — перечисляет элементы, в которых пробельные символы должны быть удалены</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:stylesheet id="<emphasis>идентификатор</emphasis>" extension-element-prefixes="<emphasis>префиксы</emphasis>" exclude-result-prefixes="<emphasis>префиксы</emphasis>" <strong>version</strong>="<emphasis>число</emphasis>"&gt; &lt;!-- Содержимое: несколько элементов xsl:import, элементы верхнего уровня --&gt; &lt;/xsl:stylesheet&gt;</code></td>
      <td align="left">Корневой элемент преобразования. •<code> id</code> — идентификатор преобразования; •<code> extension-element-prefixes</code> — префиксы элементов расширения; •<code> exclude-result-prefixes</code> — префиксы, не включаемые в выходящий документ; •<code> <strong>version</strong></code> — версия языка XSLT</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:template match="<emphasis>паттерн</emphasis>" namе="<emphasis>имя</emphasis>" priority="<emphasis>число</emphasis>" modе="<emphasis>имя</emphasis>"&gt; &lt;!-- Содержимое: несколько элементов xsl:param, шаблон --&gt; &lt;/xsl:template&gt;</code></td>
      <td align="left">Элемент верхнего уровня. Определяет шаблонное правило. •<code> match</code> — содержит паттерн, которому должны удовлетворять узлы, обрабатываемые данным шаблоном; •<code> name</code> — имя шаблона; •<code> priority</code> — приоритет шаблона; •<code> mode</code> — режим шаблона</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:text disable-output-escaping="yes" | "no"&gt; &lt;!-- Содержимое: символьные данные --&gt; &lt;/xsl:text&gt;</code></td>
      <td align="left">Инструкция. Создает в выходящем документе текстовый узел. Пробельные символы, находящиеся внутри <code>xsl:text</code>, не удаляются. • <code>disable-output-escaping</code> — определяет, должны ли в выходящем документе особые символы этого текстового узла заменяться на сущности</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:transform id="<emphasis>идентификатор</emphasis>" extension-element-prefixes="<emphasis>префиксы</emphasis>" exclude-result-prefixes="<emphasis>префиксы</emphasis>" <strong>version</strong>="<emphasis>число</emphasis>"&gt; &lt;!-- Содержимое: несколько элементов xsl:import, элементы верхнего уровня --&gt; &lt;/xsl:transform&gt;</code></td>
      <td align="left">Корневой документ преобразования. Псевдоним элемента <code>xsl:stylesheet</code></td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:value-of <strong>select</strong>="<emphasis>выражение</emphasis>" disable-output-escaping="yes" | "no"/&gt;</code></td>
      <td align="left">Инструкция. Создает в выходящем документе текстовый узел, содержащий результат вычисления выражения, приведенный к строке. • <code><strong>select</strong></code> — содержит вычисляемое выражение; • <code>disable-output-escaping</code> — определяет, должны ли в выходящем документе особые символы этого текстового узла заменяться на сущности</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:variable <strong>name</strong>="<emphasis>имя</emphasis>" select="<emphasis>выражение</emphasis>" &gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:variable&gt;</code></td>
      <td align="left">Инструкция, элемент верхнего уровня. Создает глобальную или локальную переменную. Значение переменной не может быть изменено. • <code><strong>name</strong></code> — задает имя определяемой переменной; • <code>select</code> — задает значение определяемой переменной</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:when <strong>test</strong>="<emphasis>выражение</emphasis>"&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:when&gt;</code></td>
      <td align="left">Субэлемент элемента <code>xsl:choose</code>. Выполняется один из вариантов в блоке <code>xsl:choose</code> в зависимости от условия. • <code><strong>test</strong></code> — задает выражение логического условия</td>
     </tr>
     <tr>
      <td align="left"><code>&lt;xsl:with-param <strong>name</strong>="<emphasis>имя</emphasis>" select="<emphasis>выражение</emphasis>"&gt; &lt;!-- Содержимое: шаблон --&gt; &lt;/xsl:with-param&gt;</code></td>
      <td align="left">Субэлемент элементов <code>xsl:apply- templates</code>, <code>xsl:call-template</code>. Задает значение одного параметра при вызове параметризованного шаблона. • <code><strong>name</strong></code> — имя параметра; • <code>select</code> — выражение, значение которого должно быть передано как параметр. В случае, если атрибут <code>select</code> не определен, значением передаваемого параметра является дерево, полученное в результате выполнения содержимого <code>xsl:with-param</code>. Если элемент при этом пуст, значением параметра является пустая строка</td>
     </tr>
    </table>
   </section>
   <section>
    <title>
     <p>Атрибуты</p>
    </title>
    <p>Сведения об атрибутах XSLT представлены в табл. П2.2.</p>
    <empty-line/>
    <p><emphasis><strong>Таблица П2.2</strong>. Атрибуты XSLT</emphasis></p>
    <table>
     <tr>
      <th align="left">Атрибут</th>
      <th align="left">Назначение</th>
     </tr>
     <tr>
      <td align="left"><code>xsl:version</code></td>
      <td align="left">Указывает версию языка в случае использования упрощенного синтаксиса записи преобразований</td>
     </tr>
     <tr>
      <td align="left"><code>xsl:exclude-result-prefixes</code></td>
      <td align="left">Перечисляет префиксы пространств имен, которые должны быть исключены в данном элементе</td>
     </tr>
     <tr>
      <td align="left"><code>xsl:extension-elements-prefixes</code></td>
      <td align="left">Перечисляет префиксы пространств имен, которые используются в элементах расширения</td>
     </tr>
     <tr>
      <td align="left"><code>xsl:use-attribute-sets</code></td>
      <td align="left">Перечисляет названия именованных наборов атрибутов, которые следует включить в данный элемент на выходе</td>
     </tr>
    </table>
   </section>
  </section>
  <section>
   <title>
    <p>Приложение 3</p>
    <p>Краткий справочник функций XSLT и XPath</p>
   </title>
   <section>
    <title>
     <p>Обозначения</p>
    </title>
    <p>Прототип функции имеет следующий синтаксис:</p>
    <p><code><emphasis>тип1 </emphasis><strong>функция</strong>(<emphasis>тип2</emphasis>, <emphasis>тип3</emphasis>, <emphasis>тип4</emphasis>?)</code></p>
    <p>Здесь <emphasis>тип1</emphasis> — тип возвращаемого значения, <emphasis>тип2</emphasis>, <emphasis>тип3</emphasis>, <emphasis>тип4</emphasis> — типы передаваемых параметров.</p>
    <p>При этом символ "<code>?</code>" обозначает аргумент, который может быть опущен, а символ <code>*</code> служит для обозначения аргумента, который может повторяться несколько раз.</p>
   </section>
   <section>
    <title>
     <p>Функции</p>
    </title>
    <p>В табл. П3.1–П3.5 представлено описание наиболее часто используемых функций.</p>
    <empty-line/>
    <p><emphasis><strong>Таблица П3.1</strong>. Булевые функции</emphasis></p>
    <table>
     <tr>
      <th align="left">Функция</th>
      <th align="left">Описание</th>
     </tr>
     <tr>
      <td align="left"><code><emphasis>boolean </emphasis><strong>boolean</strong>(<emphasis>object</emphasis>)</code></td>
      <td align="left">Явным образом преобразует объект, который ей передается в булевый тип</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>boolean </emphasis><strong>not</strong>(<emphasis>boolean</emphasis>)</code></td>
      <td align="left">Выполняет логическое отрицание</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>boolean </emphasis><strong>true</strong>()</code></td>
      <td align="left">Возвращает <code>true</code>, "истину"</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>boolean </emphasis><strong>false</strong>()</code></td>
      <td align="left">Возвращает <code>false</code>, "ложь"</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>boolean </emphasis><strong>lang</strong>(<emphasis>string</emphasis>)</code></td>
      <td align="left">Возвращает "истину", если идентификатор языка, который передан ей в виде строкового параметра, соответствует языковому контексту контекстного узла</td>
     </tr>
    </table>
    <empty-line/>
    <p><emphasis><strong>Таблица П3.2</strong>. Числовые функции</emphasis></p>
    <table>
     <tr>
      <th align="left">Функция</th>
      <th align="left">Описание</th>
     </tr>
     <tr>
      <td align="left"><code><emphasis>number </emphasis><strong>number</strong>(<emphasis>object</emphasis>?)</code></td>
      <td align="left">Явным образом конвертирует свой аргумент в числовой тип. Если аргумент опущен, то выполняется с множеством, состоящим из контекстного узла</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>number </emphasis><strong>sum</strong>(<emphasis>node-set</emphasis>)</code></td>
      <td align="left">Суммирует значения узлов из переданного ей множества</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>number </emphasis><strong>floor</strong>(<emphasis>number</emphasis>)</code></td>
      <td align="left">Округляет аргумент до ближайшего не большего целого</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>number </emphasis><strong>ceiling</strong>(<emphasis>number</emphasis>)</code></td>
      <td align="left">Округляет аргумент до ближайшего не меньшего целого</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>number </emphasis><strong>round</strong>(<emphasis>number</emphasis>)</code></td>
      <td align="left">Округляет аргумент до ближайшего целого значения</td>
     </tr>
    </table>
    <empty-line/>
    <p><emphasis><strong>Таблица П3.3</strong>. Строковые функции</emphasis></p>
    <table>
     <tr>
      <th align="left">Функция</th>
      <th align="left">Описание</th>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>string</strong>(<emphasis>object</emphasis>?)</code></td>
      <td align="left">Преобразует свой аргумент к строковому типу явным образом. Если аргумент опущен, то выполняется с множеством, состоящим из контекстного узла</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>concat</strong>(<emphasis>string</emphasis>, <emphasis>string</emphasis>, <emphasis>string</emphasis>*)</code></td>
      <td align="left">Возвращает конкатенацию (строковое сложение) своих аргументов</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>boolean </emphasis><strong>starts-with</strong> (<emphasis>string</emphasis>, <emphasis>string</emphasis>)</code></td>
      <td align="left">Принимает на вход два строковых аргумента и возвращает <code>true</code>, если первая строка начинается со второй и <code>false</code> в противном случае</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>boolean </emphasis><strong>contains</strong> (<emphasis>string</emphasis>, <emphasis>string</emphasis>)</code></td>
      <td align="left">Принимает на вход два строковых аргумента и возвращает <code>true</code>, если первая строка содержит вторую и <code>false</code> в противном случае</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>substring-before</strong>(<emphasis>string</emphasis>, <emphasis>string</emphasis>)</code></td>
      <td align="left">Принимает на вход два строковых аргумента, находит в первой строке вторую и возвращает подстроку, которая ей предшествует</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>substring-after</strong>(<emphasis>string</emphasis>, <emphasis>string</emphasis>)</code></td>
      <td align="left">Принимает на вход два строковых аргумента, находит в первой строке вторую и возвращает подстроку, которая за ней следует</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>substring</strong>(<emphasis>string</emphasis>, <emphasis>number</emphasis>, <emphasis>number</emphasis>?)</code></td>
      <td align="left">Возвращает подстроку переданного ей строкового аргумента, которая начинается с позиции, указанной вторым аргументом и длиной, указанной третьим аргументом. Если третий аргумент не указан, то подстрока продолжается до конца строки</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>number </emphasis><strong>string-length</strong>(<emphasis>string</emphasis>?)</code></td>
      <td align="left">Возвращает число символов строкового аргумента</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>normalize-space</strong>(<emphasis>string</emphasis>?)</code></td>
      <td align="left">Производит со строковым аргументом нормализацию пробельного пространства. Если аргумент опущен, выполняется со строковым значением контекстного узла</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>translate</strong> (<emphasis>string</emphasis>, <emphasis>string</emphasis>, <emphasis>string</emphasis>)</code></td>
      <td align="left">Производит замену символов первого своего строкового аргумента, которые присутствуют во втором аргументе на соответствующие символы третьего аргумента</td>
     </tr>
    </table>
    <empty-line/>
    <p><emphasis><strong>Таблица П3.4</strong>. Функции множеств узлов</emphasis></p>
    <table>
     <tr>
      <th align="left">Функция</th>
      <th align="left">Описание</th>
     </tr>
     <tr>
      <td align="left"><code><emphasis>number </emphasis><strong>last</strong>()</code></td>
      <td align="left">Возвращает размер контекста вычисления выражения</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>number </emphasis><strong>position</strong>()</code></td>
      <td align="left">Возвращает позицию контекста вычисления выражения</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>number </emphasis><strong>count</strong>(<emphasis>node-set</emphasis>)</code></td>
      <td align="left">Возвращает число узлов, которое входит во множество, переданное ей в качестве аргумента</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>local-name</strong>(<emphasis>node-set</emphasis>?)</code></td>
      <td align="left">Возвращает локальную часть имени первого в порядке просмотра документа узла множества, переданного в качестве аргумента или локальную часть имени контекстного узла, если аргумент отсутствует. Если аргумент опущен, то выполняется с множеством, состоящим из контекстного узла</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>namespace-uri</strong>(<emphasis>node-set</emphasis>?)</code></td>
      <td align="left">Возвращает URI пространства имен первого в порядке просмотра документа узла множества, переданного в качестве аргумента или локальную часть имени контекстного узла, если аргумент отсутствует. Если аргумент опущен, то выполняется с множеством, состоящим из контекстного узла</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>name</strong>(<emphasis>node-set</emphasis>?)</code></td>
      <td align="left">Возвращает в виде <code><emphasis>префикс</emphasis>:<emphasis>имя</emphasis></code> расширенное имя локальную часть имени первого в порядке просмотра документа узла множества, переданного в качестве аргумента или локальную часть имени контекстного узла, если аргумент отсутствует. Если аргумент опущен, то выполняется с множеством, состоящим из контекстного узла</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>node-set </emphasis><strong>id</strong>(<emphasis>object</emphasis>)</code></td>
      <td align="left">Возвращает множество узлов по уникальным идентификаторам</td>
     </tr>
    </table>
    <empty-line/>
    <p><emphasis><strong>Таблица П3.5</strong>. Другие функции</emphasis></p>
    <table>
     <tr>
      <th align="left">Функция</th>
      <th align="left">Описание</th>
     </tr>
     <tr>
      <td align="left"><code><emphasis>node-set </emphasis><strong>key</strong>(<emphasis>string</emphasis>, <emphasis>object</emphasis>)</code></td>
      <td align="left">По данному имени и значению ключа возвращает множество узлов, которые им обладают</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>node-set </emphasis><strong>document</strong>(<emphasis>object</emphasis>, <emphasis>node-set</emphasis>?)</code></td>
      <td align="left">Позволяет обращаться к внешним документам по заданным URI. Первый узел необязательного параметра <code>node-set</code> принимается за точку отсчета для относительных URI</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>node-set</emphasis> <strong>current</strong>()</code></td>
      <td align="left">Возвращает текущий узел преобразования</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>unparsed-entity-uri</strong>(<emphasis>string</emphasis>)</code></td>
      <td align="left">Возвращает URI неразбираемой сущности по ее имени</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>string </emphasis><strong>generate-id</strong>(<emphasis>node-set</emphasis>?)</code></td>
      <td align="left">Возвращает уникальный строковый идентификатор первого узла переданного множества или контекстного узла, если аргумент опущен</td>
     </tr>
     <tr>
      <td align="left"><code><emphasis>object </emphasis><strong>system-property</strong>(<emphasis>string</emphasis>)</code></td>
      <td align="left">Возвращает значение свойства, имя которого передано как аргумент</td>
     </tr>
    </table>
   </section>
  </section>
  <section>
   <title>
    <p>Приложение 4</p>
    <p>Интернет-ресурсы, посвященные XSLT</p>
   </title>
   <section>
    <title>
     <p>Зарубежные интернет-ресурсы по XSLT</p>
    </title>
    <p>&#9633; <strong>http://www.dpawson.co.uk/xsl/sect2/sect21.html</strong></p>
    <p>XSLT Questions and Answers. Большой архив вопросов и ответов по XSLT.</p>
    <p>&#9633; <strong>http://www.zvon.org</strong></p>
    <p>The Guide to the XML Galaxy. Большой репозитарий примеров, уроков и материалов для изучения XML-технологий и, в частности, XSLT.</p>
    <p>&#9633; <strong>http://www.datapower.com/XSLTMark/res_2001_04_01.html</strong></p>
    <p>XSLT Benchmarking. Тесты эффективности различных XSLT-процессоров.</p>
    <p>&#9633; <strong>http://www.tfi-technology.com/xml/xslbench.html</strong></p>
    <p>XSLT Processor Benchmarking. Тесты эффективности различных XSLT-процессоров.</p>
    <p>&#9633; <strong>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk30/htm/xmconxsltfaq.asp?frame=true</strong></p>
    <p>Microsoft MSXML 3.0</p>
    <p>XSLT Developer's Guide: XSLT FAQ. Вопросы и ответы об XSLT-разработке на основе библиотеки MSXML.</p>
    <p>&#9633; <strong>http://www.netcrucible.com/xslt/msxml-faq.htm</strong></p>
    <p>Unofficial MSXML XSLT FAQ. Неофициальный список вопросов и ответов по реализации XSLT в библиотеке MSXML.</p>
    <p>&#9633; <strong>http://www.ibiblio.org/xml/books/bible2/chapters/ch17.html</strong></p>
    <p>Chapter 17 of the XML Bible: XSL Transformations. Глава, посвященная XSLT из популярной книги "Библия XML".</p>
    <p>&#9633; <strong>http://www.biglist.com/lists/xsl-list/archives/</strong></p>
    <p>XSL Mailing List archives. Архив сообщений списка рассылки XSL Mailing List.</p>
    <p>&#9633; <strong>http://www.oasis-open.org/cover/xsl.html</strong></p>
    <p>The XML Cover Pages. Extensible Stylesheet Language (XSL). Сжатая информация и большой список ресурсов, посвященных XSLT.</p>
    <p>&#9633; <strong>http://www.dpawson.co.uk/xsl/xslvocab.html</strong></p>
    <p>XSLT Terminology. Глоссарий XSLT.</p>
    <p>&#9633; <strong>http://www.w3schools.com/xsl/</strong></p>
    <p>W3C XSL School. Школа Консорциума W3.</p>
    <p>&#9633; <strong>http://incrementaldevelopment.com/xsltrick/</strong></p>
    <p>XSLT and XPath tips and tricks. Приемы и методы работы с XSLT и XPath.</p>
    <p>&#9633; <strong>http://www.xml.org/xml/resources_focus_xslt.shtml</strong></p>
    <p>XSL, XSLT and XPath resources. Большой перечень ресурсов, посвященных XSL, XSLT и XPath.</p>
   </section>
   <section>
    <title>
     <p>Русскоязычные ресурсы</p>
    </title>
    <p>&#9633; <strong>http://xmlhack.ru</strong></p>
    <p>Новости и ресурсы для XML-разработчиков.</p>
    <p>&#9633; <strong>http://www.xml.nsu.ru</strong></p>
    <p>Школы Консорциума W3 на русском языке.</p>
    <p>&#9633; <strong>http://citforum.ru/internet/xml.shtml</strong></p>
    <p>Ресурсы XML на CITForum.</p>
    <p>&#9633; <strong>http://www.sinor.ru/~xml</strong></p>
    <p>Подборка XML-ресурсов.</p>
   </section>
   <section>
    <title>
     <p>Технические рекомендации и стандарты</p>
    </title>
    <p>&#9633; <strong>http://www.w3.org/TR/xslt</strong></p>
    <p>XSL Transformations (XSLT). Version 1.0. Спецификация языка XSLT.</p>
    <p>&#9633; <strong>http://www.w3.org/TR/XPath</strong></p>
    <p>XML Path Language (XPath). Version 1.0. Спецификация языка XPath.</p>
    <p>&#9633; <strong>http://www.w3.org/TR/REC-xml</strong></p>
    <p>Extensible Markup Language (XML) 1.0 (Second Edition). Спецификация языка XML.</p>
    <p>&#9633; <strong>http://www.w3.org/TR/1999/REC-xml-names-19990114</strong></p>
    <p>Namespaces in XML. Спецификация пространств имен XML.</p>
    <p>&#9633; <strong>http://www.w3.org/TR/xml-stylesheet/</strong></p>
    <p>Associating Style Sheets with XML documents. Version 1.0. Ассоциация преобразований с XML-документами.</p>
    <p>&#9633; <strong>http://www.unicode.org/charts/</strong></p>
    <p>Unicode Code Charts. Таблицы символов Unicode.</p>
   </section>
   <section>
    <title>
     <p>Переводы стандартов на русский язык</p>
    </title>
    <p>&#9633; <strong>http://www.rol.ru/news/it/helpdesk/xml01.htm</strong></p>
    <p>Расширяемый язык разметки (XML) 1.0 (вторая редакция). Перевод Радика Усманова, Luxoft (IBS).</p>
    <p>&#9633; <strong>http://www.rol.ru/news/it/helpdesk/xslt01.htm</strong></p>
    <p>Язык преобразований XSL (XSLT). Версия 1.0. Перевод Радика Усманова, Luxoft (IBS).</p>
    <p>&#9633; <strong>http://www.tkachenko.org/xpath/REC-xpath-19991116-ru.html</strong></p>
    <p>Язык XML Path (XPath). Версия 1.0. Перевод Олега Ткаченко (Multiconn International).</p>
    <p>&#9633; <strong>http://www.rol.ru/news/it/helpdesk/xpath01.htm</strong></p>
    <p>Язык XML Path (XPath). Версия 1.0. Перевод Радика Усманова, Luxoft (IBS).</p>
    <p>&#9633; <strong>http://www.rol.ru/news/it/helpdesk/xnamsps.htm</strong></p>
    <p>Пространства имен в XML. Перевод Радика Усманова, Luxoft (IBS).</p>
   </section>
   <section>
    <title>
     <p>Другие ресурсы</p>
    </title>
    <section>
     <title>
      <p>Списки рассылки</p>
     </title>
     <p>&#9633; <strong>http://www.mulberrytech.com/xsl/xsl-list/index.html</strong></p>
     <p>XSL List</p>
     <p>&#9633; Open Forum on XSL</p>
     <p>Самый авторитетный список рассылки на тему XSL, XSLT и сопутствующих технологий.</p>
    </section>
    <section>
     <title>
      <p>Электронные конференции</p>
     </title>
     <p>&#9633; <strong>comp.text.xml</strong></p>
     <p>Международная конференция, посвященная XML-технологиям.</p>
     <p>&#9633; <strong>fido7.ru.xml</strong></p>
     <p>Русская конференция, посвященная XML-технологиям.</p>
    </section>
   </section>
  </section>
  <section>
   <title>
    <p>Список литературы</p>
   </title>
   <p>1. <emphasis><strong>Бен-Ари 2000</strong></emphasis></p>
   <p>Бен-Ари М. Языки программирования. Практический сравнительный анализ. — М.: Мир, 2000. — 366 с.</p>
   <p>2. <emphasis><strong>Бредли 1998</strong></emphasis></p>
   <p>Bradley N. The XML companion. — Addison Wesley Longman Limited, 1998. — 440 c.</p>
   <p>3. <emphasis><strong>Дейт 1999</strong></emphasis></p>
   <p>Дейт К. Введение в системы баз данных. — СПб.: Издательский дом "Вильямс", 1999. — 848 с.</p>
   <p>4. <emphasis><strong>Кей 2001</strong></emphasis></p>
   <p>Kay М. XSLT Programmer's Reference. — WROX Press, 2001. — 939 с.</p>
   <p>5. <emphasis><strong>Кнут 2000</strong></emphasis></p>
   <p>Кнут Д. Искусство программирования. Т. 1. Основные алгоритмы. — М.: Издательский дом "Вильямс", 2000. — 720 с.</p>
   <p>6. <emphasis><strong>Кормен и др. 2000</strong></emphasis></p>
   <p>Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. — М.: МЦНМО, 2000. — 960 с.</p>
   <p>7. <emphasis><strong>Мюнх 2000</strong></emphasis></p>
   <p>Muench S. Building Oracle XML Applications. — O'Reilly &amp; Associates, 2000. — 775 c.</p>
  </section>
 </body>
 <binary id="img_0.jpeg" content-type="image/jpeg">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</binary>
 <binary id="img_1.png" content-type="image/png">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
MDQ6MjIrMDA6MDCAP1hcAAAAAElFTkSuQmCC</binary>
 <binary id="img_2.png" content-type="image/png">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
AElFTkSuQmCC</binary>
 <binary id="img_3.png" content-type="image/png">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
AAAASUVORK5CYII=</binary>
 <binary id="img_4.png" content-type="image/png">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
k8o1b/U627ie49Le+C+x33SMJ5yovaTDvyfZgnIzSXvbrLOLbbFNpo5qbe5eof0Z1dwjeVtl
2dZNRGvBwMmJGhQb6PZ2FsY9grk79rqG6m/K3NosoLpFGUGYPuY8qmnj4pO1hPzyqeimhlc7
YxWjZUs/RdzOubSdWTsT+rtMI5CsW1QNODR46XTrGer0KX9efg0j/XpPUz7VUz3VUz3VL6lu
vbApn+qpnuqpfiH181Kbm+qpfn41qQWcXwOnEbzQ72Xuc5A4TfVLo0dwAyrhMeQnquF77GZa
bRib6kfiW9/rvet3xFF67fyeZKnb1pYr5X56Xe8uzpf+2V5dnlcep9fNXy3vPDrRXL0w33mU
Qb9t60L98uL83P0M+mfer1Eubs+1q9l04fbq4k4v9fY2Rlu/WN65d29rdWlHSa+Neufc9qy9
xZa2y6m1c2fnb9++8uBhD5giLQhDy3gny7Q6aWJolUP/H0iBhdYIpEmLAAAAJXRFWHRjcmVh
dGUtZGF0ZQAyMDEyLTA0LTEwVDA4OjA0OjIyKzAwOjAw344uaAAAACV0RVh0bW9kaWZ5LWRh
dGUAMjAxMi0wNC0xMFQwODowNDoyMiswMDowMIA/WFwAAAAASUVORK5CYII=</binary>
 <binary id="img_5.png" content-type="image/png">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
YII=</binary>
 <binary id="img_6.png" content-type="image/png">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
OjIyKzAwOjAwgD9YXAAAAABJRU5ErkJggg==</binary>
 <binary id="img_7.png" content-type="image/png">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</binary>
 <binary id="img_8.png" content-type="image/png">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</binary>
 <binary id="img_9.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAf8AAAC1AQAAAAB5PsutAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAf8AAAC1AM7TR4wAAASJSURBVGje7dlPbNtUGADw
14bBxCSiwoH1skzTJE4IZUHisIN7RUKIU4V62cQmoEKjBya2Um3O/pQWqWgITWNlgC+Tdh2X
lhOGkq0IVfg+BE4bNB+QSLKINl2S9/FsJ/4T+9l+/jp1k/JJflLtvl++7/nFfnYIJAlCcpwj
lCTqjgRktmkYAKodHLB5dx0H1L9p4IDpNSxQQwKbX2CBu0eRpxGw82AAPAaAvBMA7Dqw+2OA
BtBjMADYvWXXgV0dA2oC2gAABQk0c0hgThUASBZoH0AlOTlAj9UIM/wAFQHM/9X6gPMgAJw6
GgDgnAhw4kgQmBEBPgoCUkEIGA4CyyLA5HNB4IoIcO7fnH/qM0ARAdiY+QG22pdQAAC3/wAY
AANgAAgCNCcM9EUSoCnjAHZDzfCB+DGgWafSMECNBWpmU+ECEAsYZtNGALrVul2rooDqAtTc
G3UzigNsg7suY6eLDAUBxfpD6o5B29kVDMMZLB9wy2y2HeCP03yg/UoY8IPZrDpA5TAXuH/y
TT0EUNk0bEoOcD8CePdvJQxoknYGegBsvMoHni6FAgAZcIHfxnsAcSPTzWCMA4AH+PMvqQvI
wRIm9HjADA5g0NZqSqBlAxA6D3YSgIPZTlQJ8UC1THAZQPQgPnEAYIH4DH4RBKAfUAvfav1A
1BUpAPy4Z34uGvAn4S3hgQ0Ul71A1VvCFtuWXst6+ssOoFq3ow3y9X8Xv3IAdqQM9lXZAswb
1oKhLGpGwc6OPuNkyPKuX3rnS7KSn7/iAkVCegC0yUqRdfv9JWX/52PzebaHHe0CZevaXr89
fISwohRvCZVesjrbGmzTbl2fmCRrl+0Mct4MarfJ86HzwPfsfXX5u4mX985fhm3/WWBdaP7Q
tfiZuJSHtxeGD+X7gd5pjAW6lRi8eeDt4wMCIZqBGIDOwA9QcYBbgpQKSJGB5+No96c1NTVg
NjrUJD5QjwFkE8hFAJ9FA79+zAAavJjZALtE1FrRQIWtLvR2cCAdwNiKBh4cNDPo2Ls8ebQS
Au0N65rSTTOwQmFfKkOLBu69ZR5ouLunW+wji2vVHrClRwPWgpO+B+FhAmoQUL2AFVN8oCEn
ARQ+0AoBoA9Y5S7WGdCEIGBnIDvAT9xXpWXfYp0L6MCP5kwIoLnVt0EkesC62VQQAH0Roh4v
4wHYGIKfU/T3PvoSGRAlpI7HF9CfRMBI2oUHaNgMlAIS+LRwDFfCjdEsDrh+wwukKGHlhRwu
A3+kyGCHAUwJ1n098Xg4QFPzAsH1TTxwp1p2gawsDLRKJw47AJXFgYezH7zhAjRpf8/7xD3/
PCs7QEcc2HR3QW85JATAzgJnsMAUFlBRwEwu6sE7AUDGEr7N5ABiMQAeDZDFAqfMJvH3OQjQ
6eHS2fz+76eU1AAZKpb2PnUyWSkhJUwy4M7FoeOpgeyl0vsjxeX11ABbqwr8RhEKdJJflB/N
TFSTFxAK1BYtQEoNbC/KI3NL0wfSAxfOj4/czHyYGqjPfjI+WswcTw1szh4go8V96QGAhddb
VG4gAPvtGwpIHvR/9qeNYGZbbAUAAAAldEVYdGNyZWF0ZS1kYXRlADIwMTItMDQtMTBUMDg6
MDQ6MjIrMDA6MDDfji5oAAAAJXRFWHRtb2RpZnktZGF0ZQAyMDEyLTA0LTEwVDA4OjA0OjIy
KzAwOjAwgD9YXAAAAABJRU5ErkJggg==</binary>
 <binary id="img_10.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAf8AAAEQAQAAAACWmEBEAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAf8AAAEQABxhZRcAAAhKSURBVHja3ZxfbNNGHMfN
GNAHUAvVNgRMaQvqMzRorGNbJrWT9gDjfXsATVEAocIEUxkvuKUdLRJ/1vZhZC31hjQe0UYr
tqljQetGQUso2sO0roW0alE1Cep0kbCjuL75T5zYvrv4zldC2SFIk9if3Pfjn8/2xYUD/pok
ASBqjyrnb30lGImE47ej0TqfgAXrB1wPsq7nJ3EkmUv01DbGz3RV1tSGG7kzXcGamvCu2xfX
rqtpbCw7oz+819lVWWc8dNVtRgGGmucS45oV3UlyCByPzCXu9+b6kZWaDz+6Pz4UdPfcFiHp
K7qnA2KUTAfIfzDIxCyAzwiZj7M7h+kdqHmAcvTaxs0sDpTmU2X7cw54H+svZF479Y4JSMoh
is8tAE5/2bDfdJANqeSEQhsBAWA6SM+3b+vwacKIkJ7Z3h4kXBxZyunJrRwLAGSvbD1NCkBF
AHJVO7eKxYGaPn/iAosDAGLaHwYHbI1yd0Y6oFl8KQ1pPiMsIQegACitAziCUmIHcFOeuYOl
UMrPmQMFAVjUCClOa3RDvBMwqQOWMzgQ9X+ygKY5HYg6ugBYIAA4I8yFgzeL9sBrdxZ3jw9T
AlwONmXTlA6cu7PYv1OiBDgdiIFeicnB3O7f09QO7O/Phdcfp47gcKB+SltIMl0lMpeylwNP
AEkElUM0ZgDPGmHRACQRyHqQb4pPwOI5UJ6VA9pSXjQHqAilBZSklJd913Ii5jfCqLUzhigA
grMH5mVwDAMgiEALgCPMPdiLB3g50Hswc3YvTQ+g3Vmd1wGAGAA7mI8zRphvoQS4I8x0U0WA
BhT17roG1joYZnNg/ODXwaifUnZLRH4OnQPKCMwAgQbwFHZnpcQOUANKaR0wR0ABkqwRmAFL
y8GkdVLq14EvgGtRdAR8k8kAkANMKeMASoA2gqspISxAIYqghgCukTnIA1A9EMx5B74ogMcC
dAcqF8qmlhcDFDnd1yOk9A5O8iQAlIMkML8bCBQDQD23l3LO0KxfgDU3lCYBoCJYsEwBQDQb
pOgLLdNLOePolA6YNN8rHiFlXpFqDuAeiI5lMQAjssoXHEyRAGxNMgGag4y5Fc4VAHNNM949
kH564V8DIGSMOpDfsvVg10MCwKWzR80ImRSvvdJikyhu+s0LoEW4NPFRLoLKrVK5cjug711r
2RbkRbwBaJ2oMQDJjLYtuXL7ZhRffcnaKs5ZgJA9QtfEZQ2gmHVQ7qiDud3bree8I0HMDrgx
0c2bDhzxDMDD7QE0wB5BAwRMBxBA1EcQT4C2bCDnAAYAggjG0loEgRUAaADOCFYpOwGcvk1p
AAIGkCGN4JIIWB0UBxA4oO2B7DuCOQijHcySRDCnGbSdCRFBogAUIgB/AIUOYPuCIms5YIzg
7UCaV/cQObB9ogOQ3vdzedEITkDADlADGkDeEwudP3a9/u62PKAD40C2HxFV8wDLA2U6Flpd
PVjBVRkRFGuOFuEgD5DsADkVqz94dnBV/VUkwF0HRgSrErVTDw1wMvbjwfODHQbAjCAgHQCc
xMYvQk3t7RXcV+R14NgXpOq22IFtw/W/VmM2I0khZfTFZ4nqAA2w3mMv5QVWAKEDugGFxEEe
4L0veABslyOLN6QBeEQCWEDhhiasA2Mnugm8D20GAHFkUqxJ2TaSCDLswDpbT1WSADgADesW
oFVCAVybMfUmgIZ1Jd4n6ICQSOBgOAOgCMqUCeCTBBGSaQCVspLuNHsgkABmET3IAWLmwq4z
VZeDURFApaxMXTYB5me7zpVdDsRRANdBwgT0A49mAAREhAfX23TABAlgNgaU/Flarqn6LWsa
YAy5liuCxAMVV4njJD14wiMi5ADTJIAUADKmB5jrTmcEcR4ABXW2rm+9gBdANm9VUN2XvlYE
0qa4L759AHKX/yMkgAUEQDAnIKypIkKAYw7FvPAEJABkBA3Cg/xmowckjQmH/LkRfQQNAFKF
e09oJTJPB0JzafQOBBoA84wmqpCYI/gDOKcD2R2MkDrARbDd6+vPQeyG6D+C7qB/fRubg474
NBkAF6F7NWEP4GbO7v/wfqX/CDqghWN0MBIAZACcA/sLRQEqApCkARDc3LdIEUKMAGuenAgg
ADB17uqNPTaAuhIHwDj4Z8WVSwHbIpPYXzrBRHjcXtUq2ACzXlPCEGDLlupyG0DE3paF+Ybj
5oorLUfsPUiTAwwHNy/o33kXANIsZYSky7Mk0gCSrhe0v+kkdnFEBAFeJCvgAASHNv2dbIjS
AQTgGRws2JP6iaDgvh3BAOAv6zxutnU3vzc844/OhOvhHdC2Rbhv3V90fCl7dPjpOyjy9SzO
QdIJLJ4IM6TZWjYjDFyYH3l9/NBfZAC3g2xmzdftn5+q+PDQPX8OstkXqwZf3rCpoeweTwhw
OsiOr1727StvVDSUrUMBvO4/0IAbm74Z/LP7lw8OEALgzVg+1TF/qwLIMpkDVCnHJLJ1cz0Q
YAB+8ZLszjE6AOQg0SeQrIcf0qb6hGnhbfXIBb8O0p3C1JoN4dpzoz4dpDv7H4f/aOQm9vgE
TF3ub/rk1oqqsXKyCJCD+LWOO/sin60kBUAOHlxva12zfzCk8D4jaO1S4YTHu8nIURkLYB7W
n8K+wPzrSItwdI75Ath6UFoHBKVM74AxwrN38L8o5efeAXMdlLqUUTMYpXWgQj9QOoABS2Ez
MjqgLOXCer1DO4z/MeNvbnR84HjkUfxOtDIY0R6jvcFjkcOJeLRHexpP6A9h7c21dTWNuzqj
XXlUz0CwNhyOn7nIzUR7asONibHoQLA58igR7dXe0dYc6/3eeDq0I3I4PtYLpCdi/D4Ygvv0
H6RcG0W5/IqEAAAAJXRFWHRjcmVhdGUtZGF0ZQAyMDEyLTA0LTEwVDA4OjA0OjIyKzAwOjAw
344uaAAAACV0RVh0bW9kaWZ5LWRhdGUAMjAxMi0wNC0xMFQwODowNDoyMiswMDowMIA/WFwA
AAAASUVORK5CYII=</binary>
 <binary id="img_11.png" content-type="image/png">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</binary>
 <binary id="img_12.png" content-type="image/png">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
ODowNDoyMiswMDowMIA/WFwAAAAASUVORK5CYII=</binary>
 <binary id="img_13.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAS0AAAChAQMAAACoKHu6AAAACXBIWXMAAB7DAAAexQHqzTBc
AAAABlBMVEUAAAD///+l2Z/dAAADj0lEQVR4nO3YsW7jNhgAYAoq4kWwLtMJqBEd0Bew4UWD
cCpQoF36ELnLkFWpFwcwYgUFkgxGdGOHNH6UMmfAvMGwXiC4c86Dhy4SPByFMGJJOQkSi3J+
5DJ0MBfJwmf+5E9K+m3EIY0iHt2d/7uKZehxs9UshrGE8xn/54OFUFd8Pub9UjZ/eCV8UQYM
+p1jS2cQNqcDEGMVUNDMBPWW2ZCZzpkJYrQCYzNQetP5FNIbbLGADLj0LxsUyuTt9Dfn1xyL
kx/LGPAGjL9C79O8fRt7T0zhUVuzNXshdgVjAYzlr5snGXVBbMIgLNRALNBhzGMFpWCHPGd9
/iVZxfqcyoM5MGPyNDuGsUFoTlazVB6uzAoGsMSWjCGcZK2wnMWeLpmGW1nLLGd0weioyVr2
CtbVP0l22cxa3qremieEGUlc3/JXsNhu/CWYFvtVv1vOJnbDIqyqsToqYXl6p6bjEJ5pWfNj
SdB86UkoGav3m5M/1DPN91tIHGfAqX9aRyUJyTwud4jrYJOmuP5DySpwWxzsqbuPzTSd+Btl
TOfLTckOYSzughjzQIybMHZcZFMFIzA2ezZbHlukDposXRHVYFYBsdgGMdxlrxcfxm56y9LC
2ERMqgXtZGJqxJm4NAqRqjdmSuYkuIoGDhasqmRU3CLJkXVFTl/tNEiNRkZb8ezl4otxEloX
ZNRpNcMeHRsdVW8i4ekt8/XAQCPZ2zKLZHLpPLAOyYi1K4Lh35EqKFn0timYXwmZj8eKKfRl
5ug8tBqC7fwUMnoxVvSWsyTJWeeXhpjCxchRsb5g8yNnrzJyiEMMOpCsGFSyJBBsLFehRslI
kbecXc+DTmpGesRj9ya6vFHNtL/QD9uz2Z8wdghjgarEKLJeV8mW83buwZgNCtoPYYzYIDbx
QCyGsSJaszVbswfs8/Xt+eIlZ6sZ9Jc4jKmurtn/lYUehDEEYlS9JwqsC2McFpRblfAcUTcZ
6qTXFuVWGdPDLRTX9nqaYMWC8Y457063OlfVRm2P9PxpodC+Z0lvqzMlTatNetukUGjfs1Qw
Qj44bWysYsmJZIGDsPEzLtS8C8a6ZxSfvt2dYhe93/h1ewW7kCxwD2ZDY+e3UtaWbLZ51tkV
rFC237Ham8H47c5ws2ftDmvvCmX7PdPIycH2RuMIzYa18rHVdPLpwDf2I202dv2S9GY8X0bm
LZ5bin8S+GKTq1f7Wew/1sXptmmmlHcAAAAASUVORK5CYII=</binary>
 <binary id="img_14.png" content-type="image/png">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</binary>
 <binary id="img_15.png" content-type="image/png">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</binary>
 <binary id="img_16.png" content-type="image/png">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
AAAAAElFTkSuQmCC</binary>
 <binary id="img_17.png" content-type="image/png">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
MDCAP1hcAAAAAElFTkSuQmCC</binary>
 <binary id="img_18.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAG8AAABwAQMAAAAqi7xtAAAACXBIWXMAAB7GAAAexAGjG5Cu
AAAABlBMVEUAAAD///+l2Z/dAAABNUlEQVR4nM3UPU7DMBQH8FeK6FgOgGBkYu9QsLgAZ2Dj
FrhCSIw9Qq7B1lYMHnuFSB2yNjCQ8uGH3yM2fqh1U1GkWsrHTy/+O3asALpWgUar3Y0F4hxc
U6tY0ikLXOwoKyWYdwXHHUFjJAuZ/CCTO6moiew7lcnDJzlQW0ZJ5jeCZfPpv9BJbYXzO8nk
3kC81nzx/PgD7b9FbZS8ui9PntoJM/fsMo17qnf+ePZqmAXWzYRqxGITbrFvYJGsLo2axRy4
ebcJdLPHbHkCZJ/1f+N+TMuWYbRjK2a5niN3vEm6qpUPu4+3SBCT1cB3ZssTNBEk+/qb9kIR
b5WnFlQY0w3RnFbXyWU8UN9Xj5iHevlLDnhxLj0n9Ur+WvbGVBj9GZ4bcPZDkHsjEJhD6J0i
V/cPro6/AM7oWTG9/zOaAAAAAElFTkSuQmCC</binary>
 <binary id="img_19.png" content-type="image/png">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
AAAAAElFTkSuQmCC</binary>
 <binary id="img_20.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAEMAAABFAQMAAAArXcktAAAACXBIWXMAAB7KAAAexQHNwmGU
AAAABlBMVEUAAAD///+l2Z/dAAAAiklEQVR4nGP4DwUPGN6DCGY2hgcMBxggQIGhAZklD1T2
T4GhH6qDeNZ8LCzSTcFvHn6TEbL3UVi/4bK/4To+w8UQrMdw1nM46z2cdR6utx/Omg9n7Yez
7GE6/tVjsv7Uw9T9gbv5LzoLm9/OD2nWgTpgqgOnMESqA7JYIKz/DXzyIHUPGKAa/j8AAAb5
7nEODVYDAAAAAElFTkSuQmCC</binary>
 <binary id="img_21.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAUAAAADAAQMAAABPmSiFAAAACXBIWXMAAB7CAAAewwF3y0R/
AAAABlBMVEUAAAD///+l2Z/dAAADIklEQVR4nO3ZsW7TQBgH8AuWcCdSgZA6RLqIJ0BMrYTq
TIzpKxR16IiqiCFC9BxFopVAZGWhXhl5gtYlg0evbDgY1QtqKQM4wvFxTuzUZ196X6hLmsIt
TtNf/p/vcr6cE0QzzV5a9RFrJPM8ykIdjZpWGOzERyk0LguGsyt9rSB4HIuH83COs4Je4dCi
wAG3IYmYDhcBWGnjUiApNFGjsOGJ0kClhxCUSIAwmApCzhGeSOfgmqHQSVFsYnnaRCnE0yaS
wkqDIS488fIg+fsQz670XkiDqbaFxUETIRVnnxTBqGlzADEUGrNL/DchnoPEawVx4fDipQeD
9j6GwG/o3FYaQ+d8iMbQTfJ/VcMb75AyKn1Cn5aiiFIwht75nZkMjTmA+D+8gvAACsnszvFq
QX9+z/GYfOX3ZiH7q9pGbC2K9mMovj2hyQpGztRw6UPJkieBKAcVhBQ6uomMIVtHybGPkvOz
46MWA8Ifi4dB4bD40izR0YDQLANLty3aH0ASF5WSU1Nbcnj/TsmsKboUHm3cXnldbyzL4eab
5sd6A3Wk8Mn7pslgWQrXHjRf1BuL8tKP7jVfgUqv32zu1huAXldvNfU6acvHceXlc4vSn3K4
0x0+SsEAiyeFmoWOmod9Ns1ys8dRhDCkMhjQ9KWQGkevx0HXWS2LoeVyUHcqalQ6D494uGtV
PosT+V6f7q+9/a75bJG6a/ipRSoHW2GZeko/t5oxaHK9Vv0OtQ59Eeyme72tndrU7vWRW2O3
vwN+eE7TEDNodIW95iDZcW17ryweRw72PK+zrwkTv2TeQgcfTBhHHrLVyYjfmRO2yzVSw8NP
My/6QBpBi8FUokuF0yyGkkshgi7trpayPzKJoE5bSyCISHvhMQQ+JDstrteToXXoQhIdYrug
XuvE6oISEbFaEBhWiIXGMPm+LBDAZWIt9bJQlIi2PlTWIYloy9xez35VJ/p0VZ65bGsjT4x7
+6dQPB+jJjlHaekACi9QOgPzicntaFJ6ocr9NsxeGH0nWDvb7eH4HxO3hSYPx9tCmoVRokp/
bNKkGfQTPWsh0ZXhg9/QHVsokyTjgwAAAABJRU5ErkJggg==</binary>
 <binary id="img_22.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAEQAAABDAQMAAAAf2DFJAAAACXBIWXMAAB7HAAAeygH2xG6F
AAAABlBMVEUAAAD///+l2Z/dAAAAfElEQVR4nGNoYICAAgYYy4Chgfke+/////8ZMMz/DwbY
WP/xyv4rIFIMr8n/sejFKotXL27WP3lM1h8Eix/G+nEezjoOY/18DmN9hLM+MGOyHjDCWI8/
wljPf8JYx3/AWO0/6qGs839I9ceQYsWAUhgircHTH1TZ/w8IFgBmSuNnWj6HjAAAAABJRU5E
rkJggg==</binary>
 <binary id="img_23.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAL8AAAC/AQMAAACVJJ9FAAAACXBIWXMAAB7EAAAexAHu0zGl
AAAABlBMVEUAAAD///+l2Z/dAAAC+klEQVR4nO3VT2vTYBwH8KftWCeUVdhlZcOnIGzXdr20
LDQHDx59B4IIHmXWkyg0XrTiSJFdOjbXF+ELaJngNijmBSjYP5IdTbuD6czy2DRP0jz55XEL
1DnUh0G3fvb7fZ8nT54EScgeIhkPg/4ZRa+JTkY/JoCq/YUDOhfsDzLgwakfDF6FA9r0gDur
KYCTofPg4is/NxxkOOCunPjgNDSMW4mcDCNeZqBTptPVV0QGmjmaoZss7D+irfxQ7dMK7YGA
GTihGe2VfNwL0WzbBk3NvHfXYVjQFO1ZdbM9L8hZ2YFMjIFcHVNIx7wZclYKgHErREG9yWyt
nHMhd8JWYDKZFZNRb1DI+zJe2K2GqhBngS5wnOwB5XG7zLlFzzz3lX/PAZx7OH/niTr3qE0B
uAcHnNrwJ4qbceGVcx9k3IeM/osd/MbJ8L8N3Arua+LHJ/RwcTGBiR88wc6wcsw/BUMHzItW
/C0wDF1xqcDdj/BwGeFX8yL+BwD/7tZexgJNPPly8tB3Rpn+NxcSdzT8/d3bfUTbmOVJf2t0
XRD9IAZXDFwQ/eDLGIIKAI3QGaK9NFhRtGsgLJdxMOT3Kzg2U7wBICUdzkfR8iyAQu3wQylb
6YJZpYSj4+h6JQpgSThSLQCttvKvvq6t1+CsdvLb6qBQU0GrAiqoaH1zFoZLT1T09PM8gEXy
ZbxyAIKIg2GPXkQAdYkwoCcpYMKCFuNAr0Oh4YMWam7kI1oJ3HCtGWnjOmqXQKvtlry6s6ms
uXe7Azutj+LSbhPCVkvOLFiAiYEPTPTMA+mFXWUNZLypyKsLu8cQahGrog2hclvOLO1pcOWK
4bkkIlFc6GgMVCcXMUKhPm4zATPpQoMB+8MCI2bM9eMBh9OImYl7AVDX+2bxFmjVRY2zEcQD
MjB5borJIDAiJBDqOhf6pBjYajQrITBc7yjC/So8OKMMZa7zEgI2Usq14UFAuP0L/0EWHuCs
QkODl8GZbhclMs343V5acMB9G0js28DggTPMnzXsrDo7ggwQAAAAAElFTkSuQmCC</binary>
 <binary id="img_24.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAMAAAADAAQMAAABoEv5EAAAACXBIWXMAAB7DAAAewwG8l5fa
AAAABlBMVEUAAAD///+l2Z/dAAAB9UlEQVR4nO3XwUvCUBwH8Dc86CUq6DBCmifP0SE6RDN2
0EN/QKcIgvoXCgQHnSM6dhIi/Cc6bNBBb96iTgojdkwTYuLma25vk73tp3trJJS76Pz4e9/f
ez6dQzJyjxp2jjE55RAAyIbtHYSypkhg873BXyJLRnXyggek0oDA9KEWfLQWCWBXBjOAQ4Ew
ZAb2ebBPEMxg78qFehDGHnwKQeiKBHrZIKgCCe/pQXiuE+hrQWi258FgwADGTAhl3HrtNql2
BfJ5RE3QGaq3SkHN64paXXtkGAzmCgdGFLTxjF3CvndjgBgECwm/GL4AYP8OWtBagYuYpF3W
ywSH1MLKA8r5gN/UwuP5Rr6MJicCDhzm5E0OiDFh8pORFJT0hqIBbBeC6QQF5qHAihSBPRys
SBHAcArg1cVABvtOTLB3mSHNDIwTL2LsjIUCngtKeuECc0Xc8OmyKxDQFRjoagpgBt0uWOGA
6WZ0QkBdDUxymvFvHijgkPDizK/qwRBXla/cqI9IsP+vleQMl/CPwPzA+CkSyhivpwd3kdB2
w/fzesd+fSvU7h5/EQ0Hx6evZ7J0Ep5gq1Th5EzEzFsl6b7IRYCGpJtiVIW2VuEaUaDzR4e7
UpxlH1/pEGiMFWDGEv4WmD+u6MNXAxDkLuKv7WdkCPs2Q3XgG+aoKhy8gZVtAAAAAElFTkSu
QmCC</binary>
 <binary id="img_25.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAP4AAAE/AQMAAABcm+y3AAAACXBIWXMAAB7EAAAewwGhkqdi
AAAABlBMVEUAAAD///+l2Z/dAAAEiElEQVR4nO3ZT4vbRhQAcAlDlUNYb29r4q4MOfjY5NQY
lig9tbd8gpIsCfU1IZc1LSunhzqHsMrRJsb+CN3eQ6ulsE5oiD9AYS2vw04PhVj1IRIRmkpe
WRo9eWas9R+24IH9Y/nn996MZ+SRLODz5gp3tur3Ohg2RwhB0C4OlPO/FhWowYE1GLf1QM0I
uAO1gpGcPwUzgqVwIhgyB+hZDuhoHIA0TpFDXgqDB/wimSk6vBqOZ6mBGYELhncXMeWWCZTg
gDovcHlg/hRUgJefYg1mBd7nuiRKAhOMGw1g3vbAa9KP9747FBkgUeAarMEarARYVFAVYk1K
gPjzQgYCFwAxAZTg0eO342dNKgiafSmBGgfJXnBB2hQr6MX/AixjJOcHoIZlzOq0Rc43J91X
4/V7VQqBm5VdYltggRXuCJOThzo5AAHYWExOQ3YI6udPwuusCMhBcQCYPECNYPHACiJMBx94
KbopwPSB6soyowZ0eP31ZxIjwmBTJMCUGoY3hddnrAjWk/qbM1YE60nz7SgT7mkToG2VWg9H
u3DTS4KbrYf/XocXQQQwG16EDAHaGMXBy+Y/I4lIIeNODASvJAGaAiYXQS4NEBE+t98rTCDs
GTITVEvexS8LbCiDGhO0ZdQhgJbsZhz4y9//iQEEgAABjPBDr/qCCpI1bCh/aOyBqujscRAq
nJH8lfdejBsVTJlys0SodY8YoJ2/kukKDKB54J2wzwK3dt0dBmjn9/p4nwksE+sssGWbmF2D
bbpccJsBDjxwwupF1QMHrBS6B7oc8Kn3875KBef/zDwfFgDwhcHsvRAyI6yrJhVQP/1nB9g2
nf3NTAyU8N+HQXFkgcELkm1+kNgFpQYrKHIN1mCxYI5Zrfq/vr1i4l+w604B8B5AFgIHACk1
gHcwUGoAv1hIAm6E5ddgccHcRS6ghksALkMv+DNq+Sn4EdQ4GKUHCguAS3y/DbD75ysaGK/0
8c5gApR4HVZ4EgDAjQERG+H3FwBMTmRDCOAuKAGoEWCRVMCNcHEwLrLHA+1Ekb14Ci0OvENt
YiRRIfNsQ4aASHFaEOsbWQCeEsB4kKsfl0PQ1KXCrVL1UQSG5VLj7G7Yi2dVqbCVOyCAhTwQ
3iSwj56Xi41e60bUCwvlGigCg3ffF+tK+1EEjHKucYYi0CoXm3IMFEuN99+ERR6dlIstmazh
uOjXEII3Jw+KdZnsRfer3//6EA1U04tQv6bTZ9RvJx/LzdIip9zMs3qOaf8lJ8J4dd8RNqvU
FGD52+FRMgJ5jxAuf9gL6vkhLPKnwv2p5wfu4k09kpwUH3kREAAKE2zvbUrbYhyckjVs792Q
8hFwPo0c9VSOAbPW3A2BZT6t7hhZMkXFRI4NgAQA7hOgdiD3OxBENdimpskDBFOIRASt7QEj
ei98YOVIoMkIEb3IV/rIMhlAeDxCztfxFIgssuqBvBCBvl9DjYigV0aoKYTrwhE17QsjS//E
8UH+vkyfD+61bm/HUCKgAhAcX8LqTjlpUwGZB6Yuf4x1Gkiu7q344yQAbbI9cP4DMZEx3unO
oscAAAAASUVORK5CYII=</binary>
 <binary id="img_26.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAL4AAABEAQMAAAAFsx2hAAAACXBIWXMAAB7CAAAexwETp4F7
AAAABlBMVEUAAAD///+l2Z/dAAABgklEQVR4nL3VP0/CQBQA8CNELXFg7WByfgXiYFhouvEt
xMQ4y0bV2Ir/RhgdGurXIDEhht2ZwaFYA3HiEgaO5HonZ8sZ7LtIHHjLXfvL3fW9vqZIyJiL
ZcRsG52eix5DBCWRAkXL8NLR/QvSlQTl5cBdmsJcQZBM+PqANwD/OXys26ovRDsDIcLxtZg9
HQFb0UH1+L6YXREMiZF7toEzoqlp+EMASGSa5T5wBhsZRrcF5TGq7nfBBGfsLNbUKtYVEQSc
TDYLchZAwLCYFyH4xBO6I6HXG69A67ZphC5RXa8At5v2hwVBybNfMUG7i6uWEEzBQ92zfRc4
fFLzCr7skkyCJ/1CAIIQRZV5ZxUmCnxXU6s3HVAQXpzpwILAc6JHEJAG+J4TgU/FK6XoEXq1
vFLXwFVZt8IBIEzAB9vHbAAgy44a+ezjSvAWACRoiffLww5YEm4JqHctHWhX4OTe2t9HiCwY
yNpAc1u1i7vvrSg/iALV1D9/g1+fgRa4unEjwGBfk+FPGabCMrYAAAAASUVORK5CYII=</binary>
 <binary id="img_27.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAL8AAABCAQMAAAA8KJWCAAAACXBIWXMAAB7EAAAexAHu0zGl
AAAABlBMVEUAAAD///+l2Z/dAAABYElEQVR4nK3VMU+DQBQA4EdrZDFBJ3U6f4BDNxfjJf4F
f4qTSSNVBseumpjwUxgYHEzsP7BUGllRh16TK+cdRwG5RwxNb+Ae+XLvvQscgPg7GOjRg/Vw
24CWYK1EJIGs1O1ptoYi5TcQHZhAO0LaGbZcPGmr0RUoUzBBYKYgRFI9KIhuja6Io4Aj4M1h
CGkTGJDoE4b7M6RGHr40gYGfz1MTAnyDsrhY4KBTdQFiAK13ZQCyYlFA0IRERtzVxc+SGjgy
ykgKI/Wq756UbzsnKvIKqB0D5tLky48ZHF8JVza3U66gAy+yQ2SD9sCL7x0EQnmdU2yD7j87
N0G0rdgYni2hHq4JjxJ+KuBVqrEQMQp+IvoTFO5438a6Gh/w3jVa45x93KCpNgDeAkf80sLb
zWxr+Y5ALA5fn95MyOcVkkoHWwTRGeqpgmWgPhnTNAKneh5tvwlegjofe6MS9IiDi197EEHu
GayLyAAAAABJRU5ErkJggg==</binary>
 <binary id="img_28.png" content-type="image/png">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</binary>
 <binary id="img_29.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAM8AAAEmAQMAAAD/c1biAAAACXBIWXMAAB7FAAAexAElj+IA
AAAABlBMVEUAAAD///+l2Z/dAAAETElEQVR4nO3YzW7sNBQAYM+N1JnFqL2AELMYYR5hdnRR
lErwIFfiBcqOxRWZspllliz9GuwaNIvZ0S0SiMloFmV3k16puMXY2LET/yQn7URcBKiRqk77
yT7HP8dOi4R6+MuLWSL8h6PqG5JPfDDJX/Me6o7F/1m6himFiQwi3EOsm+RExUArCRDxXkr6
KAZiMbjVEBIxhfcGhdZr2LYZtg8H0vvJOgNoWBF9jKLPRTe1R/VMz/T/pqWslKSb0BB67OII
E3lX50bM4VjqOAeIwbcDha6bXrqH7i8Rl9CFWBGUYbkBiMe7FdgqH4OLkkdgGus92OFqB7ZK
e6iE6R4kAlP/jhpGPbEAwgTc84OKSH7HInz+XefGf5h+mr1HP/ry97iD1GnYfneoyEiwYhVh
/ZnBxJ9JEXm8VRxSfUGpue+g2NTY04nYm4i3qT4cvByfRkl/qzDWH4YYbrXKI035SZtGmrKo
RbudTmO9btG+VBPMk+DUNlR1mL6FWsWpv7XdDHsJTL6DdkUdq50GNa1KkFZt2hlat4ec55p2
7YmqMwzuS0m4MOMq2osi6lVOBmybd0HhorjlcDB1ld4vk2RbfX6IRUD2c/JMgylD7hPdOLT0
CI1gQg4RLxaDSTCHsE/0aa0I0OqHLEev1LNYnJ7OZvPp8fT4ZCyfb9FllqFzKZ8sFrPZbDKf
TidHR0dRFCG0kq3ykl58/RU9q/JhksaSXqAUzpBAGT7AVPTRtnVJ0Zqq1VK/NHPO1JKZDt0i
SjShmibzl6rLDzd/qoJlrw1RRFQSimKdCKuj8Yb404iZIUMd9sSS4yIF1h3qPxKaDgt0pc75
irKRpuzEEFGnaNVhZlotLe0zTTcm1hI3Gd5Qn1I7LoBU8nuaaLqqycZiCbaHORObmoQhgZsM
cUhxNg5o28RaiXYsqmNtfNIZii5S49oXIdF6NsI5dGJpamY+Se165WN/Ua4thXtjazsEtk3R
uTdcijta9ezDnt1bVco5wvYmYlEpioaQR7aIRFBf3NK2qeX6MQVLnTIPqOig5mQbQl2xHqfC
OUUPoYNimSE//C3jkvMe/ZYIuataaTB7UYWL4pE/LmazlKdNtdVCKoW4VdviYOIw3Q3q8FYN
GSIxiLo7fPvYuH79onmN4+dL83JQXily/tVXFxBVF9WtpribXoyi72v6zBSspvovqToJ9XWv
cpSEQcID6E4Rrom7JLcopmPbCm/cDuVR6dBaU2kItVuVOvk1hYhsICI4pTZDjzBOhSU0bugO
Jq4os7EcUsmny2+ANEiaASTwioK0boiH49oVIOXnwGxgUow6SY2LOetF3mi61wTvDeJQ4tGV
Q9wnAbciTixvR0n6wGn1+tPqFqImDahSuEfcJ+KUnvhRLIRoiogI4OklSPoptT+UpU+rKBpd
Xl4usyx7pd/Cqzf06fS4RRcL9Yo+UUS+S38WN9fXTUd0cXp2Np/Pj/8C8HIeUJcBtHAAAAAA
SUVORK5CYII=</binary>
 <binary id="img_30.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAW8AAAAzAQMAAABiyRtvAAAACXBIWXMAAB7EAAAeywFpSy1q
AAAABlBMVEUAAAD///+l2Z/dAAACmUlEQVR4nLXWTY7aMBQA4Me4SmYRkVnSFjVzBJYsRqW7
XgP1Ao3UTXeEsmBRqRyBM/QEDWKRbipfwYBUlk2m0jRIadznn4DzAyKLRrKs8L7xvLw4toG3
uXJYz6bTVbgK2dj3B/6w1+87fcexLNsmRIRWoQz5gwHGXsGqE+Alfhvf3w8Gd73ereM8s25u
CCEyFBQhjHRhTcTogsf+YDgcPvT7r790u+5++e2zCjER8mXIgqhN7lug7fj8v45+NV9//f5y
CzwEAA9vRT/CHjuYyN4WKsPbDvYp9uRJcRfvA8VzMHrNoeA50BoPThz/S4Yt5ar9fgIqCr/A
tsQm2LH9eZCcGxwflZ7j2C5w0bzyn2QGPzTzYtTq6FW+vIpzmr5XPO4oHpNy7l6k+EHxmGgO
ijPNU6/ME55gISmOKnNnFc5szddHngsOmutk2FvFQ1IdXbwmmqQTyXf6UXe6kPOd5BMjmS1E
NMkU31T4IqmNLgqZYKSJu5qD3ciPubuKe39NnqpkKN1Uua6Mp+sOxOA8Ojt6rTJYyF+RkfvI
zN2D2qPmRu67Kg8a32qSNXM3rr3VrfGaVDL8VPcmHtE40JPgtsznLDP4sZDHOQPqayp42DFz
P3E9I4sJXHBW8L3iB1n3po9PzXe3+mnLypzjfFJbCfJLvLQSVEd367z6aYtHXRijjxr4pMzp
dbxYxcwlVdS9WIFfgCdzN1bgzgWO3V2dV9f3YjvIj/2nBZW555w/Amdvnv/An7la9k5XsYuY
V95uK2vJH9tulGc3+VEjD/vdLp5G8DgyVWeJ8RgPI+rkgSHbCDH2DkJxHLHkcWQaKC68Oqjg
ucYiMlTwzMHRrRubzGYztgo3LN7zw4f0I06t1HG6kmMIOdskP/8BoY4Dx6QULVIAAAAASUVO
RK5CYII=</binary>
 <binary id="img_31.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAMcAAAEfAQMAAADP0UBzAAAACXBIWXMAAB7DAAAexAHz1gEd
AAAABlBMVEUAAAD///+l2Z/dAAAEFUlEQVR4nO3Yv27cNhgAcKkXnDK4vtt6g1G+QpcCGYoo
b5JnyJLJAHXwcNm0thNfoWOnRoITqJvXTLWCGzwV0KFDaZQmy38SJYrf2adenRSIDOOA+/nj
91H8JzkS6sqiZYTF4OKR/ojklQYlk4KCguzvWAgocMx+CdcG5yHiBpRqj0B5crA2WAiY53BB
+iccAwpPJwiGKpgghIEijjl3prQmhYcle0GBGQ+vBVjEO+97J35lPSFHjfki/1dBE2RKa1Nq
gySbcJbAQsZ1fz7C4b0XFAbL4nCh0GmGQCE78GzcXUJSx3skDct2B0l1C7VW0cNlQzEgV+xT
zxBQciFYWKK9qyQNCvsBURGUz2GveqwKpggCZREUNQbqwqCkI2mzP5LwKTHomK0dW/4eyl07
Nr+jBg/EniPcGwcn/puOlI3oni3pUHInbChEdGub/3vJ4ZhmZoQmfkwTa0nr2SjG5EJ16cuO
Gtnu/NZaqW4PkLXpUzXqT2NOCwTLZiyNyTMSWTUGa7NCwZhmJI2Rj/7dybv7FgP3GjXjUUjs
+CwePqag9ObbQQK3FhZ4LcBS/7zU3/zEl6/EQNzVi/gvJbAjPXIFx62Np3/6UkTDy0kGSm4b
QOabnpBhBfKt/MHCHxxDn/2KMH+Orq5ffoOSTX7RyYfl6uzk5Ml8Pv9qJq94vS7qulDyZrVa
PdWiYLZeZ1lRaMn9PGVdfqyDIpjt6YHClFyHeqpFfHjxdaZ6ULSnfSvX3irRp40WAkrurWB+
jgQNCzZ1WyEhISQgpjZQ2n2HI/7Sl/aUMTsfw3VihOR13BeOixk7NyJHQ8tWmJhiwWx/tvbE
uLFSCXanhWypqavS2bkS2x8nTPcy7wlWmdMiMVIKRk3VN/q530mBejKIkbVpedvJjc2T2Rgi
RbSS2go8aWu7sv2R0gylV3Vp5H3ii3lfkrXFndxaSazMOqHdyKXC3k1bge2PL6Kr2s2BoaD9
Mb50842HJRdY3S/1/NjJXbcW2jWg5PunfzS0O2VSu0qUqE8j7VqTf5FiExub2kZP6jJTK2Qk
DBQBtqblx2fnZ2ffnp2eni6SJLm4uFCi+5PJvWp1cjLvtrGyKM1e1SxXaoM7nc+TRG9j3S4m
sMrz1qVZF2VZ2n0UqECAVe8VuLWe8CgGhNnjJB7l2SOY2zNoLOaTjvPcK2yCPFZrU/LcE5O5
d0k9211M722f25PejEVf2FCIcCdcaldj9F1UDAW7FUzvE3RoDF84IX/1hc6c5FsjVIv7HxLD
i4HIUwaIuaRQTMWgmI2AYvKeZLOB/AZKhlFQ0KZwMsiDqgIDtVUMkkvmWvPuWwOJfJcJiHrD
oXFI9Mgl4zGlk+fBtBgejsl7z2dIb/xaGmgtZNG+9fPml+i1cBdv5R/DPIeX2vuK8gAAAABJ
RU5ErkJggg==</binary>
 <binary id="img_32.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAALIAAAA4AQMAAABjbzCVAAAACXBIWXMAAB7EAAAexAHu0zGl
AAAABlBMVEUAAAD///+l2Z/dAAABlElEQVR4nJ2UwYqDMBCGIwG9iN2jB6Gv0OMeFvpotnjo
0b6Bj9LIHjz2EdbSg9cWlsVCdHaSmbRidaEbEPVz/DOZTH4Bk0OJV/ll9R4nSRhG0SIIpJRZ
VpbqU4n96i2O4zD0fT/wpfS22+1mUypRmN96+rtpWObEfDy6GQ4v8ttM/oZvhBBrfMabSDE1
vHnIC+b9gAvDc4w1HC9teAp5a3hB3H4jDkPeO46vLUzw9A8+oa+ZQ/G9pvgfSfHXnHgtideS
4lVAOrVHOjXHO34uLU+ro42HI8/b3Ig34Li2eTYt6Thecf6OV5znXUdTPlVO81ZLbfN0XAWk
o5aU/3mSF46ng3mJt6w/nreFpeHNg3ePdbn43qzX5n8+0XpLrr/jrm6K67mzOoeiDki/9ih+
x/tyOQzr33M9v9z+8t5qmOmT8b6ng33Xz9zGdzN9CM99q138qM819/n4XNz5ffRw4KfOrAsm
xm3+PE7yf5z3PbpMnIQR+gzaTGZsRin0mTb+SNCXoihCW8oy/IC+dJrxgevLvvcLuVEHOv0m
PWMAAAAASUVORK5CYII=</binary>
 <binary id="img_33.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAADMAAAAyAQMAAADLM3HMAAAACXBIWXMAAB7LAAAewgFJ3yT2
AAAABlBMVEUAAAD///+l2Z/dAAAAwElEQVR4nG3Quw3CMBAG4EO0CNoUkewx3GUVj8AGhAo6
s4FHIV3KjBAjFnCUxkXEcZezKQA3n33yf35A14UQrIaWJtZaOIcQ49GCRx4hq3/EYgsADdVZ
xdJEUY43NkWqq+zXGj2e2NG/lNRZOt8vB8mTa7/kJJ+GbI+K8+kpfeJW6sWwkdxjEvvI+8kk
XlZHNyzSh+6j8v2KdL5b16TL9WJ+75gt/4A9ztNdf/7P/VXD1dQ0NNxMVdU7DcmYqt7rNyxa
0/u1qDK0AAAAAElFTkSuQmCC</binary>
 <binary id="img_34.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAdsAAAFFAQAAAACMbXqqAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAdsAAAFFAEeQiyYAAATASURBVHja7drRa9tGGABw
mUCzN2fspaNpHdg/4OKHtmSb/pXtKY/rYIxCS6Xgh+1pfehTqVPtTxj0oQus2KEwD5ah0cI6
6IYcMua9WZ6hliZZt5MU2SfpJH26Sys7OUEkxfiX+74v8ul0PgmxbwPpbeEx/tEouAvBPQV5
9QRuI2TJEHylgQYJ7DYVpEKwq7S9NT2OrTsyqkPCNtGBVU/gI1Q3FQh+hiwJJXAdHbRBBbuH
vEYC4xfMdQj2cF3kBHYVXAkQVvx9HFvBUS7GLkrjMRTbFHwcHAFhTyi4D8VDCtZ5sAbFIwru
CryMGJ3DlrnwsDI8Xc2CocoKVh32O/imHMca3nsbcjE2JX+rx7AavAbAzghH3mvEcC/ASjFG
0UVGYFjCAgsssMACC8yLtcpwdTlXh7XVxFw5C1wSgzcaNniwBpJmanQcjXplIGYdbwczND/G
cRhzF5rw6PSwwYO75bAusMBnEHu1FMZ/0YJMjmN8K4VxD2EBW75DwzYz/vfD6yZzzuZm8yYz
HneGN4B4K53zXm+bvWBwfJeGb3O0rDtALFHwEBg2WkvjP01g2P6WwMHxrOPRaoYtsMBvCtO+
WtSCo1yMaUNm8Hgb+fPjahJvSNJFGF6uRyOBVxSHSwJYcGfqL/xgx7vMYWOsMeMfpu3dwfWP
hox4TR00L/fZ8OvtRzutvRKYyLIz3X2088HX64y4hvFPJTARduf1uxgfPmPDf9/o7LR+YSuY
eqGm9q/uZfyrhhRM5Kyu1w707y8T73Il+taATLK4xPkxca5B8Cwj5wgbPDi3ZZsHc7V8RsM2
Tg+Pf19nwipx7UILRuLNVjR0UUpiYnOj2FkK5taBWKNgC1owGgZXOxezFAzc8pJi9o9k2O+u
BefkkDkcKm/lD5lDXMvE6sdXUOZg3SUiJx8Twv23+bPMaTxaBTxbTby8ORs8YXNhroJxtKxC
sJPCBiRsG91H0WM3xv2oTW3WRa8wRkXY1Zw0thoQ/AJZ8hx/tcBygB8GL2fgGX6LLY8j3J5j
O8QP8MvTbOygWXee8+M5PimYfW+zddTODBuRBbuaxM6XP7cOH+RiJxP/d9O79sdTEF7Mb89b
/twFYymV8xdHTw7zcZTzYpY5wg8vSK2DHLy/wO7dBZ7uB5fnNxe3JygHG/OwXfx0HOHJPuDa
9j8E5Adj3vIM2A3RcJizwYO5Wl5SHF4kYzb8RsM2ivEkEyMeDGh5Gf/PXGEvac5WLt4quLkn
h8zv1INzNRr1Fg+ZGcfbePMiPPZvsWoDnWTill2xNIr/Wm4ZTMH0zrnBxvKHjSrDXAvqTr3a
bwdzLS6rruUVxYwFs+Lzy+XwGL3n+Tcflfx2EYonxLkusMACCywwZGFG2GmHX2z0iK4btBCa
nEwbBk8O2gkOj10oHgV7ozKsV4YZw9YrDrsKfB5zrhB7BvprgYOp6lK4t8B2oyxmbllPYFSI
ze1fm5+wFmx46cWTESv+5/37j5lx79ZG81NW/Nvt59eYW37+6iUdG5CwL7387rMIzzyy5cnT
Auz0/fCizsA+XPSe3eAOmIsnxzKBfanNcWHYE0tBtCktGA72Agt89rDDg6sLe5yJw6Och02e
IbNFTE4PYhixb4P/AdkFRnkooSejAAAAJXRFWHRjcmVhdGUtZGF0ZQAyMDEyLTA0LTEwVDA4
OjA0OjIyKzAwOjAw344uaAAAACV0RVh0bW9kaWZ5LWRhdGUAMjAxMi0wNC0xMFQwODowNDoy
MiswMDowMIA/WFwAAAAASUVORK5CYII=</binary>
 <binary id="img_35.png" content-type="image/png">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
bt3WyNrlcvCo6I+ncT+ZgFvWv1Zmz3g3iS751/bYM0J6B4m2hTfY08H9O8cMph87YM+ZSJe9
a3c4c85CuascXfKuXUiiK+zHHGS9xcxwyriYoM80vaU3ObW3wP7eZD/oT14/3OX0rjasS+jW
lNkzHz26bR6crq7m5Vsb9yrbxuP6ymp+/q1sU3bmmzF14/GKVc68eVjd1e5raP/SpZvz3fe/
WqtojzVQN/K5qaPrpbXK1ukzy+emp4/mpq5dv145vXXupZ/mj+YUb7VK6PrW1pnT585NH8pN
TV2/vra2dXr5pRPmPO+tm/NvnYX3BM3c1K0/l9a2H6PbK2+ufqzemrrXtX5Yxqr55rz36xBm
gF9Utq8+Precf34eTa2va9r9Xy6fNGf68S2zZ3T0ZPsZ5EST586XTP9OcoIZjI6sk8s+4s+W
UP/uJGo+PzAdTZ/M84NJrDdF8MQ6OhCZKbEu1Aas/x/+8aXP/juwBgAAACV0RVh0Y3JlYXRl
LWRhdGUAMjAxMi0wNC0xMFQwODowNDoyMyswMDowMHn5JdwAAAAldEVYdG1vZGlmeS1kYXRl
ADIwMTItMDQtMTBUMDg6MDQ6MjMrMDA6MDAmSFPoAAAAAElFTkSuQmCC</binary>
 <binary id="img_36.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAT0AAAG8AQMAAACWueCjAAAACXBIWXMAAB7EAAAewwGhkqdi
AAAABlBMVEUAAAD///+l2Z/dAAAFN0lEQVR4nO3awW/bVBgA8FdcNTlULRUcOqlKQJXgShah
zaKTt4I0DtNyhGNYJXJs2RBKtTGn9LBOmtbDLkSg5I/gVImNQARpRZSAOCAOtNky2t7SrIfE
quOHnxPHz25cf81e4iazpciN+8v3fc9+SV8+F2HzpqDmxlmO15HlgAyGIl7dQKMgqG1VJ6ic
FkqOEAOhXqMzxMAadXg4ABGdz6MIjOjmCYfW2APIvkZwROZQu9bqowGB5AGaPeRRZxqRDAgU
kUBwRLZQ6gkEjRoc8QgK8bBB0Hl0uUYPerArWCMf4M6wtdobYQbJpv+Zc4YdjnnQgx70oAc9
6EEPerD/UF/t+aDQef34MXoLBsXm3oVVM7wn5V6NryZkf8IH4Vqzr9FF2IPZs4DjuXJ6PekI
r2xHOTTpc/7subZ9Y8p/fcERyle3P+en87dCgNQx/nGeW3aE0VSM/zGPnOGnEzF+Ln/bEcrj
4yos3HKGlzMEvuYMPyst3n5c8TlDsbkHzx4Xm/vD8VZgDnt3ely8hG7cdjltjexviLG7uydD
V3tgiPEO/qOxPeV4E1mL2uGYB4cTWu/NvDx0MfVQQfbn8czORwXj0jwaDb7pE+58KZjQehsm
0ImbDwq5NkxbahTNzw9tIfagBz3YAZbbMHhmazwTp8cC60onmDCv7vQm4JH+ok0hRYhfh0gw
Q/2FB+0PPwAUxdqfCdSqT9Gh2Nzra1z9f+MyOsSsYIk5ZF8j+8EMQmrbiHUo7P2oN4dyPjq9
C4GpK3i/CWuCGX5nhnJRT30omFMnj0E1tRx7Wl9414j4TXCSuz9pQEmuz0RFNeIBl8m8jQyI
JsZG/AaUUf318aigwmfnHszP+g04Xbh5bi1nwMTNqXyOwDIfuBqe0WuUxWT+BZ/cM2AuvJIv
CmqNe3wqMjuHKSgt07B4IavCjBUqIp8/iJ8AFQo+u2iGf6lwk8AHkTCdujBvgoXwIz1iohii
4MZvvuX79GDe+6CwSGDt0lMzrEx+vVVpw0YlLiqLxlvBOD3NvXX27EOn2bGI7N6u4IjMIDj1
WYJ2l3AQ4LErA47o4nlkGFE0w6otFJygZRFnbQLqqz3wstCPfmn91EpJtrj8YomGsxi4st/D
wMVwFxCc2oPuQmtP6uXhq1ljP6EwADUOAhSYQ0tq9hPXHgpQ2G1qBqO21NjPiD2HDK5Mz2vs
50fKUKW2wM6X8J/3dxWqRnURx9XH0cIRBTMIXY63V3tiK61ltVdqr/YQFAYbe77S9FhCh60K
qhQkv1pDrfrs1rjl1n7zGMRdwkMoZJ/ag00oOMG0+zW6CIVTRrQ2UbtKfWiGDbuISXJs14Bb
Ei42fuoQUYPP75pgXdAjtvZ/q3CL/HwgCjSU0vq34XKW3MdVsuqk2JKeZJa+uivog9qVnvz6
PN0effYeefmHJZT+V0qh6AWjg6RIqY/+25Eo+PPRDIFYSk0sBKlWk5S6ljO+iP/+KLxyfpQ0
AXE1FbgRVEywSH1j/4EPn39HbMGoJWKEgpwKJ5rw+0CUbqZupK7TcITnw2Na5yP0bSBGR0w+
LARpGAqFo1ofdySh1kjBlUSEgsryGxw3qqVeTQSW6NQrmYhgQPkOt7o6oY06l92J0524e+QJ
Nd2yq3jHpoUsUxHVB7l13rm3Z4HkIrYjmnop8gnd6/43AdlD8GBOf1+hd4Oxa14dSw2GvTuP
tjebuk5tXVOwnxT71msN7pHap17X/jWmYkBtGPIX2BjU2kUBJ6DdQtC94eayUHuaVj7Bnbfa
w7kqiVH/H9TpQ8kA6A2hAAAAAElFTkSuQmCC</binary>
 <binary id="img_37.png" content-type="image/png">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</binary>
 <binary id="img_38.png" content-type="image/png">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
gg==</binary>
 <binary id="img_39.png" content-type="image/png">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
YII=</binary>
 <binary id="img_40.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAATkAAAGdAQMAAABTopZKAAAACXBIWXMAAB7CAAAewgFu0HU+
AAAABlBMVEUAAAD///+l2Z/dAAAEzklEQVR4nO3bz26jRhwH8KGsYqTSYKkXDsi06gtY6oUD
Moce8hpZ5QW86qE+NIXdbQOHCK49VMurTONu3UOlPbaHVsbyC4B8CGmxp4PtyLDGw48Vlp0a
DhaKP/rNn2+GDDhGAUISKT8shNHqMMugBYU/jEkIgt7qZGFAIbRiwnYU+lCo1l6xMjT/D7D+
ZB4rgpuuH7JdlYp+FTiGzqMPHYwHrajWDg1gHxcHhGat0F8hGCTAeVxCSB9jaMW4UkUInEMh
2Q9ku71U9KtWPEkI/sN+YpBuuVR6tS+fR/DeDLzboy9BCtluBdOLfdmxgkYDG9jAKrDs7qiB
DWxgAxv41OEf/WffgeDjbq8+aP9mYNC20Cfkfl7lgUZp02BY/z1XZVjadP1PudZwUV/F/d0N
1w/Zbq/316VN72ceYyD0odCDQgkIF5IDHPUZAjZ9A4W3fSiEjvqQcFD3qF3QPKpryHYr6H2y
j6tZDGl6PxD8iU95RX9f8JAfNh0AqhUr1vhLAa64hjX20Up3W9+8xRBY826PvvyDPnZL3BPZ
NTewgQ1sYAMb2MBTheaRw/XejIPC8k0cgkJ1dVL/HdIhoF8RnuY912mO+jDwU0J+h8Jfaofg
pmHwSygk6X9zHXkyTwK++RYIXQ0I/evjHzU9DCBcqNCKLSjkoZCDQgsMdSgUgRA/g8LyrUJF
GEAHA4cKEEa3QDgDQ9CTOJOQaQCBNT+yu09jQRegZ3vpUf4pwPqkbIu9gSoQEjD0oHAEhdPD
wQgKSzZnG1iSYQYaQFgS9gaWZJiB7Aw/BLLDzkB2NBnIjiYD2dF8CGRnmIHsaLJQBULC/P5X
FjKjyUJmNFk4hMIJFIa1w9gEQubyykJmhlnIXF45yIomB20oZGWYg6zllYOsDHOQFU0OspZX
DrKWVw6yoslDFQhZyysPGRnmISPDPGQsrzxkZJiHMyhkHE8QJo9PnspgDIXgigkyYJCmbV5H
YWs0Wn7x73qeXKc/Havj9+EokWT8Gc9jsxWTUI4DLQriB1dqbcGw1cbdMw4rHFYpxHKEtQdX
5LYhz90oeheLCEuBEL8UIkt7uC2AkyHvdfTBSOwPpciJR05ky5EjvNiCAc97iUZBbEnEQQvh
hS1/7gioALZSiAUKFwIKaKMyZ+2Aiw3EK+hsw2Ufl9CW7oX+z14KX9KOvA+nU47CAe2j7U2c
2JMm3o/RayfcbnrYthSdNtkfpdNzI6Wjfu1cbkUY8jLWe+hxHi0psuTQLuhj2JID0+ToIGgy
yhxLEQ3n3U9bE04SKb1MTuMeHxr0LxRdwIFBf7yVdcExX74ezyo8NvjvOyCcgaG3A/5NiGms
z+fEJJNiGCQoTnoG8dv8kDhB3LnCTiHEOgp0XW9RyNG3ww7CllEIZYQVXePd9keIvn15vgve
KYORIlOoKIh8r1zdoOeWWgQ9cfBKlLXJOS1ruvpXv+pXXiH8U4wtUW5zVsdAxNUvdsKYLhTR
6VLYQ7TixR2FfhH8SxhYoqXxVkdH5ptVxULoCQP79pU2czu6RtZ9LIR2e2CLd/LsvKN3acXn
Z7v6iBFt+k7+4jxt2tUuz/TLHbAbY2Uk81I6GF/vn+t9vxCGXz+ECUnopYrCcY/0en2/sI/r
Q92cLhc2fCn8B77DjunBtezjAAAAAElFTkSuQmCC</binary>
 <binary id="img_41.png" content-type="image/png">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
RU5ErkJggg==</binary>
 <binary id="img_42.png" content-type="image/png">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
w600zLnx2gbXturRElZpmN8N4mq83IBzGdLN3tvLoyX+u0HE3mu/RhlXnpuvUXrPjaP5WjGz
z50LymPwFTNVSyuPIjQ3F63dtsBrgwE0TqVYWrttsNwIp21IWphz81Upby8EvnIXILfu7gVf
ubkeQ2Aar/cGvlIcQMPNrdrVcRqo9xY2v21rN19u/rdfwnN7mJB/tTX5V5sb7VPqzZmm9iSw
0qa2Z2lQ1LTGekWrdOrCyKcCPLfG27pGGh+8r2m3Pj6zTYSPU/mdccHQ5g3tn/dBtVKrbeN6
226/pWsXPz7zkgjPrfL2hN62W7O6tnT69Dao1qx0/dMbetvWL+qavDJ4yUdurUej96b13ttI
BB+nJk3o8f1IvFGPdH9IW8O9j6uX72o6/h4Jt9IOarBKce8x6/j1ekvbejlOce9pdJhn5Y1H
GZzbzqGhna5zQOgVz9aMcntb+7bUOG75OKeXjV7vZW1lWKWcLQ/SapzXwtq2yX01ZqUCTOO8
HKglUCtl/+O8nURrReZLPwdqkqg9k0lOLt/95g9Hvz/z6PnRT86mUqlz80BNnt47MrJr9+zg
4qnP5p5afmL6Fy98b+/I+f27m1hqAZobuTMjnheEzOZmwV/nW/sfFiZFOCV2gbAAAAAldEVY
dGNyZWF0ZS1kYXRlADIwMTItMDQtMTBUMDg6MDQ6MjMrMDA6MDB5+SXcAAAAJXRFWHRtb2Rp
ZnktZGF0ZQAyMDEyLTA0LTEwVDA4OjA0OjIzKzAwOjAwJkhT6AAAAABJRU5ErkJggg==</binary>
 <binary id="img_43.png" content-type="image/png">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
rkJggg==</binary>
 <binary id="img_44.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAfwAAADPAQAAAAA4sF4JAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAfwAAADPAJ2XpF4AAAYQSURBVGje7dpPaBxVHAfw
sRFDqLqxiASKjS1qBT1EL1W0DiiC4kHwUPDUQsEeBCMWDDSaCQr1UO0GFGvxsATxKFqKRDDb
iVqtekmOOWhml9Sk0GRnydKdTXZ3fr4/s/P393Zm9iVuQvNKdruTt59835+ZNy8bBXipQ7DY
B0qK90pRWi9mBhSVPN1ij+OK0u98Yxmq3x33Aw3lTkUj9RWlF6DmAeR/g+zAHfxF6xsm+bL8
QJN8EcCA8gjAOkmk8eM6PQYVgAJ5odKfsAhPZdy3lV6mfgCgrg+AFtDgFWYUHnKFZBlhiXva
A1oEyLEqTaj1kkCzbm9GAGgPrJKXU20BjX+pwgSsfxygLmiC6uvEEGAGgPUoADGAM0ImB/4W
AIPYKAQAnmCGTCEEqClkvPMwygCDAc1AE7xObPgSaAwwWwmm66dRINgE2geLA1kXaDoA6YPp
h15sl4DUa43Cv30mBWzwADoS+U/2+4B1Ctg8gcUTaK15sHouGwZomWZAHXIMqLuASR6mAsDK
470+wHCBgydZR+khwCbvpQlsdyYu7s1gwJXTi2GgSauUIoDpG0ZnSAJj7c2DJu8DkzXBRs+F
IGBiQKsJkAAIJwgOY2LABueKxAE7MJGSJvABpdQJQk0opU5gRwGpBE02mcHAgXr4mmi5wJwP
gBBga77rQcMBntcgxy4o9Bqh2u/0+y6qAaDB1xx+0W94K9O4f2UiL4ZECZxSsE9k6PMshEqO
Pa5DmQLLPMEIq1cJVnTaboYB3QVIyAwPqbUSpwNaFQo9FiAlKYBUSZnAkARuWovHpADpJmwC
ALKAlQ4AWSDXdUC6D7rfBGnAuJ0ArR3QjAPs4/bIFRkgrglJAN6Ea4I+0OdimkCu83e5F32v
RPdMogQGXKfrluGuzrx4+4EZF1hGE5B3VgPLu1tCQCSk11QrEUC6swcBmjxBPbBrAz/qAdGf
4SXwbbo2HZiLB6qygFQTmrEJOu6DZ48mAhoLT15kCT4OHrfOKgwoxyZY+HyCARdCCS6df5C+
oxoPzD3HgKnQRPr+bgYseUCxL4sCV4dQYIIDBW8YV1/JoED/kMX7IAicP8CAog/YiyVoLECd
nY3ZUAKdN9rymnDjVTyBczrr+DzwAXyXFy7e9SD2bDTbTaTIGKWaiVVZQCqBnZMFut6Exiye
oAIFejYegQklJkH7lcn360BRH1j2ku3uqEJtA//iKgJCVyIxIFiZ7G+P6e8lAgCKPYABdvH1
hED7G4wdAVRkgWVZwEwH6F0Hcl0Hut8Hu0D3J9L85L68KgPkyD8pIEUTnlaxoz+ShUVnC4u3
5cFL9HdjrFTo7+VZjJkYwMAvllP8Nlr3A2YawPtUJtmeKQHQ/v5gGwJT2yCBFRpG4X4BdDSB
YeVpgkoCII8m+PX+ozRBgi3PwCU0wV8vsQRrmgtYAuDkIygw/3OeJqh4QOWfWRQ49QQK/MGB
Na3QAsqfZlQMeOFhFPgl0geld/EEz0xiNw50IuWCw7iCAwZ+54HcKxf3vJYCoAl050MaB1g8
N5gyQQgA4VQWJYCkgOhsTJygzdko14Tu9sHlxAkW3lSxBOWkWx7RyqRHfi0sAmJuMDoGbp35
4YweAEQrkwDQQR8NAh3eHyT/iGRHACn7QN/8BCm3fVsApGzCFvRBSsCQ7YNdYEsA838GdPZY
7yLwJW9CYSgGKCjqLHK47H5M1B8DCPdMrcV1Ln7L0/4mKwFgJQI62zNpST9j2QUwQGd/uTIM
G3HAPNgYUL137B7ydAIKsYC6cQRLcPWxD8jT+79nY5twcA/ahBuH6DvGPhx2gSzcRIHJr3Dg
UQZ8ccoFPlK/RoFvcKBwiDZh7OxhF1h7QMUT7EeBpVEG/Ga5wEafjgKX30o4DzbewIHEE2nj
PkkAqjlJoFsnk9yeaScDZGGZhMDfH4i3PG9fQw7XlH30E5Vxpce/Y1GRmtd7xzPQrsRueeKK
C9RUWwoQ7pmSAh2XXeD2AOxBWUA2QUPDjxsRoIhXrKn48QsR4E+84rqOHz8cAS7iFesCIBMB
fhIAeBPsYUkAosBneEXRKAxGgA7LNgD+A8IsZeTSYsYrAAAAJXRFWHRjcmVhdGUtZGF0ZQAy
MDEyLTA0LTEwVDA4OjA0OjIzKzAwOjAwefkl3AAAACV0RVh0bW9kaWZ5LWRhdGUAMjAxMi0w
NC0xMFQwODowNDoyMyswMDowMCZIU+gAAAAASUVORK5CYII=</binary>
 <binary id="img_45.png" content-type="image/png">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
AElFTkSuQmCC</binary>
 <binary id="img_46.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAEcAAADDAQMAAADqX56SAAAACXBIWXMAAB7IAAAexAGZEfHe
AAAABlBMVEUAAAD///+l2Z/dAAABMUlEQVR4nN3VsU7DMBAG4Isi0a1PEKUDL8DIgFh5Dp4k
XVmaOVKkvgnq1DJU8ASIokgNYysPOFKTo7EvbkKvrmlhIdMn3/12ZF0UQHoq4LQBuH4EgBAk
6OeipYL6lqzWTtVpS8Xe2tJatYs/45BKo8JktQRJV8VR6Wxm1nIl0dHM6IVRzGhshB09W9e4
qn2XU2Sfg59qCvLuYzt73Vmr5V0B9NV01rdb/YlyRlzVnuD6XBOu+52zy/8Td8/CqlYCwK9g
RbPWb0mUE/Dw3O8j++WEa/Wb4lL1JTLy51t94sPk1quVYzIML59UXxIH0VxrnEZUxbT3qoSY
+kgKPFJ1syZtIkmS2OjdKDOayXvSMPCNeo0Gb80Z+u3dNHJcc03Ys7sbH50wEQszYYu9qQt3
/98vqOI6P+2+IqoAAAAASUVORK5CYII=</binary>
 <binary id="img_47.png" content-type="image/png">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</binary>
 <binary id="img_48.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAASkAAAFlAQMAAACNzYzWAAAACXBIWXMAAB7EAAAexAHu0zGl
AAAABlBMVEUAAAD///+l2Z/dAAAFgUlEQVR4nO3aP2/bRhQA8JONRhmMsN+A6dRu7eghMAN0
bz9K5wKBj0aAqENRfYAO2jp3azcLcAGjk9cubRyogDdbhAcf7ROv5L131N3xSD/ZVOw00kJB
+uHdvfvHJ9pM+a/zl1//6X+WMv8TwRgb0FjjwybLK/qRsII/AJNERktBPATLe2WXFCZojBgt
V7Ne2VmPy1LQ2INsGWLfqIyxpymJUc63OY1Brhu2YRu2YetlQownt7N+z7c81Ls7s+wRs7yE
pGinPbKcyv7gJPYmIbGfemQZlbGY1CiNFSyiNFokYxo7oTQq+TGFCX5EiqbO+ttZ/W7Afhvt
l63w+5RUvzUqy8dz4G/Yelk19Yf/fH7RwvQjDus1CLO5x1gLu1YXplH76rFLL4X3ym7pW0Zj
xGgrsvea6Xoa/R0uh0FWLaNttTy4pL3iXDawmPMczmLfqSs47BM1V95v6CWrembuCXk3y2ls
hWgZnYkuNsAGB0hOkxArGAfGEmDTOMx0NVMWGDGwN1GQvYiBxTGkEI+DLEEGdUjJjruYQlYk
Z50s1n0qWXBATAoKU+iLdTda923czcYea8nUY23jNnGYikZdk6WeQApqFJ5Tb0BaV4i/kILr
TcXePpBdi9zeBx8gI+x66sHlsZZj8Obi+nt4R6zfNuyjYY2CrFmgrcDg5j2fvFMLpa6alYO0
WXuN5DG/YrhftLaqZrVos9Ua7TfTm17ZLQNiMu2MVq2PoZ3p339dTKovf2afmpOJpezUqtvM
lZmvm8w+3wKs6tnMZjvsyS706ErAVUlgl6p5REvrarHQ8UyItjYWVUwy6FsB9ZsoGJI0ApYO
gXEdrVGYeexVggwrLixXVBoDe/1WMx5Do9wUZiNgE+zbiQI21t0vuCnIjl02DrG8wZxoNwU/
QTYDNoYxU8c2K/t27LI0BjaNuhkOiM+cRquuB/pWspHPpMMmMLxuprLM1GWxx0Yuw3GDybJm
YQwschnDOd1F9gKnfityZsEspHqFYGHGhk6mA8NwWTKO4+awji0jaTvr7oy4s0I/xQLRbmOL
hToK9m0hNd3XrD64zr/Bg2tLH1jCPbjmgfOtPiWXTPBMnXlf6+uWKfMkd05y8/Lv9d6B38r6
jdZvow+S6YP0rYvJdlb+sBN7e+KLnV32GXv+SZj5j+lMoeil0PaYzmN+uSKX15Qd0ljSWzRi
33hnYXa/aJ0p9Bet30ZX6Nv1znO3zCvZb/ryw/5BeSn+TdnALfM66jci84/oxvHMg7ePBlPB
Az/Eim4mmo36t4+6XxyjzbrvMiYa1G+ZmnIg8HhOqlOoavikvIGzWQH3+qwsdoDV1cwQUgAm
n8XQ6LMI2BBv3qMRRBsD4xEUZjHWbzGWK9FR3WjZt7IC00xi3VYXP/HMZW+BQcVlHlrJIrmS
hmumkMFglFdkOAvpNrALnalULYxpNhc6hUzIIbB9yLTYG8BklYzVLF+ybcMghUgPiMlUvNIs
r1lyYM9CPSBcZ1heZ8gyZ0CwaCy/zu1xK+IM6zfNZILlcXLkMBW9c6feTNYQH9NB39QBXHms
mWJQupdlHTBTt+EKqTKt1tsUl2Wa4HqLvfV2pqOZRT7HZSk4MMnN6i1Y65ZxFnk7kysyRdvO
4X3awV63MNz1l6fkg8v/K0ULU/gSv0zhzXn5CwA+UfXLfqSTK/clN+z/x/itTLrF2T2Zd7+3
WUZjxGiPh/FH3Dci42uNZv9fiHNo8bsy5r2XX/34pXCZOXdNz+wj+oNkC2SyyZb/RSc0IDCB
TITYcsJJjBhtyRp9EyqnsLyFFTRGi8YpKXDqgJCihdicNrzCZrw1GjHTO7BFO1t5kUsa6zfa
CgwavmmsXvvRRi/nW81esqe/Vm8ui2/1B+l/6fS1D0tAfv8AAAAASUVORK5CYII=</binary>
 <binary id="img_49.png" content-type="image/png">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
AJSeiSh8nTYQAAAAAElFTkSuQmCC</binary>
 <binary id="img_50.png" content-type="image/png">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</binary>
 <binary id="img_51.png" content-type="image/png">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
AAAAAElFTkSuQmCC</binary>
 <binary id="img_52.png" content-type="image/png">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
gg==</binary>
 <binary id="img_53.png" content-type="image/png">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
eghfa8+fRAAAAABJRU5ErkJggg==</binary>
 <binary id="img_54.png" content-type="image/png">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</binary>
 <binary id="img_55.png" content-type="image/png">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
AElFTkSuQmCC</binary>
 <binary id="img_56.png" content-type="image/png">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
AABJRU5ErkJggg==</binary>
 <binary id="img_57.png" content-type="image/png">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
gAAAAABJRU5ErkJggg==</binary>
 <binary id="img_58.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAgAAAACHAQAAAABIKdweAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAgAAAACHAPaPoqwAAASxSURBVGje7dm/bttGGADw
EzSoRQcOfQACXTt0TALIZoE+QF6hQIeMnQoPtXycmmwaOrRDIXbrA2TIkogCXNTd1L2ASaeG
uQSgEgIRGR7v63dHUjxaJE2LBmgE4uIjT/fT/f+OMoEbL0ZGDbnkZiCBdd9A0hkIOgJRVyDu
2oTuQNcmrDsDfU+kqHeAgdcR6LqcIYY9sAf2wF0AnVfjPYjOvHdg1XVXdrsCb3oHLvvug3tw
zOsd2AfXewFE7YAFuf1lqMBfFMy38PeSug9gBRAeAfuSwucATwF+p7CgcPGZEZI/GPnuPRnY
hJyaZcBpqGfdVLT3AFgK4Fr15Vff6tUZn1AFEGNSBxCt8vkCy2wARzSotgV+5XMHOgJW/4Cl
AloDcFoDaCpAG4B/q4HZ920BpwaAO61B5z6YNgBeDWDd5TxY7gTQdkDQBljstBoVQGwOtVfN
y/OF3vuW9jEBQ4gvLIYRUL3+HMZkwL4msCRHycJgRE9MDf4ZVQBhHm0HRR7bPKsIydeBzQmC
FXlJbRPsBoA3AH5+Y+0IeF0BaAMkNYCv3lT0webXOtYG2K7B5jDMi3HkZFh8rrScxRpWkkR+
WZB3weZEx9XTYYDbzeYSEXVTly0gqQRKW1oJMDJg3TfwNm9CWAChCpypgF4Aegbkv7ryDwXw
TgVOq4FZDgQ5EN2yBkYGsBzgkwL4UQECFZgWwDQDLuO8CQXwQQXU6Ow8Lpqg5Z2YA2onKm8J
5T7QtjsxH7Ld50H/QMVispQ+CKgCnCmASxuWs7JDX1vORpGk9btyCMpVis5WKbnDnmiXkh8d
0Cq0Xe/ELGTqeI9/xIC6RSDVxYCmF1UCLpF7tvgcApgRcE0eD3CZ/AzixLfiNLED0MRXsCdy
GH8y8C3cW8VLrvPjR46YeqcAJhBO0yYIoEgqT0VbvDQzknr5czUAlAG/BZBlQC1gpIDfrga8
K1BRA7sERBvAHEBijmCF42L+AOybKcAzCq8HOGYauEM5U0JXx3MUDugIh04HcwhsgEVwWS4G
eA6T+4HHdDCItNyRBUMGoe7Bkhn8ZAABeQzmF5R9+lwCegiMjeAKk+QhMbgEfLG98Ky+DlCx
I63FWwiXkc/HFlCxc3liR8qfYRGWAnFeSkneCgi6ACfyv7L+1IHxSQr4DhyfQPzfGpZTW8SK
9RoBmyYRAmcOHB5iKEHAt2B8TMZ452Kppw68PJQxRiSPD/Hwi4CGwEQGlrlOkxUCv+AXzbAI
AtjZ4zE5mMnQ5j934BUm32PyhQOTGcRvEHhi83giQ9vcoQwzPfzcwTkkVwg8sODRbxK4yoDz
FMDk5Fz+nLw8UoFEAsvrwDytwYsCEDWYQ3yJwFfbADZBAV7KPrgo+mB1Ux9gpuy2tA8ejskY
x8TDUjYCmFynyQkGKQ8BaotDx3qJAKVJgICFgCiCA6cjwMkB3vlpqVdlwE+BOJGv/3OgDDM9
zDzIANvCpDoT7dJEitL5k88znEgsm0i2OvvVtaAAxhZgZcCvWv7MS2cibqwsX6YiOZRJfBrK
p4aIsiK4moTmmdnnVjJJ7ATDiY/fZostg8sgYBfBg0JxeJARIpJJjpM7xkwnbvObauP1P0kd
iVO1ueblAAAAJXRFWHRjcmVhdGUtZGF0ZQAyMDEyLTA0LTEwVDA4OjA0OjI0KzAwOjAwvF4b
UgAAACV0RVh0bW9kaWZ5LWRhdGUAMjAxMi0wNC0xMFQwODowNDoyNCswMDowMOPvbWYAAAAA
SUVORK5CYII=</binary>
 <binary id="img_59.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAgAAAACGAQAAAACDdQ+7AAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAgAAAACGAO+Uk+0AAATXSURBVGje7ZhBa+NGFIDH
uDT0pJb+AKWnXBd6SAtJtNA/Uughx/S4aezI0MNeCnvotVg/ooc9bNZj6CGUQnUuC5GXDfFl
iewa1lE1mtc3I41mvJa0a0+KNyWCwNM8zZf35s17b8YE3vkw0m7QkvcBfGkHyCDdNCC7+4D0
7gNmG98HGwcwmFkCbNO50YN7wD3gHrACILEEWKfz5ktaxm0BzBYwsQVc3X2A9RrcWG8ky9a2
eYB1NvIXYAf4AEra3QZk4oyV9Hz41oOfXJg4MGzPJy3okettckI8EzAkqz8LgKjBkHnNOL0H
2AMCAzASMal5bohTOT4kvgZcO7QWkEJcOR6BAYiFPSsDPBOwjgW3CggbXHhVA3AMQLjTAPi9
GnBxZAAiv96FWVQN6JtRWAcwODIA4WEDoMaFgWMCnjQAahaRuiagIYyzmjAGcJuA+L8E3PjV
gJ6ZjU3pnPScakVgFpQA6p8Pt6T9jwBMNcuW1rGmjvo2IFXXKmYAai2gFQA1wLUuqwUEdgC+
8/GhHeAHW4C1CxDoo3OQAzjZKgZ0HLl5QF5orkP9K7FqrhktmPyb8prMv5/qOYlRULhRulRz
Lc/zXBvOzSu32dp4BM80wCsA8wqAcbxcKGkRlC4EpQWrAZ4uAaYKcKMB5k3LbK4scj0l990l
QLcSMPtDA7LIKy0Y+AVA/erKE21BYgLOTRfcEqA6U3mzXLDgxADMTEBYhpGGBUCZy//RAG4A
0hemC0clQDXXbKr2QY0F6W/mIjo6Cu4aG6kyjCrmdfvABLB1ALNFAF0GlC7oZKpzgZ3DrpJV
cy3vtvz90nlXi0V3LiuEUYpvwHheaXGhIgVrVSSqX+g6gM8+37UCQGILsK3KsLSIQ4f3ttin
LsiG6oM4LpWPKwJa9lSj4baL7xBAHhCyTWSkCflCKvwh8UbudPLQx3/BPwHA0XMvj/I5+NzL
Ix+i0ie4G6ULMf4ti1Hu1jz3N1tU5gC+PiC6HcBbs2A1gIiC8VYpNgNyF8olNRYHk9WBES4/
STEbXcw82YRHKPYIBnRLHo5JS4SSFQpT/AiS1hj+/Mrjey34G4Pc6/js9Dup9BgwdgjjHQ9F
gm+itYmLq89lbYlF1xUVaY4CVWOoZjg2Fh2VF1MojhFPz/J44WUNIHsXQFqQKjGpBdBKQFwA
cgu6p9hREeBS0XBn8xj6ns+mCHgcwd4BZC8R8CSATofINwQoRSrFzgGk+E3kUNFsZthYsBMz
bIHjHyM460M2QsBWAI/2SHcA2SUCniIAFZepFLt9SF4j4JDyZF/eG/uhz96cwPhZBM8vILtC
wC6F41/IMc66zmdJBYq/lgC8jfKT55D+FcOFAoTyu+sS8DUCXmvAm8KCQQ44ovx4XwKUBT+H
0oXLAnBG0NtslDt+diA7fbEGCa5BiGvwqCubq1qDx6H8Tq9B5zRfuSBfxGkudjCMYwR4aAFG
L0SA7zM8iIwpuoDRQmXsBnDMyL54w1k0kop5LnYRECPAxzVAAN7eLzDKcw1AZewF0M0Bxe6h
SxsJD5XcN8bERgr1RhK739yJlQBYBFw9dMR3DJUvEYDJtE1kcx2RIE/TtpmYQ5mxsrliI+VS
6eh0Fpmt0nmCn/ZUyqPYKlO+10YR60FbKsV3ojRc4flciOG/JeVF+2dC3QIAAAAldEVYdGNy
ZWF0ZS1kYXRlADIwMTItMDQtMTBUMDg6MDQ6MjQrMDA6MDC8XhtSAAAAJXRFWHRtb2RpZnkt
ZGF0ZQAyMDEyLTA0LTEwVDA4OjA0OjI0KzAwOjAw4+9tZgAAAABJRU5ErkJggg==</binary>
 <binary id="img_60.png" content-type="image/png">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</binary>
 <binary id="img_61.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAgEAAACKAQAAAAAbdaT+AAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAgEAAACKAIh9D0QAAAQ4SURBVGje7Zkxb9NAFMcP
VVC2sCORSrAwgQQSYqn5Bv0IsDEyMACixd4AMTAyVKq/AAMSQ5c0AWXogETmCqUOEuCNS2UJ
Jzi+492dz3dObNfpBRKq3NJ/n+1f7727957PRfTYMUC1kqsOOp4wNCZEFM+fEBkTAmNCeCoI
eAEIi7CjFoBgnt00pEvCkrAkzJ4QmBLMszui/vwJsTFhaEz4aEw4MCZ08fwJH40J/gLsqAUg
LDvvf0hw0OQ4f7Z31bnYv/nOWdt86zy6fuUeGNfuwIU1hM4gZGcIyDmHph1WhmCXTBUX2FsZ
grUksEFOQnB1gsMWt2D0UD3X/gGWUxFapJjgUy/X3gE3NAKdnuBVJuBqBMuU0KyXEJ4XEGoZ
QpkXbwoIdmVC6x8RSuLgV4pD6VrsFxDcGe+HBSCU5uaFeq49m5tlFSb8XHDBNa5R5oTWKSPE
9D42IvRlJ11RFwdl7XaCkL4gROpipP8tPPaHZ0dwTwUhjYM/FcGdnEP64jxCq/KaJsc67wdV
BtLsDqCF8hGrI3asvwNm+qanSlHaeQM5yyJCpka5iuCdjOD9HUJbEo4U4Ugn6B3HU60p7RdB
RxK+KsJ3naB33p27inBNEvYlIVCEr/pavNYjqc2hLgnys3o8UISBPgdfJ9QUoSMJXyThW/qY
JoGwq3uxkePFVJHUvahVXU1/tjvq7xD6Mjdj96EiaEfljBevFOHTw3HCtNndS3t3XoXJfErD
+i8t3aP5V/uFIqSRDKoQ3LFIEtVPR/CjRjPnZ0u1YFvcoPXoHrM6aJTMgRES6SoJ1iGlvJbb
qWTnqSiZmSUIoXApzkpfSHlv8pin5MkI71duGBJurFyuTsA5BFLgRRKznDlYk4RonADrwjov
ZBzhsp6VlECS9kUOMtlDF5kccWsdpIOsIe+80IkInZAusUcgWH1oEV51WKLXRrwWMasL28lm
diweEzUqkcwKR4aY/0dMEghmNUrcKaxAGE5J2M4hBOMEq5BAcwiPn/Cud1i3yADs+1TKEKxw
AIyPgABdr/mM9RCCX7t0c513FtZFmusIPQHCJyBsWOT3ViJtJsO2IPQj3nkbTdbHCH4OBCYD
Yb2E0NPbNDiAx7BNIiB0YQ4PLCZD6IXNjh3/AsJ7j+4d0vgneLG7Tbd2aPwj4NbGISeEk4Sg
kHArIUQpAbwI1dSDA0H4nRA8QYDO29gRXuyCF8kc3ggCi2SbRdLmkWynQZVxYJGEmDXW2TsF
wasikj0RSR4HeMyDx2CNokTaFpMhSDjOx2HET+57sIQYvLDAC5A+WF0gwGo+HSYEcD7mBYTJ
YkLL5QQccOv0O0rt6ii7J9N0EnaLSUZwBUFlFmG5aZE0sxgB8rgvs/vMuISj9Ahu6PE85inN
CIjJlSS7UZWvrNkRifojR6XvtNogE5apCd3uFzMCffFy25Aw6cUfc1uPoh7Yuq0AAAAldEVY
dGNyZWF0ZS1kYXRlADIwMTItMDQtMTBUMDg6MDQ6MjQrMDA6MDC8XhtSAAAAJXRFWHRtb2Rp
ZnktZGF0ZQAyMDEyLTA0LTEwVDA4OjA0OjI0KzAwOjAw4+9tZgAAAABJRU5ErkJggg==</binary>
 <binary id="img_62.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAgIAAACJAQAAAAB21m1TAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAgIAAACJACXELikAAAQbSURBVGje7ZnPb9MwFMdd
IdgOSJ3EH5ADSNz4CybyJ+xP4NjjjjB1nXNA4ojEP1D+B66oqcShTIzljNCaok2rkEaTLRNJ
1NTm2YljJ/2xtqlYOi2Ttu+enc/s5/f87A7RG58IbcxobaP/QRhR//YJI+/2CcPCsygDwS8B
oQwRVQJC8dykQ3pPuCfcE1ZPCIsS7kjlJYUJ14UJvcKEi8KEQWHCWWGCW4J4WAGh8EmsBJU3
mjWJ9dnl7gYhpCTVOqWW3QhebG80jacIZwgGWvzRMgRzxiimBaVdAoJVAsL8s+jPM4Y20qcC
XFSdaO/BckqCTacTfOpMtDvwlkow15PQzxCqMwhfphDeZQh4BsGeQjBVQrcwwd6dQTiZi1Dc
D+saDzmCXpBQPDdLv0eVeaddISFA6NEz9PDDkSMbowraRBUDbaEnb3mN3ETIEMVyzJOBqKQV
hZCtsVuZcjs2hvSAMJKNiszNwi4XwS4TIT20hvMQrHE/BOLgTNAD0abIXHb35DaQZvdQVHci
50PUK4Gn7jCOjN6+2GGGYpQZgnKK9KcQnBUQrJURTgUhlARXJZyqhPeSICqOJMjXyF+F4H1T
CbokNMcIl5JwqY6hM2UMHUEIBSGShEgleCqhLwm+IPxOZ1GXs6grhMwsnk/wwy9BCOQYgnk8
2SlDROUJ0bKEED9PCKYkqP/2uLquyl96H/VUitwMRPIumt3uYy2/w6z1Trv0LOhtEaycJ0lS
T3UwwI8Njk0fna1rKpVqzGq0y6xAwPEYmtA3kbaUTRao8U3NlFKPh8hG1owJw+Q1mpEJTPQ1
Y+lIeSPBXz0hODpcjDA2i/4Ivi1BiFRC6lSFAOsSQeqxjJskMYUkZcnbRpjlqytlwDvAgkY0
jGq0A0uEQcLfYFtIIi2qExzyymtTDLuO6YGtCZJbLfhCCEd8j7LYa4RLR0q4dBD+yR4nnAMh
bR7xnhY15iL4MWGg9lyKkGkWVgPt7/OqZ2km3T/gkhWERNqaSYIRr3q2hqGGmEyaTI74DdCu
AmGbVxwLLot7sWRFiUmoZHCFJGGD16zuK3x+VTeZbO1g4oH1EKy7Btr7TIcXQKjBay0undex
/AOEmkmGDer9gL4OJn6d+j+B4MQEZq2NEQaM0JybcJwQoK/Fhv6SS0dKuEpzArzW3cEDD2bB
CFVMrhrcD91q7MnED28OYj8k8jT2Q5D01fC5C54E2QJPurEnjzUYA6ymAwS4+u8RLh0mY6uN
YQwjfvfvwhL6Qy5bTEKcgTzGaTzYOQKZQUjigRHyERXNjupBNqq9JCYbAT/T5gkRt8JVmkCK
udBsY3xufzJZbhoVyM1KkrF8140lpDTiR+wku5kEq+ybzW5m1egZmuszUuUxxywLEfqFCWdH
XwsSyPeTcWP7H37Gn0mHu5lPAAAAJXRFWHRjcmVhdGUtZGF0ZQAyMDEyLTA0LTEwVDA4OjA0
OjI0KzAwOjAwvF4bUgAAACV0RVh0bW9kaWZ5LWRhdGUAMjAxMi0wNC0xMFQwODowNDoyNCsw
MDowMOPvbWYAAAAASUVORK5CYII=</binary>
 <binary id="img_63.png" content-type="image/png">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</binary>
 <binary id="img_64.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAgEAAACJAQAAAACd4dZQAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAgEAAACJAKNQXIcAAAWFSURBVGje7Zg/aBtXGMCf
qR23OELQQbROiZZClpQMMTEBWYendnNHb43pUA+GULpI2PETVpCXFg8ZGqjxecvq0qlDKwsN
JtBa3uoukYyT3tCAzjmwdPh0r993f9/JdyfJT1ARcoP0dN+n33vf974/d4+wnlebJGOkBdKb
oAoTNNZ8GwiaMKE1AgRlBAhNYcIoxIMw4YzVBAni2c0U9o7wjjBEws+Pv/7oQIjwa0n7rSZE
KI+AHzA3NSGCeIX5ZQQImi5MqDRFPfm3sB9GgVAVJWDvfhtisiZIEM9NrA/ihDgrni7enpme
migV5x/sHS1/mrpR/ovV2YUlrVufT16psAT6Welw/uXu0fLt1HTiWpF1mMlMU/ocCKaZXU8n
SvXT/NnxWsaUEuMblaXdo8WVmdRUogTj4tKu+uVNGBerJzBJ5t6NxGSxsoTzTU+NE1IW84M5
DILkjg0y8JUOrkGPmgbmkMMlNYvAxAiwm54VnRhPyK3INXARFUvQIgmkT0JfVlzRkz7BJO9F
EhqEhglU2E4uHgwnF8Lnmg27rZhy/4S7oQRIPc6TV1lDvwQJCFIUgdsLox1D2AonHNT5iDLe
xFhxK9yKH4OEVgyBhnuyHLSitRpDkKII/G6qUQTww51wwmaQ0InxpBztSbGYHCSixGNSiiLA
XpSdn/G5GUpo2Lnp/Y6rD1uhAvV9GqhykQQWVyf7qlGsR530CJF18vC77YNZIQLr0XHECdaw
4XZCyReT/fBmOdntSW/YNZl5+b9j8LBw/WOtX4IRZcVFgOBacXWCGw8CaxAnkCERVHcXuQaZ
4zQvnlKf7J8Mmdc9Aqapde37AUHGfALfeQ0/IFQ/uxV3mX4pMSmXaXyF0f3nOvyb48krE7yO
I0JwrKi7hPKgBCeilC2XkPYIOZ6Q5AhnPsHuvBZBdglSb4LiVTyuZymbcrdqkMB1f/3MJ/g9
S3nmEhY8wnqeIyxwBMO34lndfa4OXQNPiPDDZl04ory9aApH1GCEVoBgW/H6Qdq+t6/2JLT/
VXiCY0UjJLv5Rhyfm5I9iXPJvibjLpkbB2v10GrU/1rth9IvqOAaIKKcN1UsrCqx1qT6rVJi
vLzhCxieS4AcCR0bhnMqGEnMCjrJ3ray/Wwj219BNVsOEdUnIajGHIKMu9kJhUcRcjtUjHD+
7feUV4sgxFjR6vYDxsNgfmjDOEAoEHwaxtyE7cJcK4xZp0f7xGqx+4SakIsN/AqqefICWYcQ
gSqH9UDDQmDApM5vyH+TGu7tMLU6yxJiuqKOLTJ9VdRwCc7tc5dgOgSJW0MH7L8SIdtFMMIJ
eLtpEeQAAazIwpsq9E0z94i1DmosA8RThe1kqa6BRpoa0B+gnRoqEFAtzzRQy2aZfopyJLxZ
ZcqkbOYfMe0JEH5nF88Vtn2T6q8U9mKBGi81dnhHMkCteQvU8q6aXkG5S7grm6tzrPVTjc3t
sIs/gXBI9deg8ZAa/wDhG5swK5+v3mearab/gXLcCyTMAtwhbNuEFwHCQ4ugRBDAQLQC/VC0
/fDcJqAVX1GjAYSk5Kid5/KyVvStSOJuaiBKAgH2YgtEsG1VIIAnT0ADPHkChLRNQDXYTdma
SK+iHNcAb+yKBH4AAojmgFADAuxmEzQoNRQN37sNmKiJarqrptdQPlhE2fHgqvnxMDDhUkRd
SjrMTajhbUhKyD3D+pKc3DwnY7KnhoJ1Ev422/8FFYYKEwb8R6fZdaMw4Bq0T5Sg2WZf59XD
teLSVSCJiY3q/O7e4vJMyjr3XlKP19bupZPJUvXkRD1ewfGWpXKM5+GJaxuVJRhmYLhZrOzu
EfLDxGZxvrGXW8mkphKT1sn5F5nUhx+MP67CGFTvTScnLUIbJ0kiQUUYHoHD3cJ/SeVkMxoD
y1AAAAAldEVYdGNyZWF0ZS1kYXRlADIwMTItMDQtMTBUMDg6MDQ6MjQrMDA6MDC8XhtSAAAA
JXRFWHRtb2RpZnktZGF0ZQAyMDEyLTA0LTEwVDA4OjA0OjI0KzAwOjAw4+9tZgAAAABJRU5E
rkJggg==</binary>
 <binary id="img_65.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAgIAAACKAQAAAADwQh/9AAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAgIAAACKAA7pfeoAAASJSURBVGje7Zg/b9w2FMBp
JIA7NL0AXToEOHTKmkxNgSTK0L0fokPGDB5cw77SU70E8JAMBVpUH6MIXEQHGLARxIaWLoUB
y4GBqEMcyVBR6SIdmUfyJFInUSeVrns4mIP9jkf+7r3H94cSojMHQcsN3w7RbEKGrhkSxjRd
BMJ4IQjpFYET5iCiMnOCcW6SNWpIAEdcEa4IV4TpMTIlLEjnJcaEzJgQGhPeLgTB3A/mhHmI
yXnovMY388WocpdoxcgJP89ufTHGVSsI+xtThz6/+9XmJ4gN/I6Sx3/0S4Qh6j56JYLXoGqs
mQ8uj3D+44oh4cWeKcGJSRuC3UCINARfJQyRpSUk6LPa+RPUVwhuqiekTN1aFTyVACGnGzsa
QtCB8LYFwWskvG9D2NYT0jcawm7JitsNhDONH56VCLjBCk9DcNoTNFbstLVi55WG8MzYk/tt
TzNtFVH/LaFtVFsNhHo/+NfV3Dz5F9kdlrJ73mv1L/7XhoSf/HuXY4VtQkjyTrokvyTadtuv
IRS3vUx+OVbjMFJ/2GtN0Fkx94RxR4KbEwpHjdoQ3Cohya+9RN6giXqZTtiFKR9KEhedN7nl
T7bZ57MJgSxFfmALwijXkkiPEPWRIFJjQyEUNUohFI4ovc4r1Um3JYF0I5znhEQSRqoVvmqF
bCzBdk54kxNCSVAf8KLXKqEnCVs54bRKyCKV4GoI21UrileRWUmHU5WwJQl51xv9lRP+KQjk
b5VwpBJkiw5+q/pB5lhJh131LBRPbrWNh5kRlc6Khy4EpVLoCPUxmWdWGysUQnGnrcvurFN2
11aY0kOmr35wS6JhlfMurk7+jwTvgmq17Kes2bJzPZFd1pIt2Cp1Y9ajQzYLBCx0sGHBQIjD
Up/O0J0vT2HaEi2NHawltGWaOUNEsPCDx0KyJMaCm+VrhWWBFPmCWQRnmhA99TsTSImw8vS7
bgR7moC7WlFDGE8TEAJvL/OM21wCsVcQIvhvY5pQ+uEbi507S90QfQoiJo+uQcayzHyElhBN
7gjCzes0uSdE4LKch0dpAkcfAvfgBJNBxEWb4GIWI4QzXmFY3cCEl0xWxnDGKxc8MhBQOOLV
CLMStipXilkgiG2T+TQnkNmEWBJSSRjVElKVcDhN2PgBHsRi3k9z0bP56hQIfYckQNgP6LGF
SQLU/UP6so9Zj45h1usD4SHvOMGyQ79/KAi9QvR6QBjQFDrOMWwL12m863JCuAYizPYQWntJ
03cx72WqeJ+mh0B44pD0AU3/hLUBJhEQjoDggggENvsECL+KbauC8H4i/l5HiNfp6s9VAmw7
g22PpQ4TwtmEMBAEl+uwegR++FYQXgnCRsV47pL7Wj8cTPthA7zuwzYLfhjOiIl9LqYBECyH
jOAs4AZyjOGH4Sxs0AHEczgLPovQQKwNcLGNi5kgYLACCB6shROOgeCBH0CMgMBni4gKpmIy
00ZUNSZFXgRNUa0QVvYOpvNikoVKQlZzk3VeltI8u2/QTVTkJq8OlTHWvEKrayQt39M2js6E
B8G6IeHF3t0Lt+IjmKbMI7LxG5AAAAAldEVYdGNyZWF0ZS1kYXRlADIwMTItMDQtMTBUMDg6
MDQ6MjQrMDA6MDC8XhtSAAAAJXRFWHRtb2RpZnktZGF0ZQAyMDEyLTA0LTEwVDA4OjA0OjI0
KzAwOjAw4+9tZgAAAABJRU5ErkJggg==</binary>
 <binary id="img_66.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAgIAAACJAQAAAAB21m1TAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAgIAAACJACXELikAAASHSURBVGje7ZhPa9xGFMAn
+JBcytJ7yd6aj9BCm26/QSBfwkcTeijG3k5uOfrYS4g+Rg8J1pZAQ2nC9BpCPQ5OrEuJ1hFY
q0qa1/dGO5qRLcm7niVZjGW8+3iSfnrvzfszWgYXHgXb6Dk7YZ+CUEL++QnllSDkV4KQrEE+
rAGhgMSToNhNT0KvE9eEa8I14bKEqW9tXpHJq7wJhTdh6k049iZ8WAMb/OPw3xpk1BoQ/Gvz
enZ/coLieQBJGnDndKw/s8YtryDLX91vI0zY8sewQZA9pqYdetkgBAtEpI+g/vhyz88G1WvD
YgSZ+xEwDj2Ero21cAkTNuoEzNigVX+Iy2kJEroJ+Ty1zh7RF4ETBwnh0oQYn+sSnvoRYAWE
QY8XRx2EFw3CVg/hzw7Cr4048B6C7CCETcJTPwJ60UNYxAuQe96RXEFG+RN8M2rCvuskdNVm
9Ltbm3+znaUJ00Z1X6pXC7fLpY8jT8LRV54EuFSvFt4zqyYU7EEIG2Lj683LEmZmkt6wJ4u+
cXuOUE+K0p4s3Wc1bJCrJMg1sGGFhGQpgjhPKMy2V9kdtHI3043aPLQjuq7NzDxD2W2bcveA
jQ4T2/yPTIdxCOUihNCKc0LpTfC3ITsxhJklzFyCOy/ivToO9bwo3xvCxw7CXy5hYAmPDOHI
EDJLyFzC8w4bDCHLai/G1gandecnLiGycTBeZO8MYWoJH12CO3njO5bwmyG8vSiSTS8s4dHq
VnMNCDNbmzcuJrx7WROiFsJy1W331W0dpvF61tjbSyuKdeqTn3FeSKdXh1qza9d6iV7tzFP8
ojU8tFN2ROt6TpzP6ClpJ0zxarEC/OeVQ4JewmstiUegrSyAsgjofaqcWxZWhLxyqUM011a3
RVYkbdBFgDaCevBkcUKrDRHdFvvYkHYTkosIYG4LW7zAdaHJSxXniA9JHKDISUu1OSFxA1dQ
i1S6M33Bj2xUYBlGep6iSAPw7SiA27uQxRGIg5HiGVoj8I8rnqO5AgLFqZMQ7OUtxnihexQR
uNIE6jycOkyKV4eKl7rDoO7U6Oh0hjDSniU4oiFATTiGLHQIaSuhxQZLUO2EXfQYpx7Nst1f
oDwhUZKYo1YOQ1UgIcJrh1zNkPACOy2KCp+FogyQ8L2eOPEdJPwAJY6v+KYkMUetGIQ0CWni
HNzjaroDyXMB+yRuQ0raAWPbzyD7F2/7JoDtfSg/kChhvA85asVmqPK7kPyD18b8NNmB9A0S
BFcJEnAWHmwh4XFNGDuEJxXhZ03IK8JxOifEFeE1ajcZGz8750UFc2zIX2sv0IYwfRNrLwxh
y8ZhUEVSi61xGFIcwpTiMGzGAVczxtswEce4clqUJOYoilFIu5Jc4LUcH4xLKJCA4gmJpK3y
ga7lrQSOXpT63f8AczLFHJFIwHzAOk21ts4o4eZkR0ZVWR1XGVXWGcWYnps0AlGk2pwXmeae
ziuLcocfT38KqZweskZd6OI9U90aRtoJGylb3VjSYV3dRssW+ZUVoOV3gWD+vdDvtL3HUoT0
24h7Eu7GLYT/AW8WlOgvcNwLAAAAJXRFWHRjcmVhdGUtZGF0ZQAyMDEyLTA0LTEwVDA4OjA0
OjI0KzAwOjAwvF4bUgAAACV0RVh0bW9kaWZ5LWRhdGUAMjAxMi0wNC0xMFQwODowNDoyNCsw
MDowMOPvbWYAAAAASUVORK5CYII=</binary>
 <binary id="img_67.png" content-type="image/png">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
bWYAAAAASUVORK5CYII=</binary>
 <binary id="img_68.png" content-type="image/png">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</binary>
 <binary id="img_69.png" content-type="image/png">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
MjQrMDA6MDDj721mAAAAAElFTkSuQmCC</binary>
 <binary id="img_70.png" content-type="image/png">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
ODowNDoyNSswMDowMEWYZtIAAAAASUVORK5CYII=</binary>
 <binary id="img_71.png" content-type="image/png">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
MEWYZtIAAAAASUVORK5CYII=</binary>
 <binary id="img_72.png" content-type="image/png">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
mGbSAAAAAElFTkSuQmCC</binary>
 <binary id="img_73.png" content-type="image/png">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</binary>
 <binary id="img_74.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAgEAAAELAQAAAABo7mg3AAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAgEAAAELAKsnzHkAAAv/SURBVHja7dx/WBPnHQDw
C6QhtEEY3WODOH6MBOqKhUgfZIMl0VhKVx3t9o/TrQ2Ep0gFQbOuMpALFZSsQdT6YFN+hD5d
6/bYbc20aCdyIhhkBuLaZ24US9S4pD5FA4YR0iT37i4hNkiC94NV2qffxyeX5HIf3vf7fnO5
95ITAvQChaCvQrAC4PTcQZBTsG9D38ohCLoC4ZFTxD7DUEO+YDQkQMSC5ROohTQE0kHQGcrb
Y30zATMtwaYwgeBtSIgiIECyVky4soQzG/m+ZAnEUqSnExCEsoE7AhOCxEzP34aW9rKYTHFC
FiHBhAsQZyR8lZGRaGkXb+iMTXyXY2JF7ClJaRYTEsxeIWbVcKiM96Z0sDNWlsypxIQy3kEp
EaEHE64qOCMlmTGNJt4neRs6R4q7l8dgwi8JCONyoawVb4OCPSJZFcvG2oAL/OTMWExQ8Q/e
sxfjcu9oXuFCXAj/h5UY9F0sk55gJt8zkVgvgFeAoKgZwT849xaw4aP9voDunxDZhO1XsI6n
x39l+6hvhW8FACwLJSC0BQ1ZYRwGDnqCTQQmyAt7ZwmjMoP8Q2xzy27iwuv40UDTjCCoY3AS
2TKTxKImIfxDFXFr774q+7Fx2MavVRWlS2UhDIuai6ZxwggJu8XMCF4KJ1TC6IBtvERVaZbs
GSjUshuKDmslJrzO4tWvPBL+qphRB2w8bd1KztN5a2It7Zzo2jfKiQoPJISV7Baf4wG7ViXg
JHGvYHloL2fVtRATDq5j1vJSImL21PM8gyjyjqZGLK0n2AadgzH++BRrV/+E3fMk7BWQ5aYJ
F0xI8IYdxM9ahTWmn+ho+kJ0t2AgK4C7BTyQewg1wQU7IBQ1tPdRQtoC/TYshl7QFlDavQgg
wLAbhkET7HvstDf0v6EIBZ4CsTWcVHiOYhjYwQ8UAkGh3l6coX4UdUcInYWw2RKX505IGOyr
zXzDfJkMtpL4WCyMYPWmDbhPmIyeHBu9L5iGweRVVeVn8DTeH2dQwWK3uoAbf8L99vl8fJ8g
7EdAhmdswGRpSVZv/iD+fg8qwCnHMMEFgBG4bQPgunrEKexPhl/BX7Hz37dKyzKzDZ+OfZz5
RKRxjuCph6EbKSENuVEKM+N30F7bgKsjvWnN0SvHhUXv5apTd1zaJlWtzgJthofW1adZAwt6
U3GmYsnF2knGSV2YbRBdkamJCTXz28dSmeolO5p/Wm3JjINP68N551IsgXuhNx1pVhSdqZ9g
XPQKLOv3MKFtaH1tTuSO5uerLSsN+acvxNSdSzEEFoa2pkQnrbt03KlV6GDbDVTJanoyzfzB
6dENLTkjvz0YV8DZcKN814UY1jtpxsCCwSr6W2nx8JBzsEUIgBwbWaMDoJNlo9gLXK5p2NYO
XFeBC0bgAPVQM1MP6NxV7pnl+LwFhfoEV/DXOIgJ1GPu+wLBYTc1wYEVPgJEztsw2kZJMOKC
BhOwNjhgKkJ3w9lrj7RzEh8CXTInQlj4MpPozrc/6tuTI4Nk8R2P2TVUhMqRQ7gQggl2C+E2
+I9m1mvNdXVdsgdliFJmJZwHf6FTqVua3jUm+xy0FlMTsN3LTGUSTyMmwIFqUkRGoF3VQQXj
zNKE38BEBacGv3UhKLY0Ym/3IwBMKrBnHPL5GuEnIF4BINjGRuOUAU+ovRv/+y8TFITqZpGp
gQtMEhcnTwLGxKC6F8jWpb3VZCbYi4qj+5afaxD3ml9wp8aOxG8JAUUh8SW/avxL2LzVMauq
VczBV8W9t19w82KH4/M2wUWvxieUNaZFGogJoPJC3YS+MLf/9mZ3EiZsXQav/yS+81z9yrTL
BHtx7LXOh/UP5YFrve6x0s2gdBNQ9QONTjDR5CYoYDXwypwXXAX3iLsqiuBUO1geKMbCCs6Z
TxfDFzBW25QEDXDYsOMhg7OYuOCfSaRFXRseLVxSugZcTygmmtRZVf3afuaKZXHNK+si68Kf
IjjDmV3VLfu7yqLjDoXrm1Qryp3kBVD5+eGusY9cB5T6yHplCoU2gL8ebT6uejPuEJMDDq0o
tlIZixEHiI8XoUI40PEIkUziARPfNIhAPr6hwi2Zk3uLFHG30LpFxn4KpiO0ny+sKBfR6cVo
3ktyM5k2zBHGSiQ/WUemE3ME1IZ0WWkJpOO+CbDbs0vehQYXRJ5bBHgmi76Ho951fcANu6/h
T6Wun0+wYbs5fE4D2yaNHgFGhfgaAyY4YLdVg93n43v0gIKzMqff5mzRHpN3y4szgKpnQpWR
IZ8WooJ9yaVVzJMf9u3VDze9V8B3G4MI9jU5ku9kQ5C2IC5x7dJ47sP/VbxVUXBWGKZtfZyT
1VexQo/8XaJtrH0H3zKgYI3Niul5LCRXUCC8Ck3Fc6P5tR0Va14UPql9n8N+VFfxx5uioc0C
ZQ/fGUywxGTH9PxgR25EvqZ82VT8wwf5H/6pNF8nfOCE4IZyuu/EwCQy1iZQGvj4sVtAwfbc
qQd/VlWY21g2mrrp54Advb32rbIynbBa8ERq6k7mxeG+vZYJFaeAbwuayV9cXhvnfnON1oTI
i7PBGJpusG03TXfXxExtqwEnnMPYfL5qFIVXzldRQ9X+xyNaz2076qkLJziNH5Bj98rmEwLN
9owB63OxHcN4QkRXsOKClY5gKFx6UVdMR2gv1F3aU0VLmNKt1sjpCPprZ5e2p9ARbpq407py
OgL5WATCApyH8RNQ/JSgkY7gAmoANCIawmlXo4o7rNVQF378B3Vt6MZ0sknxPzJXqmtl6QnU
BVClUv9Qxkom2YtZ882ONqUU0iIk2+B/TsxtNUw7HCSBu2vSRnb7hXhfLOxZd9980+qEwQil
Xvjmm1ZHMfiYioA420bUGcJtL8rAVAXxeZKfsEO5v1a5LI7FS4w8zqiBCQJ+FYXubNn/RGJI
XDM23/x9hEhEPpNo5cjh4wlrUXy++cEN4oJfL3509F8fvLcJPdCIzTeVQqK98Be6ldMnIpfF
uTLLwRRMPJN3VRThtgfKJMX4v5wz98ZN/LSiG6EhrGjFblxHKAhWO2hDLdvgG93Y++TyKQrC
kFTO3lnIFDiTcvnafS4KQru+cEuGdD/DWfJcXRqLSFXMEdYXVsg37p9wSMvq0jhUBENq4VY5
9wDiWP3P+rRUKr24JQtlw2tRkVvTJ5hoJPJFSLDRdPWAL78LmjcWwTHMvQQ3QBHggikIIoCf
+YbBddiFuGwa7JFSQ14QobBlDBNQuxF71BRMEAaZscriHN3m3NVo9WVz/9jT545nICfICJaN
2c8U/iZHxnpXyH32s5GbJdq2q8gpUkJs9vnC5JxeplmYFTWlGYvQnv4PsouMYP9e9nmpWZif
YxZu7rvdYkG17xxBqsgIzrwsWfh4TiGWh9LSa73HpvfkCLrtZAQs0BgH6plv6gE4iY8MAsgK
vlnKzGkL8gLxoC/MqUmEJIDSn7HO2du/IhrW0RKML1261A/TEdq3nT3cS6onc4Sps48cptUG
/bWNUfTyYLXEOPppCeRjkQmej1kjPaENExAawig+YzWeIkv4CV1dbSruxvfJ9sNP2NWork3i
dhioC5XYfDNpaQoN4dSf2wRJrE4NdUHT5dp75dkDNDKJx/2Yby7sWRRaghOFa6g63l9YVaGw
EBOIT3TnCFOvC4RDkuUDlIXBqeTtbGYRezkFwDsWg+ZVVVtYevbzlNugv3V0u1S0vupT6nlA
bYLkug3srZQFA6D2hf1swUBboBzfCGGhZu5G2gKdWAzCYvh19Ne7F77fINdQFVB+pHcppCzA
4P4Lv94NdYRESdeKKAvl3uUX1AXYQlu44LmuAqXRiwHPBR902jBQzb0uotWGnqy1Uhm9NrAl
Ein4gkZFDSRINhcBJw2hNzxKUnCTloBo8V9h0cmkZ0knk4CuUO5d3qYuvNx/+PGcrJtmOr0w
epbUx0I8s5+k3gbfnhb+Wn9efMMEmPanv1fIOPPlmRM3dmTmRlruPEawKVS2E7+oBQFgWpow
cy3QnevBcUFB6+psTxtQuWUaSs8ReWes+PeLomkoo49gNxb39bxEYxEI9ykPbv9vV677CkP8
qBiSYsuoEM//W8CCHuXwuFBCiPhO6dArvKBxJqFK8T9+hLlm4hsqvwAAACV0RVh0Y3JlYXRl
LWRhdGUAMjAxMi0wNC0xMFQwODowNDoyNSswMDowMBopEOYAAAAldEVYdG1vZGlmeS1kYXRl
ADIwMTItMDQtMTBUMDg6MDQ6MjUrMDA6MDBFmGbSAAAAAElFTkSuQmCC</binary>
 <binary id="img_75.png" content-type="image/png">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
MjUrMDA6MDBFmGbSAAAAAElFTkSuQmCC</binary>
 <binary id="img_76.png" content-type="image/png">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
</binary>
 <binary id="img_77.png" content-type="image/png">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
KzAwOjAwRZhm0gAAAABJRU5ErkJggg==</binary>
 <binary id="img_78.png" content-type="image/png">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</binary>
 <binary id="img_79.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAgkAAAHfAQAAAADylnb6AAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAgkAAAHfAKIgTg8AABU2SURBVHja7d19VBNnugDw
CbAEd5WEbU+LKxJsXe2e060gbYEFGbt6+nG7au/de866171WSiu9pyJSKh8NMKF4C7tF8eOe
rgqKPd2t+49blS6KgAnFErsCoetdgRoIGGraA8wkRpnEJPPcdyZ8GEgyQwap7fXtISaZya/P
+7zv805CJgED/83Esx0YDFMTvjYq7A2HkjPAZY53367x3IwD2ADan8b42nKw+d8hFMMkvnYJ
hkrmYQYRCo2vPWLhFNGK/nX6JAyMwokI3BeBu8AK19GeiTEYFoYFY1gMNh/9p8IwOdocqwoG
fdCqYUREtKDbIejeIAzTYOMeuoE7NTkMigJLWVKONiNiiSoSEWMtDkWhfyelDRES63wNImKx
ILlExRFB7I8cERfT21giNa4Ck6sQkcYSkhi0NyaXs0SvIzUKEQXWjmZJGJaIhUZKVBLNjzli
KUfUpA9wxE8r/rEk6Or2zzOrIrdlxiw9HBlyYNELJzkCZ4kXrNt0J7Glpwf3d556d9c/Qtct
CelZ8vjhGJQLNyFhlpZ3x0h1j1/6eVXkrzKvLdu0N+Tqnl9xxG0uCoV1W9s7iGjb/0XJrl2j
y9bFh3yeNHwnkbq8vBt7miUiF5Znqpb9tjOkp89N3Ihy52JbmyriydNtp/9VcnCXOXTdIqzn
0PBhdkRq4rlcFC+tuBH0sOPxnsyDBaVFqmU9B0N6qtadXJBeoi9dzI5IsOXVdScjEk5f2N/z
WWNd97Pr5qk+//3jh7H/SUzSxPexBIOF9GNBZkyu+eEzmsR+LHg+JsFWh2DBOn0wzs4LhRkL
D8GkaFDDNFFBf0APUblHLaXoYg6wUwvViSpkYrhDJqeW4mBJjIqdWmY01jEh06fWyud/n8ZO
cJbwXyOKfp4a4WlCysyjScZ6GTnR3wxw+gPkEaHsrpHuW1uwpdijGs1fUMWELTpWrsLewWLm
a0zglH4aM/mYn7EXaawfgyoLEevR4C48iBG11wkobh9fTBxqGl3SgOMwagIXWpNsoVlOSz80
BwEeifdUORxKIHJoyN1Os6sW7m9JYzvi8L3omdEO4RhG+CdMAogiviiAlyjwuYNzLAoDP8Fw
ufNoFCtUuwkwcFs9O+xiLz4fI5KgggDLTYAcdKcM4GWEI8JlcK4fI8C2HG35DdA4uwktl8DI
ENELgxPEHgALGlSWULD/T7BzBLN2vCN2FIUsZ5ywo/0Wj9xJEFBdBrQKh8ceUkPKuoXPPweO
XY+Bc6+zgp28XBT/jkPiGrgR9yJYP9uH7SLgbHMlXJS1TRBorbYcI6A8RA3zH3sjUgaOU6Uo
ly79eC5sL+GwSAq2khfB3FoRrwKoXagAjczQiaY0R6RIgT6JCDTLEh9Jj8wA+6lycGnYQZWz
g6pzaHBQskQw0O88nh5KwJmkSqiWQef4iCQiAkVx8DIOSctf/G062P88H1ytLBHJdcTRjENB
MDh31wK9f2laHQGnIypBvwEm0mkrA0sJDl8uIqAwYdGvUC4q0sBlH5+diLhCwPxfg2vfGaC1
2W9dQLnQKqBXMUmouURzB24nVzEO98CPzU472NG94e6hgBZuWqjZWQGTRBm6jiaOdIJgQadi
Mgr2Xql7pzECzR8YgPFcJPFNcD+tk69S+YmxjuT4J4SsFzhfFPyEbNqGMdSV4iZssmtBHtut
NwgTTlBwgxVYQrX8MVX/ACYpbJS0vfuDSDlmjilveDh1h0WbxlDuZ3xM14W1qyNVUSGqy6GY
XPaoKmhJae1AWby60MENPfhvQp403m3C6ZtgJgnuqBXk83BlmjyahXndIXziwOeH2OJ3B7/z
ggvT5F5pfbcOPsL5/4ag+QgmhY8w8hHOKD6ieQ4INhd2vzsISicPoVNhaj6CZ1ANPEQ/xkMw
WBRPR/olvEQ0Xy6AtyOMAMLOT9AEXxS1fMQobxTHeQlL6Z6oNH9RnKmI2tEq80NYGdNHuo/9
EZVniNzb/qKwOOnrtH9CW5Sb4rcjZvpdU6Xfjkjz/RP0dnor5TeK2jyCh1hKv/YN5ZuwQ9Py
N5/4iT8CDXuNE3wTaHbWuEDrl/DbZmWCf38Ixs+zQjfRL/NP2Bl5MeGf0JE6HgLe4omig+xL
7pSd1bQu8EWYdlqqSxx7wmOnvECbINrIlJ6yyjM5Z10OH4Qxm6xIdNBN7yp8EBe3rxoo+7Cs
4eAtn1Fkk2Ep+cr6FRIfRAfZey3jmLRBZVb4GBFTLvlISpjyrE9CR478PeN8grLRQvkgiNzt
K1OMynoq2hfRcf2qac9Kx8URgw8iMW/p+ZT0440f6X0Q/Qr0rHvADtejcO8EYFAPaoWOSWv2
soPzjtnJAPggxpu3jnpMcF+EXTgBPgieMnPO0TFVSKXqeIgt/irVyc0L/4SLgZ08UehQpWoS
04cVHURRG+GN4Cq1LHr128bcaq03oo1s/KKsgXg5b3dXZiXujUCVWp1U90/6XHtu9xlvBKpU
Y1lDpEL5gTbzPe9EDvnDVSe/oM9F59rivRGoUo0ZDZiiYIDKfN17R3LJlas+iaD7onNHpV7T
SY5cy6hVZBVmUtve8J7OvO0rV/1tlG7ty92FeyU6Bq+azmzIK6T2Z37jtSPFecvOr8rVJpD2
Zb/r8kb0K2gc1EZUI7FSp5co7KhST6E5mqCmrCpC540Yv+6a9guycWK8UeBl/Z1CgDdi8n6D
tx1moczmiEDpJHiIfpnBP8FgO3gIHSnjISCP4CNGE/XaSiOTOirPLrOmrDB4EuzsPHWBTNwM
6WR2sDwrvcQxlWgjr296oaHMeOtohn74sLG3chrRkvf0+5lVm89vai3qSP9r0b5pxMXtWVpj
059bLEcz+gZXWb0Qxh2FRPLV9TWLWov0a0YKzl6dFkVHtJRuehWTp26OHmj6crHq5Wkd2WEm
Gi6vLgnuTet7+ETa2eBpuehwaY31O40tzKEOqimxp3I6kUfii7o2Nyo+/88++sMF9UYvxP4X
Drxm3Ndo6Rg8nX9gzzSiOG/4aPvpzYkv6hb05SxfmDg0bV4onPnQGtxfjDMvW8qKFR9MGVT2
mGrUklvwFiu6tZf4yqaYSnBXGKv7DvX0eTE2wU3uTdOKeXKC03wEAB/hq90rlYqITkI0oVKI
JtS9NaIIO0sUZjfryJXaAAkURb0+McQUQv4iAQ+YOKsnwk35HY0J6sCj6G2MNhX8tTHXG6ES
mIuGo6b8E+c+CZyo6b0aborddvhygB1BhGbx1xJTqC1aBIGaFgjvb10JJ3TeXhHNjAAxxKwc
U0UTs1SpeplvQsDUYglDMTh0ooh6Q+GKtAcd4ghl2bYdYgnVM/k/EpVOg1K3IX/IOyEsihqD
ktqwQxShUhRmpYX8SAzBvgK1rlCII8B3mc0tAd824bdSBa7g1QpRBHdYFt2R+l6HNvZdhShC
n/xhKm4QQxzSL/zLydTAo+COqSPb6tSioqjpJTP3JIkiVFGbqWONotJJnU8FK0OIyQX4meVz
VCN8B8TvUrF/P4hZGJH7gzqrubg30vm96ch9YrzR90QU90ZH6PsT/D5xn7j7xL1RZnef0PMR
LvEE/ylf1XNA8HeEj2DPoPNPtPASvKcC8hJMER9hEpJOnhqZixGZjUGlxBLsqYB+CScWxUNo
JH5Po2aJFJXfdylBwNnHqNjhniCCJYWM7fWMByzpxpugq4DGeU29Bry3iyyOuQTNh01gw9bU
mt/a5FybEb3xuUsb+9JT1mwKfwXbwp3QHCZF6dyh8EBJfGoUDtcd6TIAGKdFkXfHTXYuz8en
End+9M8Ark61PwI1WxAxlXB4xlmy3OPEFkS8yZ3OOPE4Z1Cy+xYxQZSg6O+YHZrlOJCT7+sj
YksSSxaP72BerUQPp+4kJAaPoXlVigPl9CSGDZHlv9yWuYDLhdXkaI1/a8uFOHyCeMbwSndb
+SPXOtu5dBYTic8+ETI/aOyNWT1LDG4Kbogcjs80sMQolrzXsvPEgMZNoDJDHUnfWHVI1/IQ
Fw2sliZHh8dVR0onoki39z8qaYh0xv8Xt8eoRlk/kH2iROPuiMMEzELDmsRL9bqWuiPcQ4ql
yVHhcWfHid+psNVJxmVtDZEjp9/gorjxiWPfN9kn9l1wR8GY4Haw4cWVA2dbL/2YI2CrITlq
T+zZyDXuHVBHVhf0J8wrDdr2+DwuF0PXbc8u2fnnZot7MqCDgENqSD9bkbjylZd03D2pUL51
Rd3GRfF3dIQkqgza4rEhMId6TIIqE/uLdII93R+s7lUUozz2KEJTy+5xl9XmMbXUKIqJ37m6
uBHBPc9o6UU14vGuOZg9b2ahKDSexJQVxjWt2G977sBf7C7x68UsEHb3xx1CsBhfn2eQgsb/
JyLGPzQ4tcm/ev2J0sdiktlPG7E1qpJPbApmL2KwR2KfLUTjl4W28XWEv90n7hP3idkm1N8Z
wuvSJEE/7muBEndgQgiZ2cejZUDYwCKEkJrHlmR2DcViJwkFvCmQCN3BrdmhGNaJltnYIGw1
14FdmILZIodsQbnIb5G7iVaWCJlY6xVMxsFrcUKI8ELroUFs3vG9H17B4o5Zd+1/Xv7g6hcW
lLNEt1lQFPLCSxFPBi14v6fuyvYlp+ouVm1sfvr5Sz9liaxum6BcBBe2R8T+8ud1X9Rd2bIk
rm5e1frmletzfrqXI8zZuAAiqHBDRKzqtfdZYtlTdZIDz3769C+Vy1VYdHhW97U4IQTmbD80
uGvVRz3Gy6uOP2ndd2DtmyvXX8pQZUWHoxERNi+cKP1hE0db+cS3DigYIlYYIUMEFublgB2F
vaBSLREUhd+vFJirMtO5AD1PZzJGXNC9uOU9y1lJ1b7J5zo6IcSiJzdJya1PkCNOIJ/StTjA
4ICv9Cmu3ygIV56hUghBgM/mZL/AQADhu7F5Dp4jwvcLbHYtkgohlH6jEEQ4YDFAywj3fJtR
gIvgThlDab6WzxK4YOIbYNwEwxE4mAhzovAoimpANx+93lECY3G+GlcDZFIGmJ6zxgolAObJ
oOUZYB78GcFEngpJw2F47wboD762A5PLBRL5MuhAL4AfXEIw5t0VaQoY6ZCBKVh4OpVMfhZH
PPUnghltr0AvPkfa8sD0AEusFhYFU4A6gu7/ZBkwZv26JQogsTXuKGKFEQQ7nMaxPdlvClDD
JYeWfWWCCKEjgl6/adivl4CxbxWAUvTTT3CEyBoRPMF9N8EjYvUfBT43URDT7hl/lFnoerF2
7da1lrbCQZBdVMfLbElK6j0X9VXNAxG1mDxCIjKdXBOXC49e3WVCpcHmPzPl6wQkA/1hqrjG
EIHp9H9AFJTOafnyaLSQdBL+CSFR3H1iFjoihMD9CS7xHbEJIvxGYc4TTcxCLu6NeVGlFU0E
unZ6NCEE7p/AhRCMX0JQFE7xxIhVWp3UIoYgXC5d4fsGUbmwuqh2nUJUFPQAtUAkwfTCiGiC
vNT1sigCBsg3ug3iCL9tjgjcP4GLJ+aqIxNvIwQehcHPJ6oEE+fzjhHWUgMRKIH39jbVliky
TU1dVKBRdOuJyzLFZnpnwATeo8e1G4Kj6R/0ZwUaRa/h6gVdVDFd5PVLRgRFYei1n9FFbaeL
ugImNIvJBF1wNt0WG2hH8PEr3k82mGsCvuMEIb5ScYPBIDYKVKnEJ9lUN3t8dgREoEptTNj1
Fl2dpRjpSgiM6O4juirzzhWD4UTXE4ERPfrkzzaMvlM8qt19RRVoOhtadaOp5x1du7+oDJDo
vXpFRzJ9dsOJy+cDIzQKVKkdraRLv+Xh+oAIYvyKi/0AY2BRjF/x/pu6uSbgWyVmo1KP4qKJ
PopwX2UGTWqnIxDCMBynrlzU1V3Q3j96pP1m6syJTgOlvkoouwwFugbbLVQtAUShj5aZlK/L
O/Pbkt+5NZwbFADR5/rYpBz6o9SxIvmo643cxEBy4fi4621HV41D2XD+pnFryswJzWJbXFXo
jzo3Kr9O/nTx1+sD6IimBg1kdRbDHhCnf7BKEMFduijun+mv04QTY20WCPj2CLNUNHGLpsUS
NH1cPPHxT2LTmlr/zRQwMZpQU9BE1nc9pA2ceLjmvV7qKXoPHTBB0+qhXvKpM++eEUHQVC+z
QH1FDLHyxVVDRz76R17AhFlqDysacEkNEDAB7MGQ8vHW1YwIEEf4bnNHOCWzQLjEEi7XN+KJ
IVN1FFgbXTaLtqQlSl5ATRzthRL6ob9nJa/I/me9bfDAkS/XFzrVE98uJ5RoM92mlRU7W07d
Jmubeugi8hc7a2ZI6IY+pZXtmS0nbpClLNGff1MxQwJGUBQtmf88MUpebuoxFVG/sBgmNwtL
58g5U/LxzE+OjHbUNp3LKqIct2aYC6eE/FSRn6WpU/dvtjY5FEUWacUMOwLs8dgBfQAkMTX8
GRCeT36JAAif7TtFzEKxu1zD4okh+mg0WM+DzWJq1oFNGUildmQlZ+3sqr89aD2SatTfOj4y
0yh0JoZW7snTcpX6ttGAKnWmRMfQNVSprxmbGFSp+ScV/W/PuFKZkS9ppS7LcoImW5ryrQbq
7ZmWmQuoc7TyeGZd0yjqSHFOL3U7b4YEqtSLskTqmbqm/s3xTaHWXktZgJWqB7hOuO+YfOAM
CFSpjPsDAYTH5pkQHo0IgPDZ5oyYhSfQNC262NETPtFEHlVJDfj401ICiQTq1tBfRRGjCeTN
sBXBoqIA8tYlSiGKoCmLkWoUQ5il1O7hgVIxBLAn5lMA4gi4RwiYM6LyrlWq1VomlqCtatFE
zvmb12O0ooj4yptag0MUkXwm7zmFURQBDSseqrGKI+or/2aoFUOYM2qP3JSViiKkZQYGzTsR
hLcdvxUC7hP3ifvEd5kQf+7a94Yw3xOE/Z7IxfeGUIk/43bOziaEe4KQR74kjzj1anDlo+Zc
PPTX/5tp+ey4KgLDwn5fHvaXcpkQ4s4/x4eeODbi4jqCiJtPzpwgjB6E+U+e58YIIXbkUDA+
tIg49ieKI1wzILYkU1BvIBnA1SwxoKKq26+qm5wzIP4luW1TRGno6/+xkItieD0V9lnzAfkF
d1xWIURL8vCmB3ISbaGfc1F8s5pML2mND/1v91ZBZdaSRL7y25xE+1YjRwy1kOkfdCSE7nZv
pYQQmgLj1o05iUNb13AEtenavJLWp1tXubdeFUZ8nRtRFrpt80KOGFxoidR2/DH0WXcucCGE
yUEC+3KZfU/YMbHH2COZLCHEjYnvGOCi+Cjkzo2MoI6YPYkpf85I0KBOaVPfrwmAAJGELYu9
9HiTF+cneP6wMXZXiP8DyVkXU7+/q6cAAAAldEVYdGNyZWF0ZS1kYXRlADIwMTItMDQtMTBU
MDg6MDQ6MjUrMDA6MDAaKRDmAAAAJXRFWHRtb2RpZnktZGF0ZQAyMDEyLTA0LTEwVDA4OjA0
OjI1KzAwOjAwRZhm0gAAAABJRU5ErkJggg==</binary>
 <binary id="img_80.png" content-type="image/png">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</binary>
 <binary id="img_81.png" content-type="image/png">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
gg==</binary>
 <binary id="img_82.png" content-type="image/png">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</binary>
 <binary id="img_83.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAbsAAAJDAQMAAACojii0AAAACXBIWXMAAB7CAAAewgFu0HU+
AAAABlBMVEUAAAD///+l2Z/dAAANJElEQVR4nO2dX2zbxh3Hf7QU02sdUy2CNENTU/2H9mFB
7DlADVQwHXRAB7RA3rshddst2cuWtgsad3VEBinsFtgaoQiEZBiiPAx7dlEjS7HEousg3tCg
HvrSFcNiJk6d7aEVFaUSHdO83R0pRaQsiTrZtNX4ANM0yQ+/9/vd7+5+pGgREFMxo9AyIDQB
8iZ6/UVeRjLwIYS+0TpEvCMzj5CVOUVWv+XIkYsZsvw5PmzR4ClogbdEIp4NWsUhEIuuAPop
zYERbogNlIipfsq+F5ECP71/n+mAIjJ8UCHiWvxjCXihOyA+kS9QJy3IAmaLoBoj7SgW/FZV
NwfBIKBmg9N+wWvYLWUg/4GftrQVAXTBkOftqkKX3JCiIU3biiBYCX/gbVtRPG6D4WeR5ldR
xYqWwNtgz0NIEVS8r+u+OqBmIvMwb4UEG+xTZU3UAJ3pFmvEXhG8wyNF1AYI+KYi69ADt7q7
364D6hjUeaRKOlHkVJA1iIW07u6RWD0bkTnMI02miiEFkC5aoRsP9Q/XAW9TG5FqBwAZaTTR
DFm8UQ8kir/DNko2yBMwxmFwZKS+jbd5BDYYCuE6x2J4uPOlGOetToHa2BZSZR27RR4zRuK1
QDNNFA8LpmiDYeCQNhxT+WNaTUXcjahXcawet9sRn0yPjRj8MX2gFmiCqJky9urdIOeJVxfn
OK27VgBQEAB7Fd10FAWk/9BatDidqwOS/oi9andkBKQ5nL01vQrSNaRyBgWpIh6sdGfvQC3Q
HuVKihauaVGxvWYAyIeGMki+w79y6OjggAM6ioJeA8zv2RP+4sYvJvhxPQoxp6qOIled8+zz
2ui7dBPwkV//KMoE4gnYOwfXLTtJO7KU7pVygLVWROjLu+lLqiyVsUioyBb+/Rv7D1Ju0iTH
lHE9kTyHcr8cltGh9week9MXL6hCBp3tPZYxd/fAww8f+xUoSw9v0eB+8dBzUVhG4uKgMHKU
pGSn4NGz746HT7YryW3tiUQiCZBU2hIQCW9TFIDwExN4ESarEI1CZxigH4CARy8VCggV8l/i
X/k7uE4L/ZYhmYP9MQtdG52cROgcl04vFj6AWYRGd8ozcxa8jkELNVSW7VSOgLJvKAPwH0PF
I8YQNAYulFqDawz81gX6xsoVgRXkaIZ8kxGUc6xVZQKhEfCyBywwKvq30atog7Kzt1pAmDEp
b0Ph8qqCLBXBI5RMlwhFdkCxPHIcECc7Nqjy1gF6YOpU8URg7zE7ecfGtjIbLXjMC77nAXF2
4naORUEpL9qgYMVt8P0iGHJqHeIIGHV71ZIt+7wzSH2LrqVSCC2R6yl7B+78x6e8isRGOR/j
KWjBAbqSOq3FsjMUNAWxG8+OoRDxKt8DZPgpKcbmHRApB8gUik6cugvyYhfexvPEq/ygu6rw
Wj89Xh2I2ODYDq3zjVnqnBgvdgKyuniiGB4/6wYf781ScGf8wFNkZaF/7ApVxFM/J75nIHOn
SG3UXJFjdXwcodeXanfcbo6FYaVTm7EVp9p3GCRyKDju8ep8D2c7pwy89DwBRYMbHTZIKFJw
iIJWyas5W3HGLAN/so86R+cuYRCXvCdylij4AHLAVymo9Z8wXxQomP3ohg3a7cgpRZAoSvMP
LLqqqg2fuNJpg7msVg6CC5TLQBoqhnFiVhQdUDfugkOcZttYVNxBbfy0HV57yAYVQZRsG7NZ
A0o2jnNni4pZetqdvN074OBxsrJoaKIDmpxu0rPSEUDjBsu8ituk2wGVIqhLKVppDGatUKmq
7nYkhfqEGOoM0Euo2LH4JdI7bLCt1I5OyL1sH6RyztHK80UO6QlnJV85ytFM0A2G7oIg2ytl
/TFe9GolyFeC16HUkHdtnPMaJpRAVJzRrt9VtBqaAnIeG5fqIxU2NjYF3PKAiwyKxVhlUbTk
UH3ELldKnJ2ujPkFP3eBpfmtfrnsUWQEG1C85A80K7bcKPMqBjs7s8D98w+7PufVg49gN0eF
b9RoOzwe7QGQ/gvH2rnM1F58ibT3H4NuRQWUdyHxbnh0e/IkJCKJSHtESSTJxci2SBieUE4m
wmej5Ohw+EIYLyaejNiRY6LCHO4dZGFNkShaeHYar/Y/dgfni5Nx0lHyhbSs9dpJPznsjbmm
7nZ+78F1uYdMy3f455kvyUBp5ckVGLmMuZ6elDJ//Vu6D6GL6WMpRIa15eVs4QsBLRNwTEkm
E5HtyeSD7e3JD5MJ5cHkh9uhbXsyAT17lJPj45GJCXJ5hZcK7JmIjCdgfNxkvH7kVrxr7aOE
WBUpKMolX9mXapll8kNvqH8mkeUhckRGJssOYR+ZTEQKsjZH8GCqdUCh/mErg2LgIHNVmUCr
dcCgbTSbA08ECC6zg4xeZQabDACRCYwGDgZf1daaOzbBRkGpPmitBFo+wI1i45qCLZQD3Asg
w2zVZA4gsoItkucE3ztaKHtssXYM3kam/tgUKLKA65DLbYL3ONhaE+smWA1sJgBYR/IVc3Jf
imzgetjYSl5tHRtXSdHU8JYlQwMBTQJeJTfDeXQAL+XaYPXHfIXaYPXn3/gK0GWjWv2eem1F
v2BF1jFFFvSzU/v5qzQ5u0TWpitAl+IUqlbcexoA3YoVNjYCikEruvuje3cN0DtYVQePBw7W
qar7vA0oVgcrFN1ebQBcJRvXHvTG6gau6qq1YwPOWfNuVQf0PQK0UAB4R7m1r2oLgcwB0Myk
00Jg8FN56+QAm+CagLOsoOu+XCPgHCsolm8IIkFqIXCVcrnN7HETXHNwHdLOVOCKzCBb9thS
ARB0O3pnq0ZAl2Ig8+O9oLgJboLVdtcGU0yg/6GjMntkVhRXRZE50d3YI/nqgI2knanyDWt/
6+keyTpSrKC4qbiRFNkGZG/kNNCtLObbpMwg86SzOoqNjDmsXmVXZHYOcw7AfM8q+HQl+Ltk
wVa14kG7aw0oBp/LiazgWisGnz22tI3Bg2LgiquTWQWSrzLnAMyKqdZRdIGNNAezosiqOBe4
YooVZO4dq5PnbNwZmR1sxjlzTGAzWcfq2MicrmzsXG6dQ64Rr4rVd9cAm8k6xOq7GwDXQHEj
3M9hBlOM4Ho/S7ax084WAsX1Buk3uqLPEXlymn610kKaTBWhOmDpIe1BsuCqPqRdkXX4fizc
61WtAdA1kld/gl2oAF2KRqjXwLbxgoKPlfGwC1sncfV//5hZCbL9X4BXsREweEW2f/JlBr0z
ciNgKnDFTfAeB2frH1ZZKnLyRsAUC9jUCLAJfj9A5rlDDBQ0WsurYuCKwYMtlHUEr8gMsnqV
8T9nm2nH4J2TYgKZp/Jm8tWAe0drJUibYA1QZAKbmHSYhw72MYcZTLGCwc8d4looSqwgs2JN
MPgcQAxcsYXu5wSedbRSf2whGzfbsRrImllZrFUNHmwqB2Aq6wBCyyhaNnj1JfrXV3Q5h9DS
1aP49xJ5mDZfyMetfP7N5wuFfP7AkULhdu6z/ESOvhSDfNnObvLmMZA7pC3QGd0FwJ3lAMJt
0AFPO59a0E9OyEcnHTBof8/8U/ro6BmFs5LJZPic3J6AbXjtHEQi20+OQ/iJCxcgHI5e7IVH
O5/cpTy6ddeu2NandxPnSOTVPaVXcUiGaBtRZlC6tLZcck609P4O58i0v9yONof9qhHnjRTS
Bz/w87YTCroVRwHN+wNll+KACf8L1SAqQUfxzDCn8DWI6opP7z3jgLVqXOnVM/BKaswn6FLs
h72pMXt93kSmTNeyPhRPKwSUfYEu55zHAck7IGoE/GMbKPXB5UobP0EGUdQQr86baqzr5pQu
arroAY2ykLOKoCXjk6hxXslhMHxQ1QW1AtQrY7VX65JwDZUYr/aZameY117nlR4vOF0Zq6e1
dnHOlFOnkNVnzl6JC1ZfTur12jhdZqPT1T65Por7t5w6jbDi7KW4pPbl4AEvOEbAZxxF24Gf
3FxwQIUqrgwKZOg4suTyagkEqjgAGPRW1ZSIYsHl1cXCAvYqBi3JBgewjd52NGME/O1iueLi
wmUXGJcw+JEHNA4T8GOX4imtfdilSECvjTptx5zLxvPLfxmRzZCyQ8A2zlzuojbukNxgNlve
jrZXz8hWXDI5DUcOBmfaJaUvq46IbvDredqObkXYKUtWCINqn5W5OSqrR3Ja3AOemKlU/EqB
uMeiyvcmpVNlisUgV2Co3ihndcvlvcNWPOV6J9bKxYzRdkQuxfM+QOPw4XLQVvyXPHdMrAPq
uk5nZCdybPA8CHWTu2wuV2njn7wf4K9QxnLz5Yr2xkkf4Mz09IrJQ7oeiJrJc76HoPdVqBic
RVf3/3u/fFXe/8I7yIq/87M566X9+99GS9ZL6PLVW5/mMvl8/url3bfzP2579a3bk1/cUs/l
x/8OMPXd1j8D9Co4seK2RvGyc4uCVy+eLT2CMkjeFXh/R8WTHm1VnwFZo2LAKxx5mzuXSpnA
P7Vc0GDL1zit5DgBaTC0DyGA+zIZffA18yCCthdmkTH48hzS/g8ViNsS+3yFogAAAABJRU5E
rkJggg==</binary>
 <binary id="img_84.png" content-type="image/png">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
F8Ak4f8C32dz3/0Y91sAAAAASUVORK5CYII=</binary>
 <binary id="img_85.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAdcAAABtAQAAAADb2RbLAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAHsEAAB7BAcNpVFMAAAAJdnBBZwAAAdcAAABtAGzNj8AAAAOxSURBVFjD7dffS1NRHADw
sx+5QdMtetEGboRMelsa5UNwu9VDksvnIMHIlF7CB0kl20YL14Ng+GBo5qA/IPIlettsUT5I
F+otkA0FZxBpLNhd98fpnnvu5nbvuXq3FSbtC5t395zPPefec77nHgGsOkQg7FODI5wKyX/e
gzT+HddWscnf6ZCmYAefAuAd/u3R2nb5e1Nrs/e5XB56usBq8kNT5qeHYO+5m0fdpozW5vqX
Iv651iD4GLH00GeoXoK1fzl5tJPQ59zAowiILAbB6tyJy92+oJNgt9567UR7zeEFkfiEZJsT
tC1oI9l1cKWT1Oe7Dch2ybavfSKjqSEOrgyCq53rWrveNtnvfRY3g3Cy5zN9biKntWb34Cc3
qc+JY69Hl9D4Ph4S4AYkhHic2iYNO4RMjEcXFEEM5iExRA4yUCd4uQIgzjpDgWy1Ubd1W7eG
bBpQes6ELQ9sOjYBPOQCvmBZYNGxKRjTsVDAloPZGixXqRXqtm7/MWsgFwzkoN2iaylygQgi
++W+1GmdEAprjl6XjVjub9rv0o2F8GGeZFknhFF1c8pBWCpW7A7R9u7uhGMqOwXhDwhD29Lh
Jj7DY8s75WeV/zaeaT2/sTC2NkjJ10gDHBSEixGHd3nSn2ycvSXiIQLAhCwrHUiDlN/yJ63N
N62uPl+MUduH9ieBs76LjbO0vC3jw2ZsOR6gBTr/NXx9ZOX0iIu2Tstd3VY6H5fsvOlpX9R3
yeGiWeVuoVDY12Vle2N45fSwiwaeok0p9s2paJ/tJW11dWfJdnJtJNkyMBvwM4zazt+Z6W57
ceH2TCBNtFte6bomqyvQ4dHYiMNPN/iTR2ZoooXseGaqa2hhDEIKqiyMxh4wjACnYXZHYzk8
Y/jSOVVqY+XTE9V71STZDiduVzUz0bsXfQh5iN6+0uAAaXht8kcdaSnvUe6HTRrLUy1S0zyQ
V41fFm32b0vbdrTmxLUbf15er2TLEVedQ2eZPSyzj10mWk4pEwo2q1gWlEaozIbLyiiV5fa0
CXzSqpTx6nbLIrnH/SaNPquU1qaMjlFqzzHKVm4FY9bI3OB07XNlKSi1uzloIe5k08CJc5Cc
v2iJlt+grFRPa3Huw5CmSF43hMK+Xf8tSgyh1Fb4v/dhtPwB2cPY54O631qfFV9lLhRyEAWr
v5MlNoty31y0loosWnHQmoNvt6JO/0Fb0YMurpP/jeUPyFbfZ7HGZ1XL3KjNslXN5+IeGEWF
+Ytzv6FgnRVZ3PpvrRprmhBA+eQAAAAldEVYdGNyZWF0ZS1kYXRlADIwMTItMDQtMTBUMDg6
MDQ6MjYrMDA6MDArwQp7AAAAJXRFWHRtb2RpZnktZGF0ZQAyMDEyLTA0LTEwVDA4OjA0OjI2
KzAwOjAwdHB8TwAAAABJRU5ErkJggg==</binary>
 <binary id="img_86.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAIUAAABNAQAAAACgGppIAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAAEgAAABIAEbJaz4AAAAJdnBBZwAAAIUAAABNAB54CSoAAANaSURBVDjLbVTBilxFFC2Z
xSz7B8S3dZ+FE4TUrwhZmGVkFk5DSAWzcaNv4SagpPIXuvJNGPSNEKa2EeJUNy2puLG6UzCv
i1evjue+Hjdi03Dp03Wr7jn33Kvwn89e/T+ijuYf50f/Ilt1riVcKn2LXKRyzLAeS3NA6mKT
dxIG7A7IvunTXmOPCAlEUtcGWP7vI5oZ+dVYF3v0Bh5uRj4EvEsSurgRpN6tgP2rLlFNtxak
nBZAvyrjxPBGkDzkCeajJcYM/GyI7JAyE74DiBhNZGNjGks9hguY0BDpNUKaSq+tw1QdkW9N
h4D8lelY4RSIPIfpXBz3rMGTABEt5bhhLPwHw0jElGpgwzJXGB/zXlXDh6CvHrEGaD/tVYnI
TLjnQ0JFV/Yq2zhIaZZ3MNQzlfkCE7LWGCitFsR6qdBoakg2J0SMd0GYSYOmeqIoNnuSRlwb
SFU/qTRVY3yfxjfGII54poaREMkySNrwWoUB1FD6cAiXKoQhr4RZJA107lJFSrHlDVTnCZ+w
gjhsl3zQ4sIxfK2ueHJ3h7c3CIHMPlbXpJR/zJSkC2FEfaD+4Mnv2/QbbjQfEW94JtxpwwWK
+dzFhJXyear3FyRb6meND4KkXFaLzm3SJCESiSmvFsb2aXob2BUiTFi/RWMDwnvSWCnL7ro/
SdYhiDLnypNSvyNLO99uXqhro+3Ry3xdP2lCINkHSnx0fJF+r1/qJ4s01ndqg/mO3RR4GAnv
VE8ubFbIoYpJRiJDrlXDbaigaE8NI7WHbgPTCcVZQ8lr257Noskv1dDRf6yDqo6i/Ws1sKVs
x+ND/8B+vZ87k7emswyVyJYnqfiWY+OQJtAJQskhT5ZmZR6Rg53WhxDymZqSMLMvE++ghW7O
VJm903xzcyqO8H+f0auBZtUUXQoVZ8IIjceaBpVC6V6+St8W8ylkhDDOCCRvyUEZcz0l0hqR
otCGLGeenSsW3cf8SuyEMRJZ0/tcAb/ICEV4mVMOim/xdC50RrJo0Pi7czmQyS0yIfqHR5Si
mufzTjAyWScSKpbz3mjYJXyBRgYszUgvRffUi8z6w/4BV0qLDcisPewojX6rwa+73VG1oY8Y
NPztHuOSwlOGBSQc9uHRQwqA1b3t7fZDVR/IaJU57P8BXoVJ1Pd64wcAAAAldEVYdGNyZWF0
ZS1kYXRlADIwMTItMDQtMTBUMDg6MDQ6MjYrMDA6MDArwQp7AAAAJXRFWHRtb2RpZnktZGF0
ZQAyMDEyLTA0LTIzVDA5OjI1OjQwKzAwOjAwwaWk/gAAAABJRU5ErkJggg==</binary>
 <binary id="img_87.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAIUAAABNAQAAAACgGppIAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAAEgAAABIAEbJaz4AAAAJdnBBZwAAAIUAAABNAB54CSoAAAIESURBVDjLbZS9btRAEMcX
kEh5j3CPkDYUyK8F1aa7MgUN3T1G6Bx0xdGgbWmQL0rhNMiXWJHXsr3DfO6CwdLdf/Tzeudj
Z8fB6onu/8S9of90fWHk/NZ5lPn1tZEjAL39CrARkiqAJ5EHIbPnX0SJQnrads+C64gEIoF2
A7hhsiWzx1XsBEkizzCKTERmDnUWWYiMbKaPIkR6yUfFI2nFPIrUSIKYKg2SvZg7kQ5JLeat
yICk+qtgU3QSGcBLIWKlX6JjdLMub0TmQtRBik6SwITUw4d/yJWbzK/6/OL61Ql+doOl3qzI
YGt+GMnom9PyQJcJWWcPXXOEOzqVR0eVWpDUR2hDIZiCr6FtuTeUJIywHfKaaQ/f0RmvOblG
yIFIyKQPMGB+520mpxuO8LQpZAOhw68eMuk6CE0LbV+IpEJ7KQkDF0zXkMfdASPM+yj5ieTu
IsdMQS74uvqTDJMWKjqtVGc1fLQaWglLVbvQGcmHkM/CTtCvybOv7AT13Me0XRFItXXCYt0C
1j+ZeCPWddqzqXSvPnPpcHW1lFvwXqtSbop2aI+kEVOlRaI5a+UCEk1e7yDdOE3jk8g+32V4
J1LRBJBYJXa+3ZKQzoSRCQfUS+w9k4O4CiJEntiHjSGbUfjNIiXhyXYpc2zLwuSeZhPPup2S
WEVyFD2JzExuHJRXxH8DBxPHT0qThO8AAAAldEVYdGNyZWF0ZS1kYXRlADIwMTItMDQtMTBU
MDg6MDQ6MjYrMDA6MDArwQp7AAAAJXRFWHRtb2RpZnktZGF0ZQAyMDEyLTA0LTIzVDA5OjI2
OjEzKzAwOjAwU5oLBAAAAABJRU5ErkJggg==</binary>
 <binary id="img_88.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAIUAAABMAQAAAABrRkntAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAAEgAAABIAEbJaz4AAAAJdnBBZwAAAIUAAABMAAdjOGsAAAKoSURBVDjLXZSxbtRAEIYX
pUh5j3APQQFUfqSUBEFkpEik40qo4kegoEmB8EUpAg1ug0LiI1eYbokssd6svT//zNo+hHW6
9X1nz/47888Y/Hd1hl/RPIIuexM59/2CywZxOZITDBdcjvUjpF/a0HHJgPtEfAb3kMFDqZBt
DutWcBJ9qeQbiBqshDRKspij3iITci8k5gMfuiEWNUIG5yPyz69UcZ+TBPsgfz9TEjMSVwMD
8DgdS4gtawSgSqQmuUUttyOpSE7lxuFdIg1JyZcpekxPS/KSikrYkYTOUFlPhbdHiXiSyoEK
45DI0JmhaEDR0xU747MKYRC1iRyawLAu9D6dHTg0HfLSuhCm156a+4iynuUIafsoIoEikTPj
+DxDNRN5b9ByyUnG68o0vKecekcqHmkT8YE/1vlIKtcd4YAJWrPs+EIC6/No+WgjWftlblms
n1oZ2EslP4DyOmNkJ4UVcs3sfCxYkAbWKqmZiueFpvBuoR6r2yE2S5Wzkb02pm4CNgs92d0q
EWZn85ancqkgQqxjyGwijMzKVI0mWklnCiZs1TLRdtJzw1TsX0D0NEnzdxZrdUyFFq8XKU6I
c0ahpApjNe1MtH5lNT0j+ZHc0812znOtbs8nk10ZsVNAcnOqzp+cJf2nB0mkKxzmMp+ZNo47
l1PdwyD1m0sqRAyPajuRQ+PVhsXXcTe6rrfSOyji7MNYWz0GZq/G5MxJIh2OjM70iC92pKRJ
W8Sw64tTxmhmydI7o8LVrr+2kgo7kaITZ4p9qyeJSJ96vpfjNO0Vpbt7yon5J6+k15lwAN+z
oVSi17nBmD42qXdaJZc1Wl+lzao0f6iwzVIfpInUZwU2OceKDBIlnHD1OfT04xzDG+TiihNg
fySdMbL1b12UYL2netPM/AtIlo3xowu5VgAAACV0RVh0Y3JlYXRlLWRhdGUAMjAxMi0wNC0x
MFQwODowNDoyNiswMDowMCvBCnsAAAAldEVYdG1vZGlmeS1kYXRlADIwMTItMDQtMjNUMDk6
MjY6MzYrMDA6MDBDhyPeAAAAAElFTkSuQmCC</binary>
 <binary id="img_89.png" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAAIUAAABQAQAAAAAfUosNAAAAAmJLR0QAAd2KE6QAAAAJcEhZ
cwAAAEgAAABIAEbJaz4AAAAJdnBBZwAAAIUAAABQAOEUZTYAAAN5SURBVDjLjVQ9jxxFEC1E
4ARpAhIkIybkL9xJ5pp/wE9wQMAPcHIWH33SCR0J2tCHsOlfQG7JxrPIwZyFoAMnh06+sT2W
+wJLs+uWrmc0s/14NetLEAEbbM2+ne569epVCf716eX/IvLe/EPev0JWImYbrpCj2Bca0qrc
IlMZ4u98LLt4tkV6g7CyWJkmrLbIa+vw0qC1VXNpZuSXbFAX+BEWvpgRM1k0NXYz4GpFsp2y
xZNsN9nap4r0zJbx8YSR/9xXJHoME/ZueUKYFAkupGH67lOHNPAKIt44xB6FaRCRDZFz0gnr
ycEgjXBE7jKpjwPpVEjwRHYB6+r2VxKruhR6ybfIgyUBGrqWyFfKw/w1gP+gITL5uJmyuTsk
krHVH71sXEeG1g4MGfbvXga9o+eBm4RYUC8jk3brfszGd3GD3MuKh30aYrauI8O8Ly+UDvmT
DqGBSKt0HOk8AulE7EtQOs4H/JYpdBp3hG8Sqmo84HEg3RdmoGBUJIF0EI7FN2FNOg6dils1
RODb5YQSHgefkcmxNJRi9e2mQeMPrrNBP8g56by05E/dalb2kTxjSYc2KcOFj1M+lQe878OC
SIdC+3QqFXOHsnN4gy8WrKyXinQC6WDEskSXLsRhPb0u6bq4WZZVEy6kYrOWn2jPxj89hSHi
urAsyDAE/4oMT6SyqM88LQRftxnmRB5Z4498PzNUrS7kIRkWR+A98KrVhfw0AcUhEQ8pZoZ3
tFnsGfsnhvKdSq22MwvgCTVsuvFEFlhvwOQ4Y6DQp+J9q2ZzaidCoIZOraAaBuRsqKE323PQ
ZrF1x9LZsgnbA2Ekwx15lSlFOzI9fCLDHUl8E3XsYC3USfuSdCp4K/b4VgARTcQDwG21Tfd2
X0adCuse61Sw/Eu6jlPBxv2c6VX6ha7bNCHyucoUmhSe0b2lp/b0BQIba3fpcOOaOFCLSivL
XxOxOk1DjnYuI3FS9sgwRFyyMgZOCu7Rc1T4HumwQJ0mT8/R0QudCj9PXBj0qu7aqPPuKyLt
SBtW519CC3Q6uevAMvBwrfOOG4pwwAjd7jncDPOWKAPHKOabNDbnQzcJy4hDDcOAeZPgiPzj
Agu10HbbtGzWW/LmvLzbSCuW8dxeBUUyKzukEwyqx++230H+Rrff99Cw3ZAfCE2H5Y3P7dUW
PSj1O0vx35v2H3rZZuAv9TGcAAAAJXRFWHRjcmVhdGUtZGF0ZQAyMDEyLTA0LTEwVDA4OjA0
OjI2KzAwOjAwK8EKewAAACV0RVh0bW9kaWZ5LWRhdGUAMjAxMi0wNC0yM1QxMzo0MDowMCsw
MDowMOwjLFMAAAAASUVORK5CYII=</binary>
 <binary id="img_90.png" content-type="image/png">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
YII=</binary>
 <binary id="img_91.png" content-type="image/png">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
</binary>
 <binary id="img_92.png" content-type="image/png">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
YII=</binary>
 <binary id="img_93.png" content-type="image/png">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
ODowNDoyNiswMDowMHRwfE8AAAAASUVORK5CYII=</binary>
</FictionBook>
