格式化字符串(删除前导零)
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
。
【讨论】:
<xsl:value-of select="number(.) * 1"/>
为我工作
【讨论】:
【参考方案8】:XSLT 2.0 从 STRING 中删除前导零
<xsl:value-of select="replace( $value, '^0+', '')"/>
【讨论】:
这个问题被标记为xslt-1.0
。以上是关于格式化字符串(删除前导零)的主要内容,如果未能解决你的问题,请参考以下文章