格式化字符串(删除前导零)

Posted

技术标签:

【中文标题】格式化字符串(删除前导零)【英文标题】: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(见下面的答案)。 【参考方案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

以上是关于格式化字符串(删除前导零)的主要内容,如果未能解决你的问题,请参考以下文章

如何删除字符串中的前导零和尾随零? Python

如何在 Pandas 中为字符串添加前导零格式?

格式字符串,带前导零的整数

如何用前导零格式化资源字符串? [复制]

删除 perl 字符串中所有前导零的最优雅和最快的方法

如何使用 C# 删除前导零