Во второй лекции мы уже рассматривали пример с использованием
А это как раз то, что нужно для генерации кода. Применение
Модель
Документы XML являются входными данными, которые нужно преобразовать в другие документы. Документ стиля XSLT является корректным (well formed) документом XML и содержит набор правил для выполнения преобразования. Иными словами, документ стиля является шаблоном.
Процессор XSLT является приложением, которое принимает в качестве входных данных документы XML и стили
Процессоры
Другой частью технологии
Язык . Для выполнения трансформации документ стиля
Для преобразования документа XML необходимо добавить в начало документа инструкцию, подобную следующей:
<?xml-stylesheet type="text/xsl" href="MyStyle.xsl"?>
. Именно он указывает, что данный XML-файл является файлом стилей. Кроме него могут содержаться другие элементы, например , . Документ XML и файл стиля передается в
Ниже представлен документ XML, содержащий список языков программирования.
<?xml-stylesheet type="text/xsl" href="languages.xsl"?>
<languages>
<language>C#</language>
<language>Visual Basic</language>
<language>Delphi</language>
<language>Prolog</language>
</languages>
Необходимо вывести этот список в формате HTML. Для этой цели используем инструкцию , которая будет применять часть шаблона к секциям документа, наименование которых указано в атрибуте select. В нашем случае укажем select="languages/language".
Файл стилей будет применяться следующий:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<H4>Мои любимые языки:</H4>
<xsl:for-each select="languages/language">
- <xsl:value-of select="."/><BR/>
</xsl:for-each>
<BR/>
</xsl:template>
</xsl:stylesheet>
Шаблон внутри выводит содержимое каждого элемента language из languages. Для этой цели используется инструкция и задаваемый атрибут select=".". Это означает, что процессор должен выбирать текст содержимого текущего элемента в документе. Кроме отражения содержимого можно задавать имена конкретных тегов, а также атрибутов для выборки значений, хранящихся в них. Примеры будут рассмотрены далее.
Откроем XML файл через Internet Explorer или другой браузер. Будет выведен такой текст:
Мои любимые языки:
Одним из самых главных элементов в стиле является . Служит для определения повторно используемого шаблона и содержит правила, по которым будет преобразован документ XML. В атрибуте match содержится выражение для отбора узлов, к которым будет применен шаблон. Также может присутствовать атрибут name. В этом случае есть возможность вызывать шаблон по имени инструкцией .
Для повторения вывода шаблона для каждого элемента документа применяется инструкция . Шаблон выполняется для каждого элемента, соответствующего условию, указанному в атрибуте select.
Инструкция служит для вычисления выражения, записанного в атрибуте select с последующим выводом результата в том месте, где расположен сам элемент.
Мы рассмотрели случай, когда считываются значения каждого узла. Однако часто возникает необходимость выбирать только часть данных, то есть их надо фильтровать. Шаблоны
Один из них - это применение атрибута select инструкции , а второй - применение атрибута match элемента . Применение match мы рассмотрим позже, а сейчас рассмотрим select.
Изменим немного файл с данными: добавим атрибут , обозначающий, является ли язык из нашего списка языком высокого уровня. Также расширим сам список языков.
<?xml-stylesheet type="text/xsl" href="languages4.xsl"?>
<languages>
<language high="true">C#</language>
<language high="true">Visual Basic</language>
<language high="true">Delphi</language>
<language high="true">Prolog</language>
<language high="false">Assembler</language>
<language high="true">Java</language>
<language high="true">Perl</language>
</languages>
Заметим, что значение false для атрибута стоит только для значения "Assembler". Изменим немного файл таблицы стилей:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<H4>Языки высокого уровня:</H4>
<xsl:for-each select="languages/language[@high='true']">
- <xsl:value-of select="."/><BR/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
В секции [@ мы указываем, что выбирать следует только те узлы документа, у которых атрибут имеет значение 'true'. Знак @ является символом, указывающим на то, что после него стоит имя атрибута.
Посмотрим на результат:
Языки высокого уровня:
Как видим, значение "Assembler" не отображается в списке языков, то есть процессор
Кроме фильтрации другой часто применяемой операцией при генерации кода является сортировка. Атрибут order-by инструкции служит для сортировки результата, для обозначения порядка прохода узлов документа при выполнении трансформации. Сортируемые поля перечисляются через точку с запятой, а также имеют перед своим названием знаки "+" или "-", означающие сортировку по возрастанию или убыванию.
Рассмотрим немного измененный вариант документа - вместо атрибута будем использовать элемент level, принимающий значения или . А имя языка запишем в элемент name.
<?xml-stylesheet type="text/xsl" href="languages6.xsl"?>
<languages>
<language>
<name>C#</name>
<level>high</level>
</language>
<language>
<name>Visual Basic</name>
<level>high</level>
</language>
<language>
<name>Delphi</name>
<level>high</level>
</language>
<language>
<name>Prolog</name>
<level>high</level>
</language>
<language>
<name>Assembler</name>
<level>low</level>
</language>
<language>
<name>Java</name>
<level>high</level>
</language>
<language>
<name>Perl</name>
<level>high</level>
</language>
</languages>
В следующей таблице стилей для инструкции применим атрибут order-by со значением +name, где знак плюса означает, что надо отсортировать по возрастанию.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<H4>Языки высокого уровня:</H4>
<xsl:for-each select="languages/language[level='high']" order-by="+name">
-<xsl:value-of select="name"/><BR/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
В атрибуте select мы фильтруем по значению элемента level. Также в атрибуте select инструкции указываем непосредственно имя элемента.
Получается такой результат.
Языки высокого уровня:
Названия языков отсортированы в алфавитном порядке и значение "Assembler" не отображается в списке.
Другим способом сортировки является применение элемента путем вложения в или в . Элемент имеет атрибуты select и order, которые указывают на элементы, по которым должна осуществляться сортировка и на порядок сортировки соответственно.
В сложных случаях возникает необходимость применения вложенных друг в друга шаблонов. Рассмотрим документ, в котором содержатся таблицы и их поля вместе с названиями.
<?xml-stylesheet type="text/xsl" href="multiple.xsl"?>
<database>
<table name="book">
<field>id</field>
<field>title</field>
<field>author_id</field>
</table>
<table name="author">
<field>id</field>
<field>first_name</field>
<field>last_name</field>
</table>
</database>
В данном примере у нас будут два шаблона. Один будет основной, для таблиц, а другой будет вызываемым из него, для полей таблиц. Для вызова шаблона используется инструкция .
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<H4>Таблицы базы данных</H4>
<xsl:for-each select="database/table">
<table border="1" width="150">
<tr>
<td><b><xsl:value-of select="@name"/></b></td>
</tr>
<xsl:apply-templates select="field"/>
</table>
<br/>
</xsl:for-each>
</xsl:template>
<xsl:template match="field">
<tr>
<td><xsl:value-of select="."/></td>
</tr>
</xsl:template>
</xsl:stylesheet>
<H4>Таблицы базы данных</H4>
<table border="1" width="150">
<tr>
<td><b>book</b></td>
</tr>
<tr>
<td>id</td>
<td>title</td>
<td>author_id</td>
</tr>
</table>
<br/>
<table border="1" width="150">
<tr>
<td><b>author</b></td>
</tr>
<tr>
<td>id</td>
<td>first_name</td>
<td>last_name</td>
</tr>
</table>
<br/>
При открытии сгенерированного результата в браузере будет показано следующее:
(рис 5.1) Результат в браузере
Инструкция позволяет вызывать определенный шаблон и выполнять его много раз. Кроме того она является более наглядной и удобной альтернативой .
Для применения условий к обработке шаблонов используется одна из инструкций: или . Инструкция дает простую функциональность if-then, а инструкция поддерживает выбор одного из нескольких возможных вариантов. Сейчас рассмотрим пример с использованием , а пример с использованием рассмотрим позже.
В следующем примере необходимо создать код объявления процедур на языке PL/SQL такого вида:
procedure prc_save_record (id in out number, name in varchar2, title varchar2, save_date out date);
procedure prc_delete_record (id number);
Объявление состоит из ключевого слова procedure, имени процедуры, имен и типов параметров. Для каждого параметра может указываться его вид: in, out, in out или без указания его. Представим наше объявление процедур в иерархическом виде в следующем документе:
<?xml-stylesheet type="text/xsl" href="if.xsl"?>
<package>
<procedure name="prc_save_record">
<parameter name="id" type="number" in="true" out="true"/>
<parameter name="name" type="varchar2" in="true"/>
<parameter name="title" type="varchar2"/>
<parameter name="save_date" type="date" out="true"/>
</procedure>
<procedure name="prc_delete_record">
<parameter name="id" type="number"/>
</procedure>
</package>
Создадим следующий файл стиля:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:for-each select="package/procedure">
procedure <xsl:value-of select="@name"/>
(<xsl:for-each select="parameter">
<xsl:value-of select="@name"/>
<xsl:text> </xsl:text>
<xsl:if test="@in='true'">in </xsl:if>
<xsl:if test="@out='true'">out </xsl:if>
<xsl:value-of select="@type"/>
<xsl:if test="not(position()=last())">, </xsl:if>
</xsl:for-each>);
<xsl:if test="not(position()=last())"><BR/><BR/></xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Инструкция здесь используется дважды, причем одна вложена в другую. В первой инструкции просматриваются все процедуры, а во второй выполняется работа над каждым параметром процедуры. В атрибуте test инструкции делается проверка на необходимость добавления ключевых слов in, out. Кроме того, инструкция проверки используется для определения того, нужно ли ставить запятую после параметра. Если параметр не последний, что проверяется условием not(position()=last()), то ставится запятая. Функция position() возвращает номер позиции данного контекста в процессе обхода ветвей. Функция last() возвращает общее число позиций. Аналогично проверяется необходимость перехода на следующую строку в конце каждой процедуры.
Инструкция используется для выяснения необходимости включения какого-либо шаблона в результирующий вывод. Шаблон, находящийся внутри инструкции выполняется только в том случае, когда выражение , находящееся в условии test возвращает истину. При этом аналога команды else языков программирования в .
Элемент служит для вывода текста в результат трансформации. Чаще всего он используется для вывода пробелов, так как без применения пробелы будут схлопываться. Атрибут disable-output-escaping позволяет включать и выключать преобразование системных символов вроде знаков больше, меньше, амперсанта.
Инструкция применяется, когда есть необходимость выбора шаблона из нескольких возможных согласно каким-либо условиям. Она содержит одну или более команд и может содержать . Каждая команда содержит в условии test выражение. Если оно является истиной, то выполняется содержимое . Порядок условий имеет значение, так как результатом всей конструкции будет шаблон под первым истинным выражением. Если ни одно из условий в не вернуло истину, в результате будет обработан шаблон под .
Например:
<xsl:choose>
<xsl:when test="$a=l">Истина</xsl:when>
<xsl:when test="$a=0">Ложь</xsl:when>
<xsl:otherwise>Некорректное значение</xsl:otherwise>
</xsl:choose>
Инструкция служит для объявления объектов наподобие переменной. Строго говоря, эти элементы являются не переменными, а скорее инициализируемыми во время запуска обработки шаблона константами. Но в контексте нашей лекции мы будем называть их переменными.
Они позволяют определить заменяемое значение, которое можно использовать в таблице стилей при трансформации.
<xsl:variable name="Имя переменной" select="выражение" as="тип" />
Значение переменной может быть также получено другими путями, например:
<xsl: variable name="a">8</xsl:variable>
Или так:
<xsl:variable name="str">
<xsl:value-of select="." />
<xsl:variable>
Для подстановки значения переменной надо предварить имя переменной знаком $. Процессор
<?xml-stylesheet type="text/xsl" href="variable.xsl"?>
<package>
<procedure name="prc_save_record">
<parameter name="id" type="number" in="true" out="true"/>
<parameter name="name" type="varchar2" in="true"/>
<parameter name="title" type="varchar2"/>
<parameter name="save_date" type="date" out="true"/>
</procedure>
<procedure name="prc_delete_record">
<parameter name="id" type="number"/>
</procedure>
</package>
Теперь поставим задачу вывести для каждой процедуры число параметров внутри объявления процедуры. Для этой цели объявим в инструкции переменную amount и присвоим значение count(parameter) - для каждого узла procedure будет считать число узлов parameter. Кроме того при выводе мы собираемся выводить слово параметр в правильном числе (выводим одно из трех: параметр, параметра, параметров). Для этого мы в переменную modulo10 будем записывать остаток от деления amount на 10. А инструкция добавлена для выборки одного из вариантов написания слова параметр.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:for-each select="package/procedure">
<xsl:variable name="amount">
<xsl:value-of select="count(parameter)"/>
</xsl:variable>
<xsl:variable name="modulo10" select="$amount mod 10"/>
Процедура
<xsl:value-of select="@name"/> имеет
<xsl:value-of select="$amount"/>
<xsl:choose>
<xsl:when test="$amount > 10 and $amount < 20"> параметров</xsl:when>
<xsl:when test="$modulo10=1"> параметр</xsl:when>
<xsl:when test="($modulo10 > 1 and $modulo10 < 5)"> параметра</xsl:when>
<xsl:otherwise> параметров</xsl:otherwise>
</xsl:choose>
<BR/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Результат
Процедура prc_save_record имеет 4 параметра
Процедура prc_delete_record имеет 1 параметр
Инструкция используется для подстановки содержимого другого файла стилей. Ее синтаксис выглядит так:
<хsl:import href="адрес URI" />
Она должна быть первым вложенным элементом в < или <. В случае наличия конфликтов в стилях, применяются правила, которые записаны позже других.
Аналогом этой инструкции является инструкция . Она также должна быть вложена в < или <, однако отличие заключается в том, может подставляться в любое место внутри этих элементов и порядок расположения инструкции не играет роли. Ее синтаксис выглядит аналогично:
<xsl:include href="адрес URI" />
Есть возможность расширять существующие способности
Элемент позволяет описывать самые настоящие пользовательские функции. Имя функции записывается в обязательном атрибуте nаmе, (аргументы функции задаются элементами , а тело функции - это конструктор последовательности, записанный в содержимом элемента . Результатом работы функции будет последовательность, созданная конструктором. Функция может вызываться рекурсивно.
Для выполнения преобразования XML-файлов средствами .Net используется класс XslCompiledTransform, являющийся процессором Load класса загружает и компилирует стиль. Метод Transform выполняет трансформацию.
using System;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
namespace LectionXML
{
class Program
{
static void Main(string[] args)
{
XPathDocument xpd = new XPathDocument(@"variable.xml");
XslCompiledTransform xt = new XslCompiledTransform();
XmlTextWriter xtw = new XmlTextWriter(@"variable.txt",null);
xt.Load(@"variable.xsl");
xt.Transform(xpd, null, xtw);
xtw.Close();
}
}
}
Подлежащий преобразованию документ XML загружается в объект класса XPathDocument. А класс XslCompiledTransform используется для выполнения преобразования. Объект класса XmlTextWriter применяется для вывода результата в выходной файл.
Однако существует более короткий и простой альтернативный вариант с применением одного только класса XslCompiledTransform. Вместо всех приведенных выше объявлений и вызовов нужно написать всего три строчки кода.
XslCompiledTransform xt = new XslCompiledTransform();
xt.Load("variable.xsl");
xt.Transform("variable.xml", "variable.txt");
В предыдущих примерах мы рассматривали генерацию одного файла, однако чаще все-таки требуется создавать множество файлов. В таком случае удобно и эффективно хранить отдельно (в базе данных или в XML-файле) списки файлов для генерации, где будут указаны пути для выходных файлов, настройки, параметры генерации и т.д. Рассмотрим пример, когда требуется произвести сразу несколько трансформаций. Запишем в документе XML необходимую информацию для трех трансформаций: путь к файлу стилей, путь к документу XML, имя выходного файла, название примера.
<?xml-stylesheet type="text/xsl" href="variable.xsl"?>
<examples>
<example>
<name>Пример 1</name>
<style>languages.xsl</style>
<document>languages.xml</document>
<output>languages.txt</output>
</example>
<example>
<name>Пример 2</name>
<style>multiple.xsl</style>
<document>multiple.xml</document>
<output>multiple.html</output>
</example>
<example>
<name>Пример 3</name>
<style>if.xsl</style>
<document>if.xml</document>
<output>if.txt</output>
</example>
</examples>
Это файлы предыдущих примеров в лекции. Стоит задача выполнить трансформацию для них всех разом. Напишем программу, которая будет разбирать документ XML, считывать пути к файлам стиля, документа и вывода. После чего она будет выполнять трансформацию, используя эти данные.
string style = "";
string document = "";
string output = "";
XmlDocument doc = new XmlDocument();
XslCompiledTransform xt = new XslCompiledTransform();
doc.Load(@"hierarchy_example.xml");
XmlElement examples = doc.DocumentElement;
for (int i = 0; i < examples.ChildNodes.Count; i++)
{
XmlNode nd = examples.ChildNodes[i];
for (int j = 0; j < nd.ChildNodes.Count; j++)
{
switch (nd.ChildNodes[j].Name)
{
case "style": style = nd.ChildNodes[j].InnerText; break;
case "document": document = nd.ChildNodes[j].InnerText; break;
case "output": output = nd.ChildNodes[j].InnerText; break;
}
}
xt.Load(style);
xt.Transform(document, output);
}
В первом цикле делается проход по всем примерам. Во вложенном же цикле считываются параметры примера. Считываются все дочерние элементы и, в зависимости от того, чем они являются, заполняются переменные, хранящие пути к документам, стилям, файлам вывода. Впоследствии для каждого примера выполняется трансформация, и результат записывается в выходной файл.
Кроме описанного выше способа, можно также с применением потоков загружать содержимое файлов в память и выполнять преобразование. Так как содержимое (в том числе и стили
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.