【问题标题】:XSLT 2.0, replace function: How to replace matched group with upper case?XSLT 2.0,替换功能:如何用大写替换匹配组?
【发布时间】:2009-01-28 20:39:40
【问题描述】:

如果我的 XSL 文件中有以下元素:

<xsl:value-of select="replace(lower-case(@name), '_([a-z0-9])', '$1')" />

例如,从 'get_polygene_lubricants' 生成 'getpolygenelubricants'。

我想要做的是将'_'之后的第一个字母替换为 字母的大写变体。我用谷歌搜索,阅读文档, 但我无法在 XSLT 中找到任何简单的解决方案 替换。

也许有人知道在 XSLT 2.0 中是否可行?

【问题讨论】:

  • 感谢您阐明问题的要求。我已经更正了我的答案,现在它会产生您期望的结果。请看一下:)
  • 抱歉,SO 中有一个错误。我无法阅读您对我的最新评论。 IE 崩溃了,现在我没有看到评论。请你重复一遍好吗?
  • @Jagger 它被编辑并产生你的结果——只需要一个 XPath 表达式:) 你读过你的回复吗?

标签: regex xslt xpath replace uppercase


【解决方案1】:

已编辑:根据原始海报的说明,由下划线分隔的第一个字符串不应将其首字母大写。

此解决方案不使用递归,应该更高效

这是新的解决方案

string-join(
            (for  $i in 1 to count(tokenize(.,'_')),
                  $s in tokenize(.,'_')[$i],
                  $fl in substring($s,1,1),
                  $tail in substring($s,2)
               return
                  if($i eq 1)
                   then $s
                   else concat(upper-case($fl), $tail)
             ),
                        ''
           )

结果现在完全符合要求:

underLinedString

以下是旧的解决方案

replace() 函数假设你有一个固定的替换 -- 因此它不是解决这个问题的最佳工具。

这是一个单行 XPath 2.0 解决方案(它当然可以用作 XSLT 2.0 转换的一部分 :)     ):

string-join(
            (for $s in tokenize(.,'_'),
                 $fl in substring($s,1,1),
                 $tail in substring($s,2)
               return
                 concat(upper-case($fl), $tail)
             ),
            ''
           )

当我们在这样的 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:template match="/">
     <xsl:sequence select=
      "string-join(
                   (for $s in tokenize(.,'_'),
                    $fl in substring($s,1,1),
                    $tail in substring($s,2)
                  return
                concat(upper-case($fl), $tail)
                   ),
                   ''
                  )

      "/>
    </xsl:template>
</xsl:stylesheet>

并将其应用于此 XML 文档:

<t>under_lined_String</t>

产生想要的结果

UnderLinedString

【讨论】:

  • 感谢您的示例。我不知道 XPath 2.0,但从现在开始我肯定会学到一些东西。但是,您的解决方案并不完全是我想要的,因为结果字符串中的第一个字母必须是小写的。
  • @Jagger 它被编辑并产生你的结果——只需一个 XPath 表达式:)
  • @Dimitre 是的,它看起来很整洁。我切换到你的解决方案。非常感谢。
【解决方案2】:

您可以使用模板执行此操作,递归调用自身以遍历字符串中的字符。这个模板应该有一个位置参数,从 1 开始 并为每次调用模板而增加。当找到 '_' 时,使用 translate(1.0) 或 upper-case(2.0) 将下一个字符转换为大写

【讨论】:

  • 我用 21 行 xml 而不是 1 行创建了这样一个怪物。但重要的是它可以工作。 :) 感谢您的提示。
  • 是的,它不是很精致,我同意这一点。我倾向于从一些常见的 XSLT 文件中包含这些 hack,所以我不必看到它们。
  • 使用 XPath 2.0 / XSLT 2.0 有一个更直接的解决方案,它不需要递归。所以,可能它也更有效。查看我的解决方案。
【解决方案3】:

虽然已经回答,但这是我的解决方案:

<xsl:template name="camel-case">
  <xsl:param name='value'/>
  <xsl:analyze-string regex="^(.)" select="$value">
    <xsl:matching-substring><xsl:value-of select="upper-case(regex-group(1))"/></xsl:matching-substring>
    <xsl:non-matching-substring>
      <xsl:analyze-string regex="[_-](.)" select=".">
        <xsl:matching-substring><xsl:value-of select="upper-case(regex-group(1))"/></xsl:matching-substring>
        <xsl:non-matching-substring><xsl:value-of select="."/></xsl:non-matching-substring>
      </xsl:analyze-string>
    </xsl:non-matching-substring>          
  </xsl:analyze-string>
</xsl:template>

用途:

<xsl:call-template name="camel-case">
  <xsl:with-param name='value' select="."/>
</xsl:call-template>

【讨论】:

    猜你喜欢
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 1970-01-01
    • 2021-11-09
    • 2018-04-07
    • 2020-09-01
    • 1970-01-01
    相关资源
    最近更新 更多