Список выбора для идентификатора, заканчивающегося переменной

#xslt

#xslt

Вопрос:

Я хочу выбрать все узлы для данного идентификатора, но это может закончиться дополнительным числом. Как я могу это сделать?

Пример:

  <group id="list">
 <group id="list1">
 <group id="list2">
 <group id="map">
 <group id="map1">
  

Объявление, которое я имею сейчас:

 <xsl:variable name="rule">
<data>
    <node>list</node>
    <node>map</node>
</data>
</xsl:variable>

<xsl:template match="/">
    <xsl:apply-templates select=".//group[ @id = exslt:node-set($rule)/data/node]"/>
</xsl:template>
  

и это позволяет my работать только с узлами, указанными в списке «правило». [XSLT v1.0]

Пожалуйста, сообщите.

Ответ №1:

I. Решение XSLT 1.0:

Это преобразование:

 <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:param name="pIds">
  <id>list</id>
  <id>map</id>
 </xsl:param>

 <xsl:variable name="vIds" select=
  "document('')/*/xsl:param[@name='pIds']/*"/>

 <xsl:template match="group">
  <xsl:if test=
  "$vIds[. = current()/@id
        or
         starts-with(current()/@id, .)
        and
         substring-after(current()/@id, .)
        =
         floor(substring-after(current()/@id, .))
        ]
  ">
   <!-- Processing here: -->
   <xsl:copy-of select="."/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>
  

при применении к этому XML-документу:

 <t>
 <group id="list"/>
 <group id="list1"/>
 <group id="listX"/>
 <group id="list2"/>
 <group id="map"/>
 <group id="map123Z"/>
 <group id="map1"/>
</t>
  

обрабатывает (в этом примере копирует) точно совпадающие узлы:

 <group id="list"/>
<group id="list1"/>
<group id="list2"/>
<group id="map"/>
<group id="map1"/>
  

Объяснение:

  1. Использование стандартных функций XPath starts-with() substring-after() и floor() .

  2. Простой тест, если строка преобразуется в целое число,: floor($s) = $s

II. Решение XSLT 2.0:

 <xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:param name="pIds" select="'list', 'map'"/>

 <xsl:variable name="vIds" select=
  "document('')/*/xsl:param[@name='pIds']/*"/>

 <xsl:template match=
 "group
   [@id = $pIds
   or
    $pIds
      [starts-with(current()/@id, .)
     and
        substring-after(current()/@id, .)
       castable as
        xs:integer
       ]
    ]
 ">
   <!-- Processing here: -->
   <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>
  

Объяснение: Это решение очень похоже на решение XSLT 1.0 со следующими основными отличиями:

  1. В XSLT 2.0 разрешено иметь ссылки на переменные / параметры в шаблоне сопоставления. Используя это, мы избегаем <xsl:if> внутри тела шаблона.

  2. Мы определяем параметр так, чтобы он содержал последовательность желаемых строк.

  3. Мы используем стандартный оператор XPath 2.0 castable as .