Преобразование xml. Преобразования из XML в XML. Преобразования из XML в XHTML

Итак, дерево объектов D0M построено надлежащим образом. Теперь надо его преобразовать в документ XML, страничку HTML, документ PDF или объект другого типа. Средства для выполнения такого преобразования составляют третью часть набора JAXP - пакеты javax. xml. transform, javax.xml.transform.dom, javax.xml.transform.sax, javax.xml.transform.stream, которые представляют собой реализацию языка описания таблиц стилей для преобразований XSLT (XML Stylesheet Language for Transformations) средствами Java.

Язык XSLT разработан консорциумом W3 как одна из трех частей, составляющих язык записи таблиц стилей XSL (XML Stylesheet Language). Все материалы по XSL можно посмотреть на сайте проекта http://www.w3.org/Style/XSL/ .

Интерфейсы и классы, входящие в пакеты javax. xml. trans form. *, управляют процессором XSLT, в качестве которого выбран процессор Xalan, разработанный в рамках проекта Apache Software Foundation, http://xml.apache.org/xalan-j/ .

Исходный объект преобразования должен иметь Интерфейс

Source определяет всего два метода доступа к идентификатору объекта:

public String getSystemId() ; public void setSystemId(String id);

У интерфейса source есть три реализации. Класс DOMSource подготавливает к преобразованию дерево объектов D0M, а классы SAXsource и streamSource подготавливают SAX-объект и простой поток данных. В конструкторы этих классов заносится ссылка на исходный объект - для конструктора класса DOMSource это узел дерева, для конструктора класса SAXSource - ИМЯ файла, ДЛЯ КОНСТруКТОра Класса StreamSource - ВХОДНОЙ поток. Методы этих классов позволяют задать дополнительные свойства исходных объектов преобразования.

Результат преобразования описывается интерфейсом Result. Он тоже определяет точно такие же методы доступа к идентификатору объекта-результата, как и интерфейс У тоже есть три реализации - классы

DOMResult, SAXResult И StreamResult. В КОНСТруКТОрЫ ЭТИХ классов ЗЭНОСИТ- ся ссылка на выходной объект. В первом случае это узел дерева, во втором - объект типа ContentHandler, в третьем - файл, в который будет занесен результат преобразования, или выходной поток.

Само преобразование выполняется объектом класса Transformer. Вот стандартная схема преобразования дерева объектов в документ записываемый в файл.

TransformerFactory transFactory =

TransformerFactory.newInstance();

Transformer transformer = transFactory. newTrans former () ;

DOMSource source = new DOMSource (document) ;

File newXMLFile = new File ("ntbl.xml") ;

FileOutputStream fos = new FileOutputStream(newXMLFile) ;

StreamResult result = new StreamResult(fos); transformer.transform(source, result);

Вначале методом newlnstance о создается экземпляр transFactory фабрики объектов-преобразователей. Методом

public void setAttrbute(string name, String value);

класса Trans formerFactory можно установить некоторые атрибуты экземпляра. Имена и значения атрибутов зависят от реализации фабрики.

С помощью фабрики преобразователей создается объект-преобразователь класса Transformer. При создании этого объекта в него можно занести объект, содержащий правила преобразования, например, таблицу стилей XSL.

В созданный объект класса Transformer методом public void setParameter (String name, String value) ; можно занести параметры преобразования, а методами public void setOutputProperties(Properties out); public void setOutputProperty(String name, String value);

можно определить свойства преобразованного объекта. Имена свойств name задаются константами, которые собраны в специально определенный класс outputKeys, содержащий только эти константы. Вот их список:

Cdata_section_elements - список имен секций cdata через пробел.

Doctype _public - открытый идентификатор public преобразованного документа.

Doctype_system - системный идентификатор system преобразованного документа.

ENCODING - кодировка символов преобразованного документа, значение атрибута encoding объявления XML.

INDENT - делать ли отступы в тексте преобразованного документа. Значения этого свойства "yes" или "по".

Mediatype - МШЕ-тип содержимого преобразованного документа.

METHOD - метод вывода, одно из значений "xml", "html" или "text".

Omrr_xml_declaration - не включать объявление XML. Значения "yes" или "по".

Standalone - отдельный или вложенный документ, значение атрибута standalone объявления XML. Значения "yes" или "по".

Version - номер версии XML для атрибута version объявления XML.

