xsl:如何拆分字符串?

Posted

技术标签:

【中文标题】xsl:如何拆分字符串?【英文标题】:xsl: how to split strings? 【发布时间】:2011-06-18 06:07:54 【问题描述】:

我想将分号 (;) 上的地址拆分为由<br /> 分隔的行:

例如如果address=123 Elm Street,我想输出123 Elm Street

但是如果address=123 Elm Street;PO Box 222,我想输出

123 Elm Street<br />PO Box 222

如果address=123 Elm Street;PO Box 222;c/o James Jones,我想输出

123 Elm Street<br />PO Box 222<br />c/o James Jones

有没有办法做到这一点? (可能很简单,但我对 XSLT 不太熟悉)

普通的 XSL 选择器是

<xsl:value-of select="address"/>

我想修改这个 XSLT 片段以分号分割。


更新:显然答案涉及使用&lt;xsl:call-template&gt; 以及函数substring-before()substring-after()

但我是 XSLT 的初学者,我真的可以使用一些帮助来了解如何做到这一点。

【问题讨论】:

Does XSLT have a Split() function? 的可能重复项 也许它几乎是重复的,但我不知道如何将这个问题的答案应用到我的问题上。 另见***.com/questions/10750184/… 【参考方案1】:

我。普通的 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:template match="text()" name="split">
  <xsl:param name="pText" select="."/>
  <xsl:if test="string-length($pText)">
   <xsl:if test="not($pText=.)">
    <br />
   </xsl:if>
   <xsl:value-of select=
    "substring-before(concat($pText,';'),';')"/>
   <xsl:call-template name="split">
    <xsl:with-param name="pText" select=
     "substring-after($pText, ';')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

应用于此 XML 文档时

<t>123 Elm Street;PO Box 222;c/o James Jones</t>

产生想要的、更正的结果

123 Elm Street<br />PO Box 222<br />c/o James Jones

二。 FXSL 1(用于 XSLT 1.0):

这里我们只使用FXSL模板str-map(不必第999次编写递归模板):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:testmap="testmap"
exclude-result-prefixes="xsl f testmap"
>
   <xsl:import href="str-dvc-map.xsl"/>

   <testmap:testmap/>

   <xsl:output omit-xml-declaration="yes" indent="yes"/>

   <xsl:template match="/">
     <xsl:variable name="vTestMap" select="document('')/*/testmap:*[1]"/>
     <xsl:call-template name="str-map">
       <xsl:with-param name="pFun" select="$vTestMap"/>
       <xsl:with-param name="pStr" select=
       "'123 Elm Street;PO Box 222;c/o James Jones'"/>
     </xsl:call-template>
   </xsl:template>

    <xsl:template name="replace" mode="f:FXSL"
         match="*[namespace-uri() = 'testmap']">
      <xsl:param name="arg1"/>

      <xsl:choose>
       <xsl:when test="not($arg1=';')">
        <xsl:value-of select="$arg1"/>
       </xsl:when>
       <xsl:otherwise><br /></xsl:otherwise>
      </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

当此转换应用于任何 XML 文档(未使用)时,会产生相同的、想要的正确结果

123 Elm Street<br/>PO Box 222<br/>c/o James Jones

三。使用 XSLT 2.0

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

 <xsl:template match="text()">
  <xsl:for-each select="tokenize(.,';')">
   <xsl:sequence select="."/>
   <xsl:if test="not(position() eq last())"><br /></xsl:if>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于此 XML 文档时

<t>123 Elm Street;PO Box 222;c/o James Jones</t>

产生想要的正确结果

123 Elm Street<br />PO Box 222<br />c/o James Jones

【讨论】:

您能解释一下not($pText=.) 的语法吗? . 在做什么? @Jason-S: . 在 XSLT(和 XPath)中表示当前节点(上下文节点)。 not($pText=.)true()如果参数$pText的字符串值不等于当前节点的字符串值——我们只想在这种情况下输出&lt;br /&gt;,否则我们的输出将以@987654338开头@ 我可以将已经存在的变量传递给参数 name="pText" 吗? @Perdomoff,是的,在 XSLT 中,&lt;xsl:with-param ...&gt;select 属性中提供的参数可以是任何 XPath 表达式,并且变量引用是有效的 XPath 表达式。在 XSLT 2.0 及更高版本中调用 ` 时,为参数提供值也是如此。 这确实有效,谢谢。我可以从另一个 xsl 文件中传递一个变量吗?【参考方案2】:

如果您的 XSLT 处理器支持 EXSLT,则可以使用 str:tokenize,否则,该链接包含使用 substring-before 等函数的实现。

【讨论】:

我该如何找到?我的 XSLT 处理器是一个 Web 浏览器,Firefox 3.6 或 Safari 5.0 @Jason S - 在这种情况下,你不能依赖它,你需要自己提供函数;该实现可在链接的exslt.org/str/functions/tokenize/str.tokenize.template.xsl 这里是一个例子:***.com/questions/10750184/…

以上是关于xsl:如何拆分字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 c# xsltTransformer 在 Azure、FTP 和 SFTP 中使用 xsl:result-document 保存拆分文件?

如何解决从字符串加载 XSL 的转换中包含的 XSL?

XSLT 有 Split() 函数吗?

xslt 有 split() 功能吗?

在比较 XSLT <xsl:if> 中的字符串时,如何指定“不等于”?

当输入 XML 和转换 XSL 是字符串时,如何使用 XslCompiledTransform。如何将转换结果作为字符串获取?