Не могу перестать думать о XSLT в процедурных терминах ... помощь с шаблонами приложений

Я знаю, что XSLT не работает с процедурной точки зрения, но, к сожалению, я слишком долго занимался процедурными языками. Может ли кто-нибудь помочь мне, объяснив простыми словами, как работают такие вещи, как apply-templates, и помочь таким тупицам, как я, понять это.

Полностью согласен с сообщением в блоге Грега Бича. Подробнее об этом читайте в моем ответе.

Dimitre Novatchev 02.12.2008 21:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
1
921
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я написал запись в блоге много лет назад, который показывает простую таблицу стилей, написанную в «процедурном» стиле с использованием xsl:for-each и его эквивалента с использованием xsl:apply-templates. Это ни в коем случае не исчерпывающее руководство, но, надеюсь, оно будет полезно.

Я не уверен, что согласен с мнением - для каждой структуры много проще! XSLT ребята для понимания, а XSLT уже слишком многие считают вуду (читаемость имеет значение) - но это хорошо написанная часть

annakata 02.12.2008 12:52

Это действительно начинает уменьшать мистицизм, окружающий меня магическими шаблонами. Кроме того, я только что обнаружил, что пошаговое выполнение примеров с использованием Visual Studio (2008) тоже помогло.

Xetius 02.12.2008 13:16

Полностью согласен с сообщением в блоге. Подробнее об этом читайте в моем ответе.

Dimitre Novatchev 02.12.2008 21:00

Я знаю, что прошло много лет, но ссылка на вашу запись в блоге кажется мертвой. Этот контент еще доступен?

Andrew Neely 12.07.2013 20:25

Ага - ты прав, ссылка была мертва. Теперь обновили его на правильный.

Greg Beech 12.07.2013 20:29
Ответ принят как подходящий

Что заставляет вас думать, что процедурные условия здесь не применяются? Просто соглашение о вызовах несколько более неявно, чем вы традиционно ожидали, потому что здесь задействован невидимый контекст. Все, что делает apply-templates, можно выразить процедурными терминами.

По сути, apply-templates - это не что иное, как цикл for-each. Начиная с того места, где вы сейчас находитесь в документе (контекст, подумайте «this»), он перебирает дочерние узлы.

Для каждого дочернего элемента процессор выбирает соответствующий xsl:template с наивысшим приоритетом (на основе их соответствующих атрибутов match и priority), устанавливает контекст для данного дочернего элемента и запускает этот шаблон (подумайте «function»). После того, как шаблон возвращается, контекст возвращается, и наступает очередь следующего ребенка.

Даже когда что-то становится рекурсивным (чего трудно избежать в XSLT), весь процесс действительно не становится более сложным. «Указатель» контекста перемещается, и вызываются шаблоны.

Вы можете ограничить набор узлов, который выполняет итерация apply-templates, используя атрибут select:

<!-- all children of the context node regardless -->
<xsl:apply-templates />  

<!-- all children of the context node being "data" with a @name of "Foo" -->
<xsl:apply-templates select = "data[@name='Foo']" />  

Вы можете отсортировать набор узлов до итерации, если хотите:

<!-- all children of the context node being "data" with a @name of "Foo",
     ordered by their respective "detail" count -->
<xsl:apply-templates select = "data[@name='Foo']"> 
  <xsl:sort select = "count(detail)" data-type = "number" order = "descending"/>
</xsl:apply-templates>

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

<!-- pass in some parameter -->
<xsl:apply-templates select = "data[@name='Foo']"> 
  <xsl:with-param name = "DateSetIcon" select = "$img_src" />
</xsl:apply-templates>

Вот и все, что нужно знать об этом.

Обновлено:

Знаю, что последний комментарий несколько провокационный. Это сделано намеренно, для базового понимания того, как работает apply-templates, это более или менее. Последствия и возможности, возникающие из-за того, что не ты определяют, какой шаблон вызывать, а позволяют процессору выбрать правильный для вас, конечно, больше, чем то, как это звучит для неподготовленного уха. Декларативный / неявный подход ко всему этому, безусловно, требует некоторого времени, чтобы осваиваться.

«Вот и все» ... Не совсем, см. Мой ответ.