Например, можно задать кодировку символов преобразованного документа следующим методом:

transformer.setOutputProperty(OutputKeys.ENCODING, "Windows-1251");

Затем в приведенном примере по дереву объектов document типа Node создается объект класса DOMSouroe - упаковка дерева объектов для последующего преобразования. По типу аргумента конструктора видно, что можно преобразовать не все дерево, а какое-либо его поддерево, записав в конструкторе класса DOMSource корневой узел поддерева.

Преобразования из XML в XML

Преобразования XML-XML иногда рассматриваются как SQL для Интернета, поскольку они позволяют оперировать запросами к базе данных в XML-документах. Ниже приведен пример. Используемый нами файл planets.xml содержит достаточно много данных о каждой планете:

Mercury

.0553

58.65

1516

.983

43.4

Venus

.815

116.75

3716

.943

66.8

Что, если нам нужно только подмножество этих данных - например, имя и масса каждой планеты? В терминах баз данных planets.xml представляет собой таблицу, и мы хотим создать новую таблицу, содержащую подмножество данных из первой. В базах данных для этого служит язык SQL, а для документов XML мы можем использовать XSLT.

В листинге 1.6 приведена новая версия файла planets.xsl , осуществляющая требуемое преобразование: выбираются только имя и масса каждой планеты, которые отправляются в выходной документ. В особенности обратите внимание на то, что мы осуществляем преобразование XML-XML, поэтому я использую элемент , атрибут method которого установлен в «xml» (фактически тип выходных данных обычно и есть XML, но если процессор XSLT видит тег , он обычно по умолчанию генерирует HTML).

Листинг 1.6. Выбор только имени и массы

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

C:planets>java org.apache.xalan.xslt.Process -IN planets.xml -XSL planets.xsl -OUT new.xml

Вот как выглядит результирующий документ XML, new.xml:

Mercury

.0553(Earth = 1)

Venus

.815(Earth = 1)

Earth

1(Earth = 1)

Отметьте, что этот файл выглядит во многом похоже на исходный файл planets.xml , за тем исключением, что каждый элемент Содержит только элементы и . Таким образом, мы смогли получить подмножество данных первоначального документа XML.

Конечно, можно проводить любое число такого рода преобразований XML-XML. Можно обрабатывать данные в документе XML для создания совершенно новых XML-документов. Например, можно взять XML-документ с именами студентов и их отметками и создать новый документ, отображающий средние оценки. В XSLT есть много встроенных функций, позволяющих работать с данными подобным образом, - мы познакомимся с ними в главе 8.

В дополнение следует сказать, что многие программы используют XML для обмена данными в Интернете, и, так как обычно они форматируют свои документы XML по-разному, еще одним популярным способом использования преобразований XML-XML в Интернете является преобразование XML из формата, используемого одной программой, в формат другой программы.

Из книги C++ автора Хилл Мюррей

