Xsl 3.0: как сначала обрабатывать определенные дочерние элементы в xsl:apply-templates, а затем остальные (переопределяющий порядок документов)

Предположим, что мой ввод xml представляет собой элемент MFMATR с несколькими дочерними элементами, такими как: TRLIST, INTRO и SBLIST — в этом порядке документа. Я конвертирую в HTML.

У меня есть шаблон, который соответствует элементу MFMATR, и я хочу запустить xsl:apply-templates для 3 дочерних элементов, но я хочу, чтобы сначала обрабатывался INTRO (первый в списке в HTML). Два других (TRLIST и SBLIST) должны сохранять относительный порядок документов, если INTRO стоит перед ними обоими.

Так что я бы хотел запустить <xsl:apply-templates select = "INTRO, *">, но чтобы INTRO не совпадало дважды. (Использование этого синтаксиса с xsl 3.0 вызывает у меня ошибки.) Я также не хочу явно перечислять каждый тег в выражении выбора, поэтому неизвестные теги все равно будут обрабатываться.

Второй пример из реальной жизни: <xsl:apply-templates select = "TITLE, CHGDESC, *"/>. Опять же, прямо сейчас это вызывает обманы, которых я не хочу.

Я использую Саксон.

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Так что я бы хотел запустить <xsl:apply-templates select = "INTRO, *">, но чтобы INTRO не совпадало дважды

Пытаться:

<xsl:apply-templates select = "INTRO, * except INTRO">

НЕ СУХОЙ en.wikipedia.org/wiki/Don%27t_repeat_yourself

KP99 04.02.2023 08:17

Я не думаю, что это нарушает принцип DRY. Если у вас есть несколько элементов, которые нужно поставить первыми, вы можете определить их в переменной, а затем сделать <xsl:apply-templates select = "$var, * except $var">. Но деление набора на x и not(x), на мой взгляд, совершенно законно.

y.arazim 04.02.2023 11:14

@ KP99, я думаю, что предложенный ответ подходит и соответствует вашему требованию. Если вас действительно беспокоит этот принцип DRY, то в XSLT 3 с XPath 3.1 вы, конечно, также можете использовать select = "let $intro := INTRO return ($intro, * except $intro)", но я не вижу, как это улучшит ситуацию, в конце концов, для вашего выбора вы хотите построить последовательность INTRO за которым следуют любые дочерние элементы, кроме INTRO, и опубликованный ответ - это идиоматический способ выражения XSLT2/3.

Martin Honnen 04.02.2023 11:56
Ответ принят как подходящий

Кажется, это работает. Если у кого-то есть лучший ответ, дайте мне знать, и я изменю его.

Здесь нет нарушения DRY — нет повторяющихся имен элементов или имен переменных. Я хочу, чтобы он выглядел чистым на всех сайтах вызова, которые у меня будут.

Мне это кажется идиоматичным, так как функция была взята с собственного веб-сайта w3!

<xsl:template match = "MFMATR">
  <!-- Process INTRO first, no matter where it appears -->
  <xsl:variable name = "nodes" select = "INTRO, *"/>
  <xsl:apply-templates select = "kp:distinct_nodes_stable($nodes)"/>
</xsl:template>

<xsl:template match = "INTRO">
  <xsl:variable name = "nodes" select = "TITLE, CHGDESC, *"/>
  <xsl:apply-templates select = "kp:distinct_nodes_stable($nodes)"/>
</xsl:template>

<!-- Discard duplicate elements in $seq, but keep their ordering -->
<!-- Adapted from https://www.w3.org/TR/xpath-functions/#func-distinct-nodes-stable -->
<xsl:function name = "kp:distinct_nodes_stable" as = "node()*">
  <xsl:param name = "seq" as = "node()*"/>
  <xsl:sequence select = "fold-left($seq, (),
    function($foundSoFar as node()*, $this as node()) as node()* {
      if ($foundSoFar intersect $this)
      then $foundSoFar
      else ($foundSoFar, $this)
    }) "/>
</xsl:function>

Если цель состоит в том, чтобы «хочу запустить xsl:apply-templates для 3 дочерних элементов, но я хочу, чтобы INTRO обрабатывался первым (указанный первым в HTML). Два других (TRLIST и SBLIST) должны сохранять относительный порядок документов» , как перечислить порядок для TRLIST и SBLIST, например, SBLIST, TRLIST обеспечить соблюдение порядка документов? И если вы знаете три дочерних элемента, почему INTRO, TRLIST | SBLIST недостаточно для реализации требования?

Martin Honnen 04.02.2023 16:49

Тот факт, что функция появляется (как иллюстрация) в спецификации, не означает, что она является хорошим решением текущей проблемы. Это не. Решение с использованием except добавляет все узлы, кроме уже обработанных. Ваше решение достигает того же результата с гораздо большим количеством кода, но менее эффективно, потому что ему приходится дважды тестировать явно названные узлы.

michael.hor257k 06.02.2023 15:43

Я обновил ответ, чтобы ответить на комментарий Мартина. Мы с радостью используем этот ответ сегодня в аэрокосмических руководствах, где точность и СУХОЙ имеют первостепенное значение. Если вы хотите использовать другой ответ, сделайте это.

KP99 07.02.2023 18:42

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