【问题标题】:Formatting string (Removing leading zeros)格式化字符串(删除前导零)
【发布时间】:2012-02-06 17:56:22
【问题描述】:

我是 xslt 的新手。我的要求是根据业务规范将 xml 文件转换为文本文件。我面临一个字符串格式问题的问题。如果您有任何想法,请帮助我。

这是输入xml数据的一部分: “0001295”

打印到文本文件的预期结果: 第1295章

我的主要问题是删除前导零。如果您有任何逻辑/功能,请分享。

【问题讨论】:

  • 我有类似的问题,一个包含两个或多个数字的字符串(例如hello 002 and 021, bye),我们无法用一个简单的 "left trim" 函数来解决。 .但是有一个XSLT1的解决方案,因为我们可以使用registered functions(见下面的答案)。

标签: xslt xslt-1.0


【解决方案1】:

有几种方法可以做到这一点。如果该值完全是数字(例如不是 CSV 行或产品代码的一部分,例如 ASN0012345),您可以从字符串转换为数字并再次转换回字符串:

string(number($value)).

否则只需替换开头的 0:

replace( $value, '^0*', '' )

'^' 是必需的(标准正则表达式语法),否则值 001201 将替换为 121(删除所有零)。

希望对您有所帮助。 戴夫

【讨论】:

  • 嗨,戴夫,首先感谢您的意见。基本上我对删除字母数字字符串中的前导零很感兴趣。所以我使用了你的第二个解决方案 replace( $value, '^0*', '' )。当我使用它时,会显示以下错误。 'replace' 不是有效的 XSLT 或 XPath 函数。 -->替换($Part, '^0*', '')
  • 嗯,对,替换是 XSLT 2.0 使用 translate 代替它应该可以正常工作: translate( $value, '^0*', '' )
  • OPS,错误:translate 函数不处理正则表达式 (!)。请参阅@TimC anwser。使用 XSLT1 使用正则表达式和其他良好功能(如 trim)的唯一方法是启用调用者语言(例如 PHP 调用 XSLT),请参阅 ex。 this Wikibook of PHP Programming/XSL/registerPHPFunctions.
【解决方案2】:

您可以使用将删除前导零的递归模板:

<xsl:template name="remove-leading-zeros">
    <xsl:param name="text"/>
    <xsl:choose>
        <xsl:when test="starts-with($text,'0')">
            <xsl:call-template name="remove-leading-zeros">
                <xsl:with-param name="text"
                    select="substring-after($text,'0')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

像这样调用它:

 <xsl:call-template name="remove-leading-zeros">
        <xsl:with-param name="text" select="/path/to/node/with/leading/zeros"/>
    </xsl:call-template>
</xsl:template>

【讨论】:

    【解决方案3】:

    这是您可以在 XSLT 1.0 中实现的一种方法。

    首先,通过删除当前值中的所有零元素,找到第一个非零元素

    <xsl:variable name="first" select="substring(translate(., '0', ''), 1, 1)" />
    

    然后,你可以找到这个第一个字符之前的substring-,然后使用substring-after得到这个之后的非零部分

    <xsl:value-of select="substring-after(., substring-before(., $first))" />
    

    或者,将两个语句合二为一

    <xsl:value-of select="substring-after(., substring-before(., substring(translate(., '0', ''), 1, 1)))" />
    

    所以,给定以下输入

    <a>00012095Kb</a>
    

    然后使用下面的 XSLT

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:template match="/a">
          <xsl:value-of select="substring-after(., substring-before(., substring(translate(., '0', ''), 1, 1)))" />
       </xsl:template>
    </xsl:stylesheet>
    

    会输出以下内容

    12095Kb
    

    【讨论】:

      【解决方案4】:

      只需使用这个简单的表达方式

      number(.)
      

      这是一个完整的例子

      <xsl:stylesheet version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:output method="text"/>
      
       <xsl:template match="t">
            <xsl:value-of select="number(.)"/>
       </xsl:template>
      </xsl:stylesheet>
      

      应用于此 XML 文档时

      <t>0001295</t>
      

      产生想要的正确结果

      1295
      

      二。使用format-number()

      format-number(., '#')
      

      【讨论】:

        【解决方案5】:

        作为 XSLT 2.0 中可用于数字或字母数字输入(带或不带前导零)的简单替代方案,您可以尝试:

        replace( $value, '^0*(..*)', '$1' )
        

        这是因为^0* 是贪婪的,而(..*) 捕获最后一个前导零之后的其余输入。 $1 指的是捕获的组。

        请注意,仅包含零的输入将输出0

        【讨论】:

        • 这个问题被标记为xslt-1.0
        【解决方案6】:

        所有 XSLT1 解析器,如流行的 libXML2's module for XSLT,都有 registered functions facility... 所以,我们可以假设使用它。假设调用 XSLT 的语言是 PHP:参见 this wikibook about registerPHPFunctions


        内置PHP函数ltrim可用于

          <?xml version="1.0" encoding="UTF-8"?>
          <xsl:stylesheet version="1.0" 
               xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
               xmlns:fn="http://php.net/xsl">
           <xsl:output method="xml" encoding="utf-8" indent="yes"/>
           <xsl:template match="test">
               show <xsl:value-of select="fn:function('ltrim',string(.),'0')" />",
           </xsl:template>
          </xsl:stylesheet>
        

        现在想象一个更复杂的问题,ltrim 一个多于 1 个数字的字符串,例如。 hello 002 and 021, bye.

        解决方法是一样的:使用registerPHPFunctions,只是把内置函数改成用户定义的,

        function ltrim0_Multi($s) {
            return preg_replace('/(^0+|(?<= )0+)(?=[1-9])/','',$s);
        } 
        

        将示例转换为hello 2 and 21, bye

        【讨论】:

        • 谢谢@JaarSingleton。是的,registerPHPFunctions 仅用于解决复杂问题...主要问题是被放弃的标准 XSLT v1(没有具有分组功能的中间 1.1、1.2)和no-free DOM parser of XSLT v2
        【解决方案7】:
        <xsl:value-of select="number(.) * 1"/>
        

        为我工作

        【讨论】:

          【解决方案8】:

          XSLT 2.0 从 STRING 中删除前导零

          <xsl:value-of select="replace( $value, '^0+', '')"/>
          

          【讨论】:

          • 这个问题被标记为xslt-1.0
          猜你喜欢
          • 2011-04-09
          • 1970-01-01
          • 1970-01-01
          • 2014-08-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-02
          相关资源
          最近更新 更多