2012-05-04 3 views
4

Кажется, что функция tokenize EXSLT недоступна с PHP XSLTProcessor (XSLT 1.0).Как реализовать функцию toklize XSLT?

я попытался реализовать в чистом XSL, но я не могу заставить его работать:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:func="http://exslt.org/functions" 
    xmlns:exsl="http://exslt.org/common" 
    xmlns:my="http://mydomain.com/"> 

    <func:function name="my:tokenize"> 
     <xsl:param name="string"/> 
     <xsl:param name="separator" select="'|'"/> 
     <xsl:variable name="item" select="substring-before(concat($string,$separator),$separator)"/> 
     <xsl:variable name="remainder" select="substring-after($string,$separator)"/> 
     <xsl:variable name="tokens"> 
      <token><xsl:value-of select="$item"/></token> 
      <xsl:if test="$remainder!=''"> 
       <xsl:copy-of select="my:tokenize($remainder,$separator)"/> 
      </xsl:if> 
     </xsl:variable> 
     <func:result select="exsl:node-set($tokens)"/> 
    </func:function> 

    <xsl:template match="/"> 
     <xsl:copy-of select="my:tokenize('a|b|c')"/> 
    </xsl:template> 

</xsl:stylesheet> 

Ожидаемый результат:

<token>a</token><token>b</token><token>c</token> 

Фактический результат:

abc 

Я знаю, этот вопрос был опубликован много раз, но я не могу найти простое решение.

Благодарим за помощь.

ответ

7

Цитирование http://www.exslt.org/str/functions/tokenize/index.html

следующие процессоры XSLT ул поддержки: разметить:

  • 4XSLT, от 4Suite. (версия 0.12.0a3)
  • libxslt от Daniel Veillard et al. (Версия 1.0.19)

Поскольку PHP использует LibXSLT, это означает, что tokenize доступен, но вы должны использовать правильные пространства имен расширений (которые вы не делаете):

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:str="http://exslt.org/strings" 
    extension-element-prefixes="str" 
    … 

Тогда вам можно использовать разметить как функцию, например, чтобы построить поле выбора с номерами 1-12:

<select name="months"> 
    <xsl:for-each select="str:tokenize('1,2,3,4,5,6,7,8,9,10,11,12', ',')"> 
     <xsl:element name="option"> 
      <xsl:attribute name="value"> 
       <xsl:value-of select="."/> 
      </xsl:attribute> 
      <xsl:value-of select="."/> 
     </xsl:element> 
    </xsl:for-each> 
</select> 
1

Я могу быть немного старомодны, так как я не использую функции, но у меня есть followi нг tokenize шаблон, который делает то, что вы хотите без каких-либо специальных расширений:

<xsl:template name="tokenize"> 
    <xsl:param name="string"/> 
    <xsl:param name="separator" select="'|'"/> 

    <xsl:choose> 
    <xsl:when test="contains($string,$separator)"> 
     <token> 
     <xsl:value-of select="substring-before($string,$separator)"/> 
     </token> 
     <xsl:call-template name="tokenize"> 
     <xsl:with-param name="string" select="substring-after($string,$separator)"/> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <token><xsl:value-of select="$string"/></token> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

Она вызывается следующим образом и должны дать вам желаемый результат:

<xsl:call-template name="tokenize"> 
    <xsl:with-param name="string" select="'a|b|c'"/> 
</xsl:call-template> 
0

Вам не придется написать собственная реализация - просто используйте существующий шаблон FXSLstr-split-to-words, который обеспечивает еще более мощную функциональность.

Вот краткий Демонстрационный использования str-split-to-words:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common"> 

    <xsl:import href="strSplit-to-Words.xsl"/> 
    <xsl:output indent="yes" omit-xml-declaration="yes"/> 

    <xsl:template match="/"> 
     <xsl:variable name="vwordNodes"> 
     <xsl:call-template name="str-split-to-words"> 
      <xsl:with-param name="pStr" select="/"/> 
      <xsl:with-param name="pDelimiters" 
          select="', &#9;&#10;&#13;'"/> 
     </xsl:call-template> 
     </xsl:variable> 

     <xsl:apply-templates select="ext:node-set($vwordNodes)/*"/> 
    </xsl:template> 

    <xsl:template match="word"> 
     <xsl:value-of select="concat(position(), ' ', ., '&#10;')"/> 
    </xsl:template> 
</xsl:stylesheet> 

когда это преобразование применяется на следующий документ XML:

<t>out, of 
luck</t> 

производится разыскиваемый результат - последовательность всех слов с их позициями.

Обратите внимание, что любой максимальной длины последовательности соседних символов разделителей, которые предусмотрены в параметре pDelimiters используется в качестве разделителя:

1 out 
2 of 
3 luck