Xsl apply templates не работает

XSLT шпаргалка: apply-templates

Сегодня мы поговорим о конструкции . Данная конструкция очень активно используется при формировании таких xslt шаблонов, как:

  • обработка группы полей (вывод характеристик товара),
  • формирования форм,
  • создание шаблонов для разных типов страниц и тому подобное.

Данная конструкция позволяет обработать часть текущего xml и вывести его, используя отдельный шаблон. Чем-то она похожа на , но если первый выводит конкретное значение, то текущая конструкция позволяет обработать кусок xml и вывести результат по отдельному шаблону.

Как обычно, посмотрим, что нам говорит о данной конструкции интернет:

Элемент — Предписывает XSLT-процессору найти и применить соответствующий шаблон в зависимости от типа и контекста каждого выбранного узла.

У данной конструкции есть следующие атрибуты:

  • select — указывает, что именно вы хотите вывести. Тут можно поставить xPath выражение, которое сформирует выборку из несколько узлов или атрибутов, укажет на часть текущего xml , переменной или параметра. Eсли этот атрибут не задан, выбираются все дочерние элементы текущего узла.
  • mode — атрибут, позволяющий дополнительно связать точку вызова ( ) и шаблон, который будет обрабатывать результаты данной конструкции ( )

Давайте рассмотрим некоторые примеры:

Возьмем маленький xml , который можно получить, обратившись к любой странице в UMI.CMS, добавив .xml в конце её значения в адресной строке (например http://example.ru/test.xml)

xml страницы http://example.ru/test/

    Обработка всех узлов property и вывод их по шаблону следующего вида “Название поля: значение поля”.

Такая задача, может встать перед вами при выводе всех характеристик товара.

Тут нужно дать несколько пояснений:
— Описание конструкции будет дано позже, сейчас просто договоримся, что это блок с шаблоном. Чтобы система понимала для чего предназначен этот шаблон, у данной конструкции есть атрибут match, где прописываем название узла, который мы обрабатываем в данном случае.
— Во многих примерах кодов встречается знак «. » (многоточие), который я использую для упрощения записи самого примера. Но следует понимать, что в реальной практике вместо “” (многоточия) будут прописаны какие-то элементы, текст или конструкции.
Использование атрибута mode.
Обработки всех узлов property и вывода их по двум разным шаблонам. Первый, уже знакомый нам “Название поля: значение поля”. Второй, произвольного вида, отличного от первого. Например такой: “Только название поля”.

Подобная задача может встать перед вами, когда вы хотите обработать xml меню в двух местах (шапке и футере сайта), оформив их по разному.

  • Вложенные вызовы.
    Рассмотрим пример, когда мы делаем несколько вложенных вызовов . Например, мы хотим вывести блок с названием группы полей и внутри этого блока вывести все поля данной группы.
  • Уточняющие шаблоны.
    Это одна из самых мощных методик при разработке xslt. Когда вы хотите обработать какой-то элемент (например, узел property), вы можете создать сколь угодно точные инструкции о том, что и как выводить.

    Например, вы хотите вывести все поля типа «Строка» обычным шаблоном, а поля типа “Кнопка-галочка” в виде строчки “Да” , если данная галочка установлена. Для этого, вам достаточно прописать уточняющий шаблон для соответствующего типа поля.
    И таких уточняющих шаблонов может быть сколь угодно много. Вы можете создать общий шаблон, затем шаблон для определенных типов полей, затем добавить шаблоны к конкретным полям (например, проверяя их имя через xml атрибут @name) и т.д.

    Источник

    Copying remaining elements not present in xslt apply template

    I am new to xslt and facing a problem. I have to reorder the elements in an xml file based on a predefined order using xslt. I was successful in doing so by using the xsl:copy-of or xsl:apply-template and reordering the elements. However if the source xml has some new elements not present in the xslt apply template then these new elements are simply not getting copied. Like in the below example the element ‘State’ is lost in the output.

    eg. Original xml

    XSLT that reorders the elements in the order of Qualification , Salary and Background

    Output Obtained

    Output Required

    Please tell me how xslt can copy any remaining new tags automatically after the reordering of the existing tags are done.

    1 Answer 1

    This will first copy the attributes, then the specific elements you’re interested in in the fixed order, and finally everything else except those three elements. Leave out the first apply-templates (the @* one) if you want to copy the Employee tag without its attributes.

    Edit: you say in your comment that you want to keep any comment above the element to which it pertains, even after re-ordering. The most efficient way I can think to do that would be using a key. Define this at the top level of the stylesheet (outside any templates):

    Given any element node, this provides a way to efficiently extract all the non-element nodes that occur between the start tag of this element and the end tag of the one before (or this element’s start tag and its parent’s start tag, if this is the first child element of its parent). The stylesheet then becomes:

    Given the input

    this stylesheet produces the output

    Comments remain attached to their nearest following element, in the same order they appeared in the input document.

    Источник

    xsl:apply-templates¶

    Элемент xsl:apply-templates применяет шаблонные правила к узлам, которые возвращаются выражением, указанным в атрибуте select .

    Если атрибут select опущен, то xsl:apply-templates применяет шаблонные правила ко всем дочерним узлам текущего узла.

    Синтаксис¶

    select необязательный атрибут, выражение вычисляет набор узлов к которым применяются преобразования. Если атрибут не задан — преобразования применяются ко всем потомкам текущего узла, включая текстовые. mode необязательный атрибут, указывает имя режима преобразования.

    Описание и примеры¶

    Пример 1¶

    В примере 1 для элемента chapter создается блок, а затем обрабатывается его непосредственный потомок:

    Пример 2¶

    В примере 2 обрабатываются все содержащиеся в author элементы given-name , которые являются непосредственным потомком author-group :

    Пример 3¶

    В примере 3 обрабатываются все элементы heading , являющиеся потомками элемента book :

    Пример 4¶

    Есть также возможность обрабатывать элементы, которые не являются потомками текущего узла. В примере 4 предполагается, что элемент department имеет непосредственный потомок group и потомки employee . Сперва находится отдел employee , а затем обрабатывается непосредственный потомок group элемента department :

    Пример 5¶

    Для выполнения простого переупорядочения в пределах одного шаблона можно использовать сразу несколько элементов xsl:apply-templates . В примере 5 создаются две таблицы HTML. Первая таблица заполняется отечественными продажами, вторая — международными:

    В XSLT 2.0 у атрибута mode при использовании с элементом появились два специальных значения:

    • #default – соответствует режиму по умолчанию;
    • #current – соответствует текущему режиму.

    В XSLT 2.0 возможности атрибута mode были расширены. В следующей таблице стилей используются значения #default , #current и #all атрибута mode :

    В XSLT 2.0 атрибут mode элемента может принимать новые значения #current и #default . У атрибута mode элемента определены новые значения #all и #default . В нашей таблице стилей используются все три новых значения:

    • В шаблоне match=»/» элемент используется со значениями #default , blue и red . Три элемента отличаются только одним – значением атрибута mode .
    • Первый шаблон match=»manufacturer» не имеет атрибута mode , поэтому он применяется в режиме по умолчанию. При использовании будет активизирован именно этот шаблон.
    • У второго шаблона match=»manufacturer» атрибут mode равен blue red . Этот шаблон активизируется при выборе режима blue или red .
    • Оба шаблона match=»manufacturer» используют запись для обработки элементов . Фактически текущее значение mode передается процессору XSLT в виде параметра, сообщая ему, какой шаблон следует применять.
    • Первый шаблон match=»car» определяется с атрибутом mode=»#all» , поэтому он является шаблоном по умолчанию, который активизируется обоими элементами .
    • Последний шаблон match=»car» определяется с атрибутом mode=»red» . Чтобы ему отдавалось предпочтение перед шаблоном mode=»#all» , мы добавляем атрибут priority=»1″ . Без него процессор Saxon выводит предупреждение о неоднозначном применении правил, хотя и активизирует шаблон mode=»red» при действующем режиме red . Ядро Altova XML никаких предупреждений не выдает – оно просто активизирует шаблон с mode=»red» .

    Начиная с шаблона match=»/» , наша таблица стилей генерирует выходной документ вызовами разных шаблонов с тремя режимами mode . Три режима форматируют одну и ту же информацию тремя разными способами. В итоге таблица стилей создает тот же документ HTML, что и предыдущая таблица стилей.

    Источник

    XSLT apply-templates inside for-each [closed]

    I have an XSLT like below, and want to use apply-templates inside the xsl:for-each element so I don’t have to repeat the

    element with the informations of the » cliente » XML element.

    I’m trying but with no success to create a xsl:template and put xsl:apply-templates inside the xsl:for-each .

    I know that I can use xsl:call-template , but is there any way to use xsl:apply-templates inside or outside the for-each ?

    Any idea on how to do this?

    2 Answers 2

    Inside of your xsl:for-each where you are iterating over informacoes/cliente , the context node will be the current cliente element.

    In order to apply-templates for the context node, you can use . in your select statement. For example:

    Then, create templates to match the cliente element:

    You could also eliminate the tests surrounding some of your items by referring to the current context node using the self:: axis and then applying the test criteria inside of a predicate filter on the context node:

    Applying these changes to your example stylesheet:

    As demonstrated in Dimitre Novatchev’s answer, you can further simplify your stylesheet by eliminating the xsl:for-each statements and adjusting your xsl:apply-templates select statements; applying an xsl:sort inside of the apply-templates where necessary to ensure the selected cliente elements are processed in the desired order.

    Источник

    Практический XSLT. Использование в качестве шаблонизатора. Часть 2

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

    Вывод HTML-контента из XML-документа

    Ранее, мы определили, что все содержание разделов в XML-документе публикуется в блоке . При этом, каждый модуль содержимого помещается в узел .

    Для простоты предположим что пока у нас нет на сайте никакого динамического наполнения: форумов, новостей и д.р. Соответственно, нам на данном этапе достаточно выбрать элементы item у которых указан тип html и раскидать их в шаблоне в соответствии с тем, к какому блоку они относятся (указано в атрибуте container).

    Добавим в шаблон xsl/template.xsl следующий код:

    Мы добавили шаблон для элементов item. В соответствии с ним мы будем для каждого текстового блока выводить его название (атрибут title) и сам текст. Для вывода текста мы воспользуемся инструкцией , в которой мы выбираем текущий элемент (.) и с помощью параметра-атрибута disable-output-escaping мы отключаем «маскирование» входного кода, т.е. текст будет выводиться «как есть». Это нам необходимо для корректного вывода тегов в коде форматирования текста.

    Однако, как правило, наполнение сайта делают люди, которых мало волнует соответствие форматирования текста стандарту XHTML. В случае с использованием XSLT любой незакрытый тэг (тот же
    ) будет вызывать ошибку парсера. Я долгое время пытался придумать разного рода анализаторы кода для чистки вводимого контента (тех-же новостей) на сайт, пока Денис Креминский не подсказал мне одно простое, но весьма эффективное решение: поместить весь опасный код в CDATA.

    Секция CDATA используется для того, чтобы обозначить части документа, которые не должны восприниматься как разметка. Секция CDATA начинается со строки ‘ ‘. Внутри самой секции не должна присутствовать строка ‘ ]]> ‘.

    Другими словами, все что в CDATA XSL-парсером не анализируется и передается в конечный документ «как есть».

    Теперь, нам нужно указать где нам нужно выводить те или иные модули. Для этого, откроем xsl/my_template/layout.xsl и найдем в где у нас начинается разбивка на блоки.

    Предположим, что у вас в изначальном XHTML-шаблоне была следующая таблица:

    В ней описывается простой двух-колоночный макет. Вырежем данный код (всю таблицу) и поместим ее в файл xsl/template.xsl в новый шаблон:

    Мы создали шаблон для блока content. Соответственно, в основном файле xsl/my_template/layout.xsl нам нужно указать, где он должен вызываться. Для этого вставьте в на место вырезанной таблицы следующий код:

    Осталось только добавить в xsl/template.xsl инструкции для вывода нужных нам блоков:

    В результате, из нашего XML-документа основное наполнение страницы будет аккуратно разложено в соответствующие блоки шаблона.

    Создание под-меню

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

    В нашем XML-документе в блоке выводиться все дерево-структура сайта. При этом, для каждого элемента (раздела сайта) у нас предусмотрен атрибут section который задает тип раздела. Однако, наш шаблон для меню навигации пока никак это не учитывает.

    Откроем xsl/navigation.xsl и доработаем немного шаблон :

    Мы указали, что обрабатывать будем только разделы, у которых указан тип section=1.

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

    Допустим, блок во входном XML-документе формируется отдельным модулем CMS и этот модуль указывает номер текущего раздела в корневом узле блока : . Таким образом, в шаблоне для элемента sections перед вызовом обработчиков для item нам нужно им как-то передать номер текущего раздела. Для этого воспользуемся переменными. Переделаем немного строку вызова обработчиков для item:

    Мы поместили внутрь вызова (сделав из него парный элемент) инструкцию , которая создает параметр-переменную cur в контексте текущего вызова.

    Теперь, упростим немного шаблон :

    В проверку мы вставили переменную $cur. Некоторые, наверное спросят: а зачем нам descendant-or-self::*/@id, если можно сравнивать просто с @id, т.е. просто идентификатором текущего раздела? Дело в том, что если у раздела есть подразделы и мы попадаем на них, то нам нужно как-то отметить родительский раздел. Конструкция descendant-or-self::*/@id указывает совпадение атрибута id для узла или любого из его потомков.

    Однако, нам нужно предусмотреть два варианта:

    • когда мы находимся в самом разделе — ссылка на раздел не нужна;
    • когда мы находимся в подразделе — ссылку на раздел делаем.

    При этом, в любом случае, нужно как-то выделить текущий раздел на фоне остальных:

    Здесь мы сталкиваемся с новой конструкцией:

    Инструкция xsl:if позволяет реализовывать условие. В отличие от xsl:choose, можно обозначить шаблон только для случая, когда условие выполняется. В нашем случае, мы проверяем descendant::*/@id — совпадение id дочерних элементов с переменной $cur.

    Для полноты нашего меню нам нужно где-то вывести подразделы (если таковые имеются) для выбранного раздела.

    Для простоты, выведем дерево всех подразделов текущего раздела в правой колонке нашего шаблона. Для этого откроем xsl/template.xsl и немного изменим шаблон :

    Добавили проверку существования дочерних элементов у текущего раздела:

    При этом учитывается то обстоятельство, что текущим может быть подраздел раздела.

    Далее, нам нужно создать вызываемый шаблон:

    Для этого, добавить следующий код в xsl/my_template/navigation.xsl:

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

    Такой универсальности позволяет добиться CSS и верстка с помощью слоев. Я до сих пор в отдельных случаях использую таблицы для верстки, но постепенно стараюсь переходить на DIV-верстку, т.к. она позволяет значительно сократить код и, что более важно для XSLT, сделать шаблоны универсальными. Например, для большей части последних сайтов мне не пришлось переделывать navigation.xsl.

    Однако, отличия в подменю все-же есть. В том, что оно может иметь много уровней. Соответственно, шаблон также будет отличаться от соответствующего шаблона для основного меню разделов:

    Отличие одно — мы обрабатываем дочерние элементы item для каждого item, рекурсивно вызывая шаблон .

    P.S. Подготовка статьи отнимает массу времени. Однако, эта работа позволила мне взглянуть свежим взглядом на свои старые XSL-шаблоны.

    UPD: Исходники.
    К сожалению, дальше пришлось отказаться от использования браузера для компиляции XSLT.

    Источник

    Читайте также:  Joomla как настроить smtp
    Оцените статью