Dimitre Novatchev 02.12.2008 20:46

Я полностью согласен с ответом и сообщением в блоге Грега Бича.

Для более подробного сравнения <xsl:for-each> и <xsl:apply-templates> см. мой ответ к вопросу «xsl: for-each vs. xsl: apply-templates» в xsl-list и наслаждайтесь целая нить.

«xsl: apply-templates намного богаче и глубже, чем xsl: for-each, даже просто потому, что мы не знаем, какой код будет применен к узлам выбор - в общем случае этот код будет другим для разные узлы списка узлов. Также код, который будет применяться можно написать после того, как были написаны шаблоны xsl: apply и люди, которые не знают первоначального автора».

Еще одно отличие от процедурного языка программирования заключается в том, что порядок, в котором будут применяться шаблоны, не определен заранее. В чистом функциональном языке программирования нет понятия «состояние» или «порядок выполнения».

Ни XSLT 2.0, ни XSLT 1.0 не определяют какой-либо конкретный порядок применения выбранных правил шаблона - только то, что их результаты будут объединены в соответствии с порядком узлов (в отсортированной последовательности, если есть какие-либо директивы <xsl:sort> или иначе в порядке документа узлы), на которых применяются шаблоны.

XSLT 2.0 Spec говорит:

«Каждое проверяемое правило шаблона создает в качестве результата последовательность элементов. Результирующие последовательности (по одной для каждого узла в отсортированной последовательности) затем объединяются, чтобы сформировать единую последовательность. Они объединяются, сохраняя порядок узлов в отсортированной последовательности. Окончательная объединенная последовательность формирует результат инструкции xsl: apply-templates»

В спецификации XSLT 1.0 говорится:

"Реализации могут обрабатывать исходный документ любым способом, который дает такой же результат, как если бы он был обработан с использованием этой модели обработки.."

Возможно даже, что реализация XSLT может применять шаблоны (или тело <xsl:for-each>) параллельно.

Я не вижу, что было бы неправильным в моем ответе. Вы добавляете подробности о порядке выполнения, но для результата преобразования (и всего остального, XSL должен быть свободным от побочных эффектов) порядок выполнения не имеет значения, или нет? Мое «об этом все» может быть провокационным, но что еще?

Tomalak 03.12.2008 17:10

Tomalak, мой комментарий был: «Вот и все, что есть» ... Не совсем, см. Мой ответ ». Я никогда не говорил, что ваш ответ был неправильным. Проще говоря, <xsl: apply-templates> - это гораздо более обширная тема. Ваше здоровье

Dimitre Novatchev 03.12.2008 17:30

Я подумал, что «не совсем» было бы более дружелюбным способом сказать «это неправильно» (обычно это происходит в англоязычном мире).

Tomalak 03.12.2008 19:03

(И, сложив два и два, я подумал, что голосование против вас было вашим и что в моем ответе должна быть ошибка.)

Tomalak 03.12.2008 19:05

Эй, я давно не голосовал против! :) Спасибо за напоминание. И нет, я даже не знал (никак не мог это увидеть), что ваш ответ был отклонен. Вы хотите это проверить? Могу прислать вам скриншот моей вкладки "Голоса". Ваше здоровье

Dimitre Novatchev 03.12.2008 20:53

Не обязательно, я вам верю! ;-) Все равно ничего страшного. Иногда голоса против могут быть связаны с комментариями типа «Я так не думаю», поэтому это казалось вероятным. Жалко, что голоса против часто идут без объяснения причин.

Tomalak 03.12.2008 23:35

Да, я думаю, было бы хорошо, если бы SO изменил способ голосования против, сделав объяснение обязательным. Может быть, даже показать идентификатор пользователя, проголосовавшего против.

Dimitre Novatchev 04.12.2008 02:57

Это сработает только в том случае, если каждый пользователь будет разумным и справедливым, что можно смело исключить. Многие пользователи переключились бы в режим «око за око» ... К сожалению, кажется, что никто не может придумать работоспособную альтернативу, были сделаны различные предложения по Uservoice, но все они так или иначе были ошибочными.

Tomalak 04.12.2008 10:13

Другие вопросы по теме