XSLT

XSLT (e X tensible S tylesheet L anguage T ransformations) - мова перетворення XML -документів. Специфікація XSLT входить до складу XSL і є рекомендацією W3C.

При застосуванні таблиці стилів XSLT, що складається з набору шаблонів, до XML-документу (вихідне дерево) утворюється кінцеве дерево, яке може бути серіалізовать у вигляді XML-документа, XHTML -документа (тільки для XSLT 2.0), HTML -документа або простого текстового файлу. Правила вибору (і, почасти, перетворення) даних з вихідного дерева пишуться на мові запитів XPath.

XSLT має безліч різних застосувань, в основному в області web-програмування та генерації звітів. Одним із завдань, що вирішуються мовою XSLT, є відділення даних від їх подання, як частина загальної парадигми MVC ( англ. Model-view-controller ). Інший стандартної завданням є перетворення XML-документів з однієї XML-схеми в іншу.


1. Історія

XSLT розроблений робочою групою XSL Консорціуму Всесвітньої павутини.

Версія 1.0 була схвалена в якості рекомендації 16 листопада 1999. Після виходу першої версії почалися роботи над версією 1.1, але в 2001 вони були припинені, а робоча група XSL приєдналася до робочої групи XQuery для спільної роботи над XPath 2.0. Згодом XPath 2.0 послужив основою при розробці XSLT версії 2.0.

Версія 2.0 була схвалена в якості рекомендації 24 січня 2007. Незважаючи на те, що версія 2.0 є останньою, версія 1.0 продовжує використовуватися дуже широко.


2. Процес виконання XSLT-перетворення

У процесі виконання XSLT-перетворення задіяні:

  • один або декілька вхідних XML-документів;
  • одна або кілька таблиць Cтиль XSLT;
  • XSLT-процесор;
  • один або декілька вихідних документів.

У простому випадку XSLT-процесор отримує на вході два документи - вхідний XML -документ і таблицю стилів XSLT - і створює на їх основі вихідний документ.

3. XSLT і XPath

XSLT використовує мову XPath для доступу до окремих частин вхідного XML-документа і для організації обчислень.

XSLT 1.0 використовує XPath 1.0, а XSLT 2.0 використовує XPath 2.0.

4. Приклади

4.1. Трансформація з XML в XML

Вихідний XML -документ:

  version  =  "1.0"  ?>   >   username  =  "MP123456"  >   >  Іван   >   >  Іванов   >   >   username  =  "PK123456"  >   >  Петро   >   >  Петров   >   >   > 

Таблиця XSLT-стилів (перетворення):

  version  =  "1.0"  ?>   xmlns: xsl  =  "Http://www.w3.org/1999/XSL/Transform"  version  =  "1.0"  >   method  =  "Xml"  indent  =  "Yes"  />   match  =  "Persons"  >   >   />   >   >   match  =  "Person"  >   >   select  =  "@ * | *"  />   >   >   match  =  "@ Username"  >   >   select  =  "."  />   >   >   match  =  "Name"  >   >   />   select  =  "Following-sibling :: surname"  mode  =  "Fullname"  />   >   >   match  =  "Surname"  />   match  =  "Surname"  mode  =  "Fullname"  >   >   >   />   >   > 

Результуючий XML-документ:

  version  =  "1.0"  encoding  =  "UTF-8"  ?>   >   >   >  MP123456   >   >  Іван Іванов   >   >   >   >  PK123456   >   >  Петро Петров   >   >   > 

4.2. Трансформація з XML в XHTML

Вхідний XML-документ:

  version  =  "1.0"  encoding  =  "UTF-8"  ?>   type  =  "Text / xsl"  href  =  "My-style.xsl"  ?>   >   ownedBy  =  "Sun Microsystems Inc."  >   >  www   >  World Wide Web site   >   >   >  java   >  Java info   >   >   >   ownedBy  =  "The World Wide Web Consortium"  >   >  www   >  World Wide Web site   >   >   >  validator   >  web developers who want to get it right   >   >   >   > 

