【问题标题】:How to implement XSLT tokenize function?如何实现 XSLT 标记化功能?
【发布时间】:2012-05-13 21:46:37
【问题描述】:

似乎 EXSLT 标记化功能不适用于 PHP XSLTProcessor (XSLT 1.0)。

我尝试在纯 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

我知道这个问题已经发布了很多次,但我找不到简单的解决方案。

感谢您的帮助。

【问题讨论】:

    标签: php xml xslt tokenize


    【解决方案1】:

    您不必编写自己的实现 - 只需使用现有的 FXSL str-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
    

    【讨论】:

      【解决方案2】:

      我可能有点过时,因为我不使用函数,但我有以下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>
      

      【讨论】:

        【解决方案3】:

        引用http://www.exslt.org/str/functions/tokenize/index.html

        以下 XSLT 处理器支持 str:tokenize:

        • 4XSLT,来自 4Suite。 (版本 0.12.0a3)
        • 来自 Daniel Veillard 等人的 libxslt。 (版本 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"
            …
        

        然后你可以使用tokenize作为一个函数,例如构建一个带有数字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>
        

        【讨论】:

          猜你喜欢
          • 2018-09-05
          • 2012-08-08
          • 1970-01-01
          • 2016-11-17
          • 2017-07-06
          • 2018-11-11
          • 2011-12-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多