8.5.6 Преобразования Конструктор, получающий один параметр, определяет преоразование из типа своего параметра в тип своего класса. Такие преобразования неявно применяются дополнительно к стандартным пробразованиям (#6.6-7). Поэтому присваивание объекту из класса X

Из книги Справочное руководство по C++ автора Страустрап Бьярн

R.4.7 Преобразования ссылок Всюду, где ссылки (§R.8.2.2) инициализируются (включая передачу параметров (§R.5.2.2) и возврат значения функции (§R.6.6.3)) или используются иным образом, возможны следующие преобразования:Ссылка на данный класс может быть преобразована в ссылку на

Из книги Советы по Delphi. Версия 1.0.6 автора Озеров Валентин

R.12.3 Преобразования Преобразования объектов класса можно задать с помощью конструкторов или функций преобразования.Такие преобразования, обычно называемые пользовательскими, используются неявно в совокупности со стандартными преобразованиями (§R.4). Например, функцию

автора Реймонд Эрик Стивен

R.12.3.2 Функции преобразования Функция-член класса X, имя которой имеет вид,имя-функции-преобразования: operator имя-типа-преобразованияимя-типа-преобразования: список-спецификаций-типа opt операция-ptr optзадает преобразование из типа X в тип, определяемый конструкцией

Из книги Искусство программирования для Unix автора Реймонд Эрик Стивен

Из книги HTML 5, CSS 3 и Web 2.0. Разработка современных Web-сайтов. автора Дронов Владимир

Из книги XSLT автора Хольцнер Стивен

18.5.4. Средства преобразования Вторая крупнейшая проблема, связанная с DocBook, состоит в необходимости преобразования старой разметки уровня представления в разметку DocBook. Человек обычно может автоматически преобразовать представление документа в логическую структуру,

Из книги Технология XSLT автора Валиков Алексей Николаевич

Преобразования CSS В главе 22, ведя разговор о канве и программном рисовании на ней, мы узнали о преобразованиях системы координат. С помощью особых расширений CSS мы можем проделать аналогичные действия над любым элементом Web-страницы: сместить его, повернуть, растянуть или

Из книги Язык программирования Си для персонального компьютера автора Бочков C. О.

Преобразования из XML в XML Преобразования XML-XML иногда рассматриваются как SQL для Интернета, поскольку они позволяют оперировать запросами к базе данных в XML-документах. Ниже приведен пример. Используемый нами файл planets.xml содержит достаточно много данных о каждой

Из книги Macromedia Flash Professional 8. Графика и анимация автора Дронов В. А.

Модель преобразования Во вводной главе мы говорили, что преобразования в XSLT являются наборами шаблонных правил, каждое из которых обрабатывает определенный фрагмент входящего документа с тем, чтобы сгенерировать фрагмент выходящего

Из книги автора

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

Из книги автора

Выполнение преобразования Несмотря на полную свободу в порядке выполнения шаблонов, правила изменения контекста и компоновки результирующего дерева, спецификация XSLT оговаривает очень четко - это делает XSLT весьма гибким языком, программы на котором при этом

Из книги автора

Упрощенные преобразования Многие простые преобразования состоят из единственного правила, которое обрабатывает корневой узел входящего документа. Общий вид такого рода преобразований показан в следующем листинге.Листинг 4.2. Простое

Из книги автора

Преобразования по умолчанию Большинство операций языка Си выполняют преобразование типов для приведения своих операндов к общему типу либо для того, чтобы расширить значения коротких по размеру типов до размера, используемого в машинных операциях. Преобразования,

Из книги автора

Преобразования типов Преобразование типов производится либо неявно, например при преобразовании по умолчанию или в процессе присваивания, либо явно, путем выполнения операции приведения типа. Преобразование типов выполняется также, когда преобразуется значение,

Из книги автора

Преобразования Преобразований, предусматриваемых Flash, всего два. Однако с их помощью можно задать весьма сложное движение выделенного нами фрагмента

XSLT (eX tensible S tylesheet L anguage T ransformations) - язык преобразований xml-документов.

Введение

Задача генерирования отчетности в системе DIRECTUM является одной из наиболее востребованных.

В этой статье описан возможно не самый широко распространенный способ формирования html-отчетов на основе xslt-преобразований. Но несомненно заслуживающий внимания, как один из наиболее удобных и наглядных (если сравнить например с rtf-отчетом).

Если очень коротко, то xslt-преобразование заключается в трансформации xml-схемы с данными в отчет на основе предварительно подготовленного шаблона.

Для примера отчета описанного в статье будет выводится список контрагентов с их наименованием, ИНН и адресом.

Чтобы сформировать отчет понадобятся две составляющие:

Xml-данные для отчета

Xsl-шаблон отчета

Данные в формате xml

Данные в формате xml можно получить прямым sql-запросом:

Select Analit, -- ИД записи для генерации ссылки NameAn, -- Наименование контрагента EdIzm, -- ИНН Dop2 -- Адрес from dbo.MBAnalit where Vid = %s and Sost = "Д" and XRecStat = "+" for xml path("org"), type -- Получить набор строк в виде xml

Описанный выше запрос вернет данные в таком формате:

101702Мобил-Авто ООО123456789 148965ОАО Тринити631000001 148966ООО Дальний восток011101001

Данные нужно обернуть в тег и сохранить в файл, добавив заголовок:

Вторая строка заголовка xml-файла данных важна, в ней указано, что в файле C:\Temp\template.xsl хранится шаблон отчета в который необходимо передать данные.

В итоге получится такой xml-файл:

101702Мобил-Авто ООО123456789426000, г. Ижевск, ул. Революционная, 44 148965ОАО Тринити631000001443000, Самарская обл., г. Самара, ул. Ленина, 11 148966ООО Дальний восток011101001100006, г. Владивосток, ул. Первая, 1

Если открыть полученный xml-файл, браузер будет использовать указанный в заголовке шаблон и подставит данные в него.

xsl-шаблон

Список контрагентов

Теперь нужно сотворить немного магии и указать какие именно данные из xml и в каком виде вставить в шаблон отчета.

Для работы с данными в xsl-шаблоне используются специальные теги.


Цикл for-each и правила выбора

Чтобы перебрать все узлы из xml-файла данных нужно использовать конструкцию:

Она позволит перебрать все дерево данных. Для того, чтобы выбрать только определенные данные из дерева используется правило выбора select="orgs/org" . Правила описаны на языке запросов XPath . В текущем примере будет последовательно отобрана каждый узел из .


Сортировка

Если необходимо, чтобы записи отображались не в порядке следования в xml-файле, а сортировались, то нужно указать это в шаблоне:

Теперь записи будут перебираться предварительно отсортированными по наименованию.


Отображение значения

Но просто перебрать не достаточно, нужно вывести в отчет нужные данные, для этого существует конструкция:

Конструкция отобразит значение тэга (наименование контрагента).


Гиперссылки

Чтобы сделать из наименования контрагента ссылку, по которой можно будет открыть запись справочника, нужно немного модифицировать код:


Сase-оператор и фильтрация

Пусть ИНН контрагента отображается в отчете не просто так. Если ИНН в карточке отсутствует, то будет выводится сообщение об отсутствии ИНН. Для этого необходимо использовать конструкцию:

ИНН:. ИНН не указан.

В конструкции choose с помощью фильтра test проводится проверка содержимого тэга (ИНН) на пустое значение ( ). Если содержимое не пусто, то выводиться значение. В других случаях выводится сообщение "ИНН не указан".


Еще один фильтр

С помощью фильтра возможно реализовать еще одну "рюшечку", которая будет помечать контрагентов с ИНН начинающихся например с кода региона "18". Выглядеть это будет так:

Конструкция для всех записей ИНН которых начинается с "18" дополнительно выведет значок .

В конечном итоге получится такой код шаблона:

Список контрагентов

ИНН:. ИНН не указан. Адрес: .


Результат

А если открыть xml-файл в браузере, то получится такой отчет:

Вывод

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

А если к отчету подключить такой мощный инструмент как javascript, то описанный отчет легко можно сделать интерактивным. Например добавить элемент, позволяющий проводить какую-либо фильтрацию. Или отображать графики по данным отчета.

Какие есть плюсы при реализации отчетов описанным способом:

Требуется разработка относительно небольшого количества прикладных вычислений;

Разработка шаблона наглядна и также относительно нетрудоёмка.

Всё описанное в статье легко интегрируется в аналитический отчет, ссылка на который приведена ниже.

После того как вы загрузили, выполнили синтаксический разбор или каким_то другим способом получили объект Document, представляющий XML_документ, одно из самых интереснейших действий, которые можно с ним выполнить, – это преобразовать документ с помощью таблицы XSLT_стилей. Аббревиатура XSLT происходит от XSL Transformations (XSL_преобразования), а XSL – от Extensible Stylesheet Language (расширяемый язык таблиц стилей). Таблицы XSL_стилей – это XML_документы, которые могут быть загружены и разобраны, как и любые другие XML_документы. Изучение XSL далеко выходит за рамки темы этой кни_ ги, тем не менее в примере 21.8 демонстрируется таблица стилей, которая может использоваться для преобразования в HTML_таблицу XML_документа, подобно_ го представленному в примере 21.6.

Пример 21.8. Простейшая таблица XSL"стилей


21.3. Преобразование XML*документа с помощью XSLT

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

ИмяЭлектронная почта

... __>

Когда встретится элемент , вывести его содержимое в другую ячейку __>

Правила в таблицах XSL_стилей используются для XSLT_преобразований XML_ документов. В контексте клиентского JavaScript_кода это обычно означает пре_ образование XML_документов в HTML_документы. Многие архитектуры разра_ ботки веб_приложений используют XSLT на стороне сервера, но броузеры на ба_ зе Mozilla и броузеры линейки IE поддерживают XSLT_преобразования на сторо_ не клиента, что может помочь снизить нагрузку на сервер и объем трафика, пе_ редаваемого по сети (потому что формат XML, как правило, более компактный, чем HTML).

Многие современные броузеры позволяют определять XML_стили с помощью таблиц CSS _ или XSL_стилей. Если определить таблицу стилей в исполняемой инструкции xml_stylesheet, тогда можно загрузить XML_документ непосредст_ венно в броузер, а броузер преобразует и отобразит его. Например, исполняемая инструкция могла бы выглядеть примерно так:

Обратите внимание: броузеры выполняют такого рода XSLT_преобразования ав_ томатически, когда XML_документ, содержащий соответствующую исполняе_ мую инструкцию, загружается в окно броузера. Это очень важно и очень удобно, но не это является темой данного раздела. Дальше я расскажу о том, как с помо_ щью JavaScript выполнить динамическое XSLT_преобразование.

Консорциум W3C не определяет стандартного прикладного интерфейса для XSLT_ преобразований DOM_объектов Document и Element. В броузерах на базе Mozilla прикладной интерфейс для XSLT_преобразований в JavaScript представляет объект XSLTProcessor. В IE XML_объекты Document и Element имеют метод transform_


530 Глава 21. JavaScript и XML

Node(), выполняющий преобразования. В примере 21.9 демонстрируется исполь_ зование обоих прикладных интерфейсов. В нем определяется класс XML.Trans_ former, который инкапсулирует таблицу XSL_стилей и позволяет использовать ее для преобразования более одного XML_документа. Метод transform() объекта XML.Transformer с помощью инкапсулированной таблицы стилей выполняет пре_ образование указанного XML_документа, а затем замещает содержимое заданно_ го DOM_элемента результатом преобразования.

Пример 21.9. XSLT в Mozilla и Internet Explorer

* Этот класс XML.Transformer инкапсулирует таблицу XSL_стилей.

* Если параметр stylesheet представляет собой URL_адрес, выполняется

* на соответствующий DOM_объект Document.

XML.Transformer = function(stylesheet) {

// Загрузить таблицу стилей, если это необходимо.

if (typeof stylesheet == "string") stylesheet = XML.load(stylesheet); this.stylesheet = stylesheet;

// В броузерах на базе Mozilla создать объект XSLTProcessor

// и передать ему таблицу стилей.

if (typeof XSLTProcessor != "undefined") { this.processor = new XSLTProcessor(); this.processor.importStylesheet(this.stylesheet);

* Это метод transform() класса XML.Transformer.

* Выполняет преобразование указанного xml_узла с использованием

* инкапсулированной таблицы стилей.

* Предполагается, что в результате преобразования получается HTML_код,

* которым следует заменить содержимое указанного элемента.

XML.Transformer.prototype.transform = function(node, element) { // Если элемент указан по id, отыскать его.

if (typeof element == "string") element = document.getElementById(element);

if (this.processor) {

// Если был создан объект XSLTProcessor (в броузерах на базе Mozilla),

// использовать его.

// Преобразовать узел в DOM_объект DocumentFragment.

var fragment = this.processor.transformToFragment(node, document);

// Стереть существующее содержимое элемента. element.innerHTML = "";

// И вставить преобразованные узлы. element.appendChild(fragment);

else if ("transformNode" in node) {

// Если узел имеет метод transformNode() (в IE), использовать его.

// Обратите внимание: transformNode() возвращает строку. element.innerHTML = node.transformNode(this.stylesheet);


// В противном случае удача отвернулась от нас.

throw "XSLT не поддерживается в этом броузере";

* Эта вспомогательная функция, выполняющая XSLT_преобразование,

* может быть удобна, когда таблица стилей должна использоваться всего один раз.

XML.transform = function(xmldoc, stylesheet, element) {

var transformer = new XML.Transformer(stylesheet);

transformer.transform(xmldoc, element);

К моменту написания этих строк IE и броузеры на базе Mozilla были единствен_ ными из основных броузеров, предоставляющих API для XSLT_преобразований. Если для вас важно иметь поддержку и в других броузерах, вас наверняка заин_ тересует проект AJAXSLT – свободно распространяемая JavaScript_реализация XSLT_преобразований. Разработка проекта AJAXSLT была начата компанией Google, ознакомиться с ним можно на сайте проекта по адресу http://goog" ajaxslt.sourceforge.net .

Альтернативное введение в использование XSL Transformations в PHP при помощи Sablotron.

Данный материал следует воспринимать как альтернативное введение в использование XSLT с Sablotron в PHP.

Термины XSL и XSLT близки друг к другу, и новичкам их можно считать синонимами. Подробности, в чём же различия, описаны в спецификации XSL Transformations W3C.

Все, кто интересовался возможностями XSLT, читал стандартный пример из мануала, либо примеры, приводимые в статьях, посвящённых XSLT, на разных сайтах. Работающий пример из этой же серии:

Railroad Tycoon II Platinum экономическая стратегия PopTop software G.O.D. games 2001 Grand Prix 4 автосимулятор Geoff Crammond & Simergy Infogrames Entertainment 2002 "; $xslData = " Игры

Игры

Название жанр год разработчик издатель
"; $xh = xslt_create(); $arguments = array("/_xml" => $xmlData, "/_xsl" => $xslData); $result = @xslt_process($xh, "arg:/_xml", "arg:/_xsl", NULL, $arguments); if ($result) print ($result); else { print ("There was an error that occurred in the XSL transformation...n"); print ("tError number: " . xslt_errno($xh) . "n"); print ("tError string: " . xslt_error($xh) . "n"); exit; } ?>

Подобных примеров в Сети полно. Все они хорошо показывают, что XSL-трансформация в php работает, но после их прочтения остаётся неясным, зачем XSL нужен, скорее даже наоборот - почему XSL не нужен.

"Действительно", - подумает читатель, - "если данные лежат в базе, зачем городить огород, формируя сперва XML, а затем ещё преобразовывать через XSL? С тем же успехом это сделает класс HTML-шаблона."

После этого разочарованный программист напрочь теряет интерес к XSL и вешает на технологию ярлык "ненужная заумь".

Вам, уважаемые читатели, повезло найти такой замечательный сайт, как "php в деталях". Здесь вы прочитаете о том, что XSL может не только преобразовывать XML в HTML, но и то, как можно при помощи XSL облегчить работу с php-скриптами.

Начало работы

Приведённый выше пример, хоть и слишком прост, хорошо иллюстрирует, каким образом делается XSL-преобразование в php.

Чтобы этот код работал, нужно установить XSLT-процессор Sablotron. На виндовой машине это делается так:

1. положить iconv(-1.3).dll, expat.dll и sablot.dll в C:windowsSystem (все файлы есть в стандартном дистрибутиве php)
2. открыть C:windowsphp.ini и в нём найти параметр extension_dir. Если значение параметра - "." или нечто вроде "./", исправить на, скажем, "f:usrlocalphpextension" (или адрес директории, в которой у вас лежат/будут лежать расширения php). Теперь это будет директория расширений php.
3. положить в директорию расширений файл php_xslt.dll (это для php версии 4.2.x), либо php_sablot.dll (для версии 4.0.x)
4. в php.ini раскомментируйте строчку extension=php_xslt.dll (4.2.x) или extension=php_sablot.dll (4.0.x)

Теория

Использование XSLT позволяет отделить от php-скриптов работу по форматированию и представлению данных. Это не только уменьшение объёма кода, но и вынос большого количества логических конструкций (if, else, switch), а следовательно, облегчение работы по написанию и отладке программ. Смею утверждать, что тот, кто не пробовал работать с XSLT, не представляет себе, насколько php-кодирование облегчится.

Впрочем, не надо обольщаться: если у вас было несколько конструкций if … else в php-скрипте, они, скорее всего, появятся в том же количестве в XSL-файле.

Теперь к примерам.

Вывод списков

Все усложнения, происходящие от необходимости выводить список в удобочитаемом виде, переносятся на плечи XSL. Пример #2. Список статей на сайте с подсветкой статьи, которую читают сейчас, чередование цвета в строках и нумерация списка.

2002-05-30 Ловля ошибок в PHP Живой проект и мёртвый журнал Работа с MySQL. Часть 7. Деревья Ручная сортировка в веб-интерфейсе Как поладить дизайнеру с программистом Relax this is PHP

...

... #cccccc <

Произвольная разметка

Переводя на XML сайт с текстами (как этот), естественно хотеть сделать собственную разметку статей. Например, в контейнером important выделять очень важные места и иметь возможность выделять их не обязательно жирным шрифтом, но, может быть, цветом, CSS-стилем. Или писать цитаты как текст цитаты и иметь возможность менять стиль их оформления вместе с дизайном сайта.

Медленно продвигаясь от самого простого первого примера, многие натыкаются на эту проблему и не могут найти решения. Ведь если выделить абзац в тег И делать для него шаблон, на первый взгляд, существуют три способа вывода содержимого:

1. тег xsl:value-of выводит текст, но удаляет все теги в абзаце
2 .тег xsl:copy-of выводит копию всего содержимого (без возможности применять шаблоны к детям - внутренним тегам) и самого контейнера (что не очень красиво в HTML).
3. наконец, xsl:apply-templates применит шаблоны к детям, но пропустит текст

Проблема кажется безвыходной, но решение есть. Я использую "магические" шаблоны, которые выводят и текст и теги в нём со всеми атрибутами и без изменений. Пример #3:

Данный пример использует магические шаблоны для разбора произвольной разметки. Это позволяет избежать таких жалоб: Люди, памажите сами мы не местные! Не могу вывести теги в тексте при помощи value-of!


Запомните эти шаблоны раз и навсегда! Тогда вы сможете обрабатывать любой текст Почти любой.

Первым делом XSLT-процессор при вызове инструкции apply-templates ищет шаблон для каждого элемента. Для элемента strong шаблон есть, и именно в соответствии с ним такие элементы будут обработаны. Для гиперссылки шаблона нет, поэтому она будет выведена, как есть. Можно добавить в XSL шаблон и для ссылки, который бы выводил рядом с каждой текстовой ссылкой картинку для открытия её в новом окне:

* в шаблоне использован параметр match="a[@href]" - этот шаблон будет применён только к тем тегам ссылок, в которых есть поле href и пропустит якоря ().

Невалидный код и

Кажущаяся необходимость писать валидный XML-код так же отпугивает многих неофитов XSLT. Хорошо, с завтрашнего дня будем писать статьи только валидно, благо дома можно проверить, нет ли в тексте XML-ошибки - mismatched tag или invalid token, - с этим как-нибудь справимся. Но ведь, по-хорошему, нужно и весь архив перевести в валидный код! И я так тоже думал, когда появилась возможность переделывать сайт на XML.

Решение проблемы довольно простое: не хочешь - не пиши валидно. Пиши, как привык, - без кавычек в атрибутах тегов, используй простой
и прочее. Достаточно заключить текст в контейнер (пример ниже).

Что касается, то здесь дела такие: элемента nbsp в XML нет. Есть lt, gt, quot, но не nbsp (вполне логично - это ведь non-braking space, который относится к форматированию и придуман для HTML). Поэтому его нужно объявить в документе, либо использовать только внутри .

Пример #4:

Люди, памажите, сами мы не местные!


Запомните и эти шаблоны тоже!

Очень удобно! Большие изменения в архив вносить не придётся. Можно начать писать валидно, а продолжать как попало. А можно комбинировать эти два подхода. Чтобы не писать в архивные файлы тег CDATA, я сделал простое преобразование при помощи регулярных выражений (важно так же помнить, что один тег CDATA не должен содержать в себе другой).

$doc = preg_replace("~<(p|h|pre)>(.*?)~", "<\1>\2", $doc);

Циклы

Допустим, нам нужно сделать форму для редактирования статьи, в том числе её даты. Для удобства пользования надо сделать три раскрывающихся списка (далее - "крутилки") - дата от 1 до 31, месяц, год. Первое решение, которое приходит в голову - сделать HTML-код крутилок в php, вставить в XML в контейнере CDATA, а затем вывести в XSL с параметром disable-output-escaping="yes".

На самом деле, XSLT может и это. Достаточно вставить в данные XML число, номер месяца и год. Крутилки можно нарисовать сразу в XSLT.

Напишем шаблон, не предназначенный ни для какого элемента документа. Он будет вызываться командой xsl:call-template и получать два параметра: значение счётчика и максимум. Сперва он будет выводить нужные нам данные со значением счётчика, затем вызывать самого себя с параметрами максимум и счётчик, увеличенный на 1. Пример #5:

Февраль Март Апрель Май Июнь Июль Август Сентябрь Октябрь Ноябрь Декабрь

... 7 10 2002

... ...

Оставляю вам в качестве домашнего задания шаблон для вывода крутилки с годом.