Стиль для XSLT-трансформації:

  version  =  "1.0"  encoding  =  "UTF-8"  ?>   version  =  "1.0"  xmlns: xsl  =  "Http://www.w3.org/1999/XSL/Transform"  xmlns  =  "Http://www.w3.org/1999/xhtml"  >   method  =  "Xml"  indent  =  "Yes"  doctype-public  =  "- / / W3C / / DTD XHTML 1.0 Strict / / EN"  doctype-system  =  "Http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"  />     match  =  "/"  >   xmlns  =  "Http://www.w3.org/1999/xhtml"  xml: lang  =  "En"  lang  =  "En"  >   >   http-equiv  =  "Content-Type"  content  =  "Text / html; charset = UTF-8"  />   > </span></span></span> test1 <span><span> </ Title <span> > </span></span></span><span><span> <Style </span><span> type </span> = <span> "Text / css" </span><span> > </span></span> h1 {padding: 10px; padding-width: 100%; background-color: silver} td, th {width: 40%; border: 1px solid silver; padding: 10px} td: first-child, th: first-child { width: 20%} table {width: 650px} <span><span> </ Style <span> > </span></span></span><span><span> </ Head <span> > </span></span></span><span><span> <Body <span> > </span></span></span><span><span> <Xsl: apply-templates </span><span> /> </span></span><span><span> </ Body <span> > </span></span></span><span><span> </ Html <span> > </span></span></span><span><span> </ Xsl: template <span> > </span></span></span><span> <! - Table headers and outline -> </span><span><span> <Xsl: template </span><span> match </span> = <span> "Domains / *" </span><span> > </span></span><span><span> <H1 <span> > </span></span><span> <Xsl: value-of </span><span> select </span> = <span> "@ OwnedBy" </span><span> /> </span><span> </ H1 <span> > </span></span></span><span><span> <P <span> > </span></span></span> The following host names are currently in use at <span><span> <Strong <span> > </span></span><span> <Xsl: value-of </span><span> select </span> = <span> "Local-name (.)" </span><span> /> </span><span> </ Strong <span> > </span></span></span><span><span> </ P <span> > </span></span></span><span><span> <Table <span> > </span></span></span><span><span> <Tr <span> > </span></span><span> <Th <span> > </span></span></span> Host name <span><span> </ Th <span> > </span></span><span> <Th <span> > </span></span></span> URL <span><span> </ Th <span> > </span></span><span> <Th <span> > </span></span></span> Used by <span><span> </ Th <span> > </span></span><span> </ Tr <span> > </span></span></span><span><span> <Xsl: apply-templates </span><span> /> </span></span><span><span> </ Table <span> > </span></span></span><span><span> </ Xsl: template <span> > </span></span></span><span> <! - Table row and first two columns -> </span><span><span> <Xsl: template </span><span> match </span> = <span> "Host" </span><span> > </span></span><span> <! - Create variable for 'url', as it's used twice -> </span><span><span> <Xsl: variable </span><span> name </span> = <span> "Url" </span><span> select </span> = </span><span><span> "Normalize-space (concat ('http://', ​​normalize-space (node ​​()), '.', Local-name (..)))" </span><span> /> </span></span><span><span> <Tr <span> > </span></span></span><span><span> <Td <span> > </span></span><span> <Xsl: value-of </span><span> select </span> = <span> "Node ()" </span><span> /> </span><span> </ Td <span> > </span></span></span><span><span> <Td <span> > </span></span><span> <A </span><span> href </span> = <span> "{$ Url}" </span><span> > </span><span> <Xsl: value-of </span><span> select </span> = <span> "$ Url" </span><span> /> </span><span> </ A <span> > </span></span><span> </ Td <span> > </span></span></span><span><span> <Xsl: apply-templates </span><span> select </span> = <span> "Use" </span><span> /> </span></span><span><span> </ Tr <span> > </span></span></span><span><span> </ Xsl: template <span> > </span></span></span><span> <! - 'Used by' column -> </span><span><span> <Xsl: template </span><span> match </span> = <span> "Use" </span><span> > </span></span><span><span> <Td <span> > </span></span><span> <Xsl: value-of </span><span> select </span> = <span> "." </span><span> /> </span><span> </ Td <span> > </span></span></span><span><span> </ Xsl: template <span> > </span></span></span><span><span> </ Xsl: stylesheet <span> > </span></span></span></pre></div></div><p> XHTML, який ми отримуємо на виході (прогалини були додані для ясності): </p><div dir=ltr><div><pre><span><span> <? Xml </span><span> version </span> = <span> "1.0" </span><span> encoding </span> = <span> "UTF-8" </span><span> ?> </span></span><span> <! DOCTYPE html PUBLIC "- / / W3C / / DTD XHTML 1.0 Strict / / EN" </span><span> "Http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> </span><span><span> <Html </span><span> xmlns </span> = <span> "Http://www.w3.org/1999/xhtml" </span><span> lang </span> = <span> "En" </span><span> xml: lang </span> = <span> "En" </span><span> > </span></span><span><span> <Head <span> > </span></span></span><span><span> <Meta </span><span> content </span> = <span> "Text / html; charset = UTF-8" </span><span> http-equiv </span> = <span> "Content-Type" </span><span> /> </span></span><span><span> <Title <span> > </span></span></span> test1 <span><span> </ Title <span> > </span></span></span><span><span> <Style </span><span> type </span> = <span> "Text / css" </span><span> > </span></span> h1 {padding: 10px; padding-width: 100%; background-color: silver} td, th {width: 40%; border: 1px solid silver; padding: 10px} td: first-child, th: first-child { width: 20%} table {width: 650px} <span><span> </ Style <span> > </span></span></span><span><span> </ Head <span> > </span></span></span><span><span> <Body <span> > </span></span></span><span><span> <H1 <span> > </span></span></span> Sun Microsystems Inc. <span><span> </ H1 <span> > </span></span></span><span><span> <P <span> > </span></span></span> The following host names are currently in use at <span><span> <Strong <span> > </span></span></span> sun.com <span><span> </ Strong <span> > </span></span><span> </ P <span> > </span></span></span><span><span> <Table <span> > </span></span></span><span><span> <Tr <span> > </span></span></span><span><span> <Th <span> > </span></span></span> Host name <span><span> </ Th <span> > </span></span></span><span><span> <Th <span> > </span></span></span> URL <span><span> </ Th <span> > </span></span></span><span><span> <Th <span> > </span></span></span> Used by <span><span> </ Th <span> > </span></span></span><span><span> </ Tr <span> > </span></span></span><span><span> <Tr <span> > </span></span></span><span><span> <Td <span> > </span></span></span> www <span><span> </ Td <span> > </span></span></span><span><span> <Td <span> > </span></span><span> <A </span><span> href </span> = <span> "Http://www.sun.com" </span><span> > </span></span> http://www.sun.com <span><span> </ A <span> > </span></span><span> </ Td <span> > </span></span></span><span><span> <Td <span> > </span></span></span> World Wide Web site <span><span> </ Td <span> > </span></span></span><span><span> </ Tr <span> > </span></span></span><span><span> <Tr <span> > </span></span></span><span><span> <Td <span> > </span></span></span> java <span><span> </ Td <span> > </span></span></span><span><span> <Td <span> > </span></span><span> <A </span><span> href </span> = <span> "Http://java.sun.com" </span><span> > </span></span> http://java.sun.com <span><span> </ A <span> > </span></span><span> </ Td <span> > </span></span></span><span><span> <Td <span> > </span></span></span> Java info <span><span> </ Td <span> > </span></span></span><span><span> </ Tr <span> > </span></span></span><span><span> </ Table <span> > </span></span></span><span><span> <H1 <span> > </span></span></span> The World Wide Web Consortium <span><span> </ H1 <span> > </span></span></span><span><span> <P <span> > </span></span></span> The following host names are currently in use at <span><span> <Strong <span> > </span></span></span> w3.org <span><span> </ Strong <span> > </span></span><span> </ P <span> > </span></span></span><span><span> <Table <span> > </span></span></span><span><span> <Tr <span> > </span></span></span><span><span> <Th <span> > </span></span></span> Host name <span><span> </ Th <span> > </span></span></span><span><span> <Th <span> > </span></span></span> URL <span><span> </ Th <span> > </span></span></span><span><span> <Th <span> > </span></span></span> Used by <span><span> </ Th <span> > </span></span></span><span><span> </ Tr <span> > </span></span></span><span><span> <Tr <span> > </span></span></span><span><span> <Td <span> > </span></span></span> www <span><span> </ Td <span> > </span></span></span><span><span> <Td <span> > </span></span><span> <A </span><span> href </span> = <span> "Http://www.w3.org" </span><span> > </span></span> http://www.w3.org <span><span> </ A <span> > </span></span><span> </ Td <span> > </span></span></span><span><span> <Td <span> > </span></span></span> World Wide Web site <span><span> </ Td <span> > </span></span></span><span><span> </ Tr <span> > </span></span></span><span><span> <Tr <span> > </span></span></span><span><span> <Td <span> > </span></span></span> validator <span><span> </ Td <span> > </span></span></span><span><span> <Td <span> > </span></span><span> <A </span><span> href </span> = <span> "Http://validator.w3.org" </span><span> > </span></span> http://validator.w3.org <span><span> </ A <span> > </span></span><span> </ Td <span> > </span></span></span><span><span> <Td <span> > </span></span></span> web developers who want to get it right <span><span> </ Td <span> > </span></span></span><span><span> </ Tr <span> > </span></span></span><span><span> </ Table <span> > </span></span></span><span><span> </ Body <span> > </span></span></span><span><span> </ Html <span> > </span></span></span></pre></div></div><p> На виході не завжди вийде обов'язково правильний XHTML. У XSLT 2.0 це виправлено - доданий метод виведення 'XHTML', поряд з 'HTML', який вже існував у XSLT 1.0. </p><br clear=all style=page-break-before:always /><h2><span id=link7> 5. Застосування правил шаблонів </span></h2><p> Мова XSLT є декларативним, а не процедурним. Замість визначення послідовності виконуваних операторів, ця мова визначає правила, які будуть застосовуватися під час перетворення. Саме перетворення ведеться по фіксованому алгоритмом. </p><p> В першу чергу XSLT процесор розбирає файл перетворення і будує XML дерево вхідного файлу. Потім він шукає шаблон, який найкраще підходить для кореневого вузла і обчислює вміст знайденого шаблону. Інструкції в кожному шаблоні можуть або безпосередньо говорити XSLT процесору "створи тут такий-то тег", або говорити "обробив інші вузли за тим же правилом, що і кореневий вузол". </p><p> Більш докладно цей алгоритм, в чомусь нетривіальний, описується нижче, хоча багато хто з його екзотичних деталей опущені. </p><p> Кожен XSLT-процесор повинен виконати наступні кроки для підготовки до трансформації: </p><ol><li> Прочитати таблицю стилів XSLT за допомогою XML-парсера і перевести його вміст в дерево вузлів <i>(дерево таблиці стилів),</i> згідно моделі даних XPath. Синтаксичні помилки "часу компіляції" визначаються на цій стадії. Таблиці стилів можуть бути модульними, тому всі включення (інструкції <code>xsl:include</code>, <code>xsl:import</code>) також будуть оброблені на цій стадії з метою об'єднати всі шаблонні правила та інші елементи з інших таблиць стилів в єдине дерево таблиці стилів. </li><li> Прочитати вхідні дані XML за допомогою XML-парсера, перевести його вміст в дерево вузлів <i>(вихідне дерево),</i> згідно моделі даних XPath. XML-документ може посилатися на інші XML-джерела за допомогою виклику функцій <code>document()</code>. Ці виклики зазвичай обробляються під час виконання, так як їх розташування може бути обчислюваним, а виклики відповідних функцій можуть не відбуватися зовсім. (Приклад вище не посилається на які-небудь інші документи.) </li><li> Видалити порожні вузли з таблиці стилів XSLT, крім тих, які є нащадками від елементів <code>xsl:text</code>. Це дозволяє виключити появу "зайвих" прогалин. </li><li> Видалити порожні текстові вузли з вихідного дерева, якщо інструкції <code>xsl:strip-space</code> присутні у вихідному документі. Це дозволяє виключити появу "зайвих" прогалин. (Приклад вище не використовує цю можливість) </li><li> Поповнити XSLT-дерево трьома правилами, які надають поведінка за умовчанням для будь-яких типів вузлів, які можуть бути зустрінуті при обробці. Перше правило - для обробки <i>кореневого вузла;</i> воно дає інструкцію процесору обробити кожного нащадка кореневого вузла. Друге правило - для будь-яких <i>текстових вузлів</i> або <i>вузлів атрибутів;</i> він дає команду процесору зробити копію цього вузла в результуючому дереві. Третє правило - для всіх <i>вузлів коментаря</i> і <i>вузлів-інструкцій обробки;</i> ніякої операції не проводиться. Шаблони, явно задані в XSLT, можуть перекривати частину або всі шаблони-правила, задані за замовчуванням. Якщо шаблон не містить явних правил, вбудовані правила будуть застосовані для рекурсивного обходу вихідного дерева і тільки текстові вузли будуть скопійовані в результуюче дерево (вузли атрибутів не будуть досягнуті, оскільки вони не є "дітьми" їх батьківських вузлів). Отриманий таким чином результат зазвичай небажаний, так як він є просто конкатенації всіх текстових фрагментів з вихідного документа XML. </li></ol><p> Потім процесор проробляє наступні кроки для отримання і сериализации результуючого дерева: </p><ol><li> Створює кореневий вузол результуючого дерева. </li><li> Обробляє кореневий вузол вихідного дерева. Процедура обробки вузла описана нижче. </li><li> Серіалізуются результуюче дерево, якщо необхідно, згідно підказкам, описаним інструкцією <code>xsl:output</code>. </li></ol><p> При обробці вузла проводяться наступні дії: </p><ol><li> Проводиться пошук найбільш підходящого шаблона правила. Це досягається перевіркою відповідності <i>шаблону</i> (який є вираженням XPath) для кожного правила, вказуючи вузли, для яких правило може бути застосовано. Кожному шаблону процесором призначається відносний <i>пріоритет</i> і <i>старшинство</i> для полегшення вирішення конфліктів. Порядок шаблонних правил у таблиці стилів також може допомогти вирішенню конфліктів між шаблонами, які відповідають однаковим вузлам, але це не робить впливу на порядок, в якому вузли будуть оброблятися. </li><li> Template rule contents are instantiated. Елементи в просторі імен XSLT (зазвичай мають префікс <code>xsl:</code>) трактуються як <i>інструкції</i> та мають спеціальну семантику, яка вказує на те, як вони повинні інтерпретуватися. Одні призначені для додавання вузлів в результуюче дерево, інші є керуючими конструкціями. Чи не XSLT-елементи і текстові вузли, виявлені в правилі, копіюються, "дослівно", в результуюче дерево. Коментарі та керуючі інструкції ігноруються. </li></ol><p> Інструкція <code>xsl:apply-templates</code> при її обробці призводить до вибірці і обробці нового набору вузлів. Вузли ідентифікуються за допомогою виразу XPath. Всі вузли обробляються в тому порядку, в якому вони містяться у вихідному документі. </p><p> XSLT розширює бібліотеку функцій XPath's і дозволяє визначати XPath-змінні. Ці змінні мають різну область видимості в таблиці стилів, в залежності від того, де вони були визначені і їх значення можуть задаватися за межами таблиці стилів. Значення змінних не можуть бути змінені під час обробки. </p><p> Хоча ця процедура може здатися складною, однак вона робить XSLT за можливостями схожою на інші мови web-шаблонів. Якщо таблиця стилів складається з єдиного правила, призначеного для обробки кореневого вузла, в результат просто копіюється весь вміст шаблону, а XSLT-інструкції (елементи ' <code>xsl:</code> ') замінюються обчислюваним вмістом. XSLT пропонує навіть спеціальний формат ("literal result element as stylesheet") для таких простих, одношаблонних трансформацій. Однак, можливість визначати окремі шаблони і правила сильно збільшує гнучкість та ефективність XSLT, особливо при генерації результату, який дуже схожий на вихідний документ. </p><br clear=all style=page-break-before:always /><h2><span id=link9> Література </span></h2><ul><li><span> <i>Тідуелл Д.</i> XSLT. 2-е видання = XSLT, 2nd Edition. - СПб: Символ-Плюс, 2009. - 960 с. - <span style="white-space: nowrap;"> 1200 екз. </span> - <a rel=nofollow href=http://ru.wikipedia.org/wiki/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%98%D1%81%D1%82%D0%BE%D1%87%D0%BD%D0%B8%D0%BA%D0%B8_%D0%BA%D0%BD%D0%B8%D0%B3/9785932861509>ISBN 978-5-93286-150-9</a> </span></li><li><span> <i>Мангано С.</i> XSLT. Збірник рецептів = XSLT Cookbook: Solutions and Examples for XML and XSLT Developers, 2nd Edition. - СПб: BHV, 2008. - 864 с. - <a rel=nofollow href=http://ru.wikipedia.org/wiki/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%98%D1%81%D1%82%D0%BE%D1%87%D0%BD%D0%B8%D0%BA%D0%B8_%D0%BA%D0%BD%D0%B8%D0%B3/9785977502924>ISBN 978-5-9775-0292-4</a> </span></li></ul></div></div></body></html></td></td></td></tr></td></td></td></tr></th></th></th></tr></table></strong></td></td></td></tr></td></td></td></tr></th></th></th></tr></table></strong></style>