Тестирование элементов в списке

Для таблицы стилей, которую я пишу (фактически для набора из них, каждый из которых генерирует свой выходной формат), мне нужно оценить, присутствует ли определенное значение в списке значений. В этом случае проверяемое значение берется из атрибута элемента. Список, с которым он должен быть проверен, происходит от вызова таблицы стилей и принимается как верхний уровень <xsl:param>(должен быть предоставлен в командной строке, когда я вызываю xsltprocили эквивалентный саксонский вызов). Например, входное значение может быть:

v0_01,v0_10,v0_99

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

То, что я ищу, является чем-то похожим на Perl grep, в котором я могу видеть, содержится ли значение, которое у меня есть в данный момент, в списке. Это может быть сделано с помощью подстроковых тестов, но это должно быть умно, чтобы не получить ложноположительный результат ( v0_01не должен совпадать со строкой, которая содержит v0_011). Кажется, что единственный нескалярный тип данных, который поддерживает XSL / XSLT, - это набор узлов. Я предполагаю, что возможно преобразовать список в набор текстовых узлов, но это выглядит как перебор, даже по сравнению с выполнением теста подстроки с дополнительной проверкой границ для предотвращения ложных совпадений.

10.12.2008 13:30:17
2 ОТВЕТА

На самом деле, использование строковых функций XPath - верный способ сделать это. Все, что вам нужно, это убедиться, что вы также проверяете разделители:

contains(concat(',' $list, ','), concat(',', $value, ','))

вернул бы логическое значение. Или вы можете использовать один из них:

substring-before(concat('|,' $list, ',|'), concat(',', $value, ','))

или

substring-after(concat('|,' $list, ',|'), concat(',', $value, ','))

Если в результате вы получите пустую строку, то $valueее нет в списке.

РЕДАКТИРОВАТЬ:

@ Комментарий Димитра верен: substring-before()(или substring-after()) также возвращает пустую строку, если найденная строка является первой (или последней) в списке. Чтобы избежать этого, я добавил что-то в начало и конец списка. Тем не менее contains()это рекомендуемый способ сделать это.

8
6.11.2012 15:36:16
На самом деле, для моих целей, похоже, что подойдет функция «содержит» (используя предложенный вами отступ). Меня поразило то, что я искал эту функциональность в самом XSLT, когда мне следовало искать в XPath.
rjray 10.12.2008 14:20:24
Добавлена ​​функция Содержит (), которая меня избежала. Спасибо. :-)
Tomalak 10.12.2008 14:29:32
@Tomalak: выражение substring-before () будет иметь значение '', даже если значение содержится в списке (когда оно является первым значением). Аналогично, выражение substring-after () оценивается как '', когда значение является последним в списке. Следовательно, корректно только выражение содержит ()
Dimitre Novatchev 10.12.2008 16:56:54
@Tomalak: Следовательно, эти два выражения должны быть объединены вместе, но это намного длиннее и, вероятно, значительно менее эффективно, чем выражение contains ().
Dimitre Novatchev 10.12.2008 16:57:27
Итак, я бы немного изменил concat (), чтобы учесть это.
Tomalak 10.12.2008 18:16:20

В дополнение к решению XPath 1.0, предоставленному Tomalak, с

помощью XPath 2.0 можно токенизировать список значений:

    exists(tokenize($list, ',')[. = $value])

оценивает, true()если и только если $valueсодержится в списке значений$list

4
10.12.2008 17:03:47
Не лучше ли написать так: tokenize ($ list, ',') = $ value
lagivan 21.01.2014 12:20:44
@lagivan, это зависит от того, что мы понимаем лучше. Я думаю, что использование слова «существует» (как слова или понятия) сразу становится более понятным и естественным для людей, которые не привыкли к ярлыкам XPath. Кроме того, функция exist () может быть лучше оптимизирована, чем обычное сравнение значений.
Dimitre Novatchev 21.01.2014 15:04:10