Как я могу применить шаблон xslt к строке?

Учитывая шаблон, используемый для построения некоторого HTML вокруг значения, я хочу передать строку, а не набор узлов. В качестве примера я хочу объединить некоторые значения и передать их в шаблон. Как я могу достичь такого рода вещей?

<xsl:template match="text()" mode="kvp-print-single">
    <tr>
        <td colspan="3"><xsl:value-of select="."/></td>
    </tr>
</xsl:template>

...

<xsl:apply-templates select="concat=(haba/hiba:text(), ' - ', huba/baba:text())" mode="kvp-print-single"/>

ErrorMsg: файл XML или таблицы стилей недействителен!

Исключение: System.Xml.Xsl.XsltException: выражение должно вычисляться как набор узлов.

3 ответа

Решение

Если целью является повторное использование кода, чтобы использовать шаблон в нескольких местах, то вы можете дать вашему шаблону имя (в дополнение к совпадению с шаблоном) и задать для него параметр по умолчанию

<xsl:template match="text()" name="kvp-print-single" mode="kvp-print-single">
    <xsl:param name="text" select="." />
    <tr>
        <td colspan="3"><xsl:value-of select="$text"/></td>
    </tr>
</xsl:template>

Затем просто используйте xsl:call-template, чтобы вызвать его со связанной строкой в ​​качестве параметра.

<xsl:call-template name="kvp-print-single">
   <xsl:with-param name="text" select="concat(haba/hiba:text(), ' - ', huba/baba:text())" />
</xsl:call-template>

Обратите внимание, что при сопоставлении с использованием xsl: apply-templates шаблон все равно будет соответствовать узлам text() обычным образом.

Вы можете использовать call-template и именованный шаблон, а не apply-templates, таким образом:

<xsl:template name="kvp-print-single">
  <xsl:param name="theValue"/>
   <tr>
        <td colspan="3"><xsl:value-of select="$theValue"/></td>
    </tr>
</xsl:template>

<xsl:call-template name="kvp-print-single">
   <xsl:with-param name="theValue" select="concat(haba/hiba:text(), ' - ', huba/baba:text())"/>
</xsl:call-template>

Смысл применения шаблонов состоит в том, чтобы взять набор узлов и применить наиболее подходящий шаблон к каждому узлу по очереди. Шаблоны вызовов и именованные шаблоны позволяют разбить ваш XSLT на более управляемые куски, не меняя контекст.

Вы не можете "передать строку, а не набор узлов", потому что шаблоны не вызываются как функции. В XSLT не код контролирует порядок выполнения, а данные - путем сопоставления шаблонов. Можно использовать именованные шаблоны, которые можно вызывать вместо сопоставления, но для передачи значений можно использовать параметры для каждого шаблона.

В вашем случае вам даже не нужно это делать, так как вы можете адресовать текстовые части (учитывая, что haba/hiba - это адрес) примерно так:

<xsl:template match="some_element" mode="kvp-print-single">
  <tr>
    <td colspan="3">
      <xsl:value-of select="concat=(/root/haba/hiba/text(), ' - ', /root/huba/baba/text())"/>
    </td>
  </tr>
</xsl:template>  

Конечно, адрес должен быть правильным XPath (абсолютным или даже относительно соответствующего элемента).

@Mithon: другие ответы требуют параметров. Используйте столько модульных шаблонов, сколько вы хотите, но зачем вам добавлять параметры, если они вам не нужны?

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