Предположим, что мой ввод 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, *"/>
. Опять же, прямо сейчас это вызывает обманы, которых я не хочу.
Я использую Саксон.
Так что я бы хотел запустить
<xsl:apply-templates select = "INTRO, *">
, но чтобы INTRO не совпадало дважды
Пытаться:
<xsl:apply-templates select = "INTRO, * except INTRO">
Я не думаю, что это нарушает принцип DRY. Если у вас есть несколько элементов, которые нужно поставить первыми, вы можете определить их в переменной, а затем сделать <xsl:apply-templates select = "$var, * except $var">
. Но деление набора на x
и not(x)
, на мой взгляд, совершенно законно.
@ KP99, я думаю, что предложенный ответ подходит и соответствует вашему требованию. Если вас действительно беспокоит этот принцип DRY, то в XSLT 3 с XPath 3.1 вы, конечно, также можете использовать select = "let $intro := INTRO return ($intro, * except $intro)"
, но я не вижу, как это улучшит ситуацию, в конце концов, для вашего выбора вы хотите построить последовательность INTRO
за которым следуют любые дочерние элементы, кроме INTRO, и опубликованный ответ - это идиоматический способ выражения XSLT2/3.
Кажется, это работает. Если у кого-то есть лучший ответ, дайте мне знать, и я изменю его.
Здесь нет нарушения 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
недостаточно для реализации требования?
Тот факт, что функция появляется (как иллюстрация) в спецификации, не означает, что она является хорошим решением текущей проблемы. Это не. Решение с использованием except
добавляет все узлы, кроме уже обработанных. Ваше решение достигает того же результата с гораздо большим количеством кода, но менее эффективно, потому что ему приходится дважды тестировать явно названные узлы.
Я обновил ответ, чтобы ответить на комментарий Мартина. Мы с радостью используем этот ответ сегодня в аэрокосмических руководствах, где точность и СУХОЙ имеют первостепенное значение. Если вы хотите использовать другой ответ, сделайте это.
НЕ СУХОЙ en.wikipedia.org/wiki/Don%27t_repeat_yourself