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

15

我是xslt的新手,我的要求是根据业务规范将xml文件转换为文本文件。我在处理一个字符串格式问题时遇到了问题。如果您有任何想法,请帮忙解决。

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

期望的结果打印到文本文件中: 1295

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


我有类似的问题,即一个包含两个或多个数字的字符串(例如 hello 002 and 021, bye),我们无法通过简单的“左修剪”函数来解决...但是,由于我们可以使用注册函数(请参见下面的答案),因此我们可以通过 XSLT1 解决这个问题。 - Peter Krauss
8个回答

28

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

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

II. 使用format-number()

format-number(., '#')

9

有几种方法可以实现这个功能。如果该值完全是数字(例如不是CSV行或产品代码的一部分,如ASN0012345),则可以将其从字符串转换为数字,然后再将其转换回字符串:

string(number($value)).

否则,只需将开头的0替换为:
replace( $value, '^0*', '' )

“^”符号是必须的(标准正则表达式语法),否则001201这个值将被替换为121(所有的零都会被删除)。
希望这有所帮助。 Dave

你好,Dave, 首先感谢您的输入。基本上我想去掉字母数字字符串中的前导零。所以我使用了您的第二个解决方案replace($value,'^0*','')。但是当我使用它时,会出现以下错误。“replace”不是有效的XSLT或XPath函数。-->replace($Part,'^0*','')<-- 你有什么解决方法吗?供您参考,我正在使用xml版本1.0。 - Hari
2
啊,对了,replace是XSLT 2.0的函数。使用translate替代它,应该可以正常工作: translate($value, '^0*', '') - detheridge02
OPS,错误:translate函数无法处理正则表达式!请参见@TimC的回答。在XSLT1中使用正则表达式和其他好用的函数(例如trim)的唯一方法是启用调用语言的使用(例如PHP调用XSLT),请参见此PHP编程/XSL注册PHP函数的Wikibook - Peter Krauss

7

以下是在XSLT 1.0中实现的一种方法。

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

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

然后,您可以找到第一个字符之前的子字符串,然后使用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

3

XSLT 2.0 从字符串中去除前导零

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

2
这个问题被标记为 xslt-1.0 - michael.hor257k

3
作为 XSLT 2.0 中的简单替代方案,可用于数字或字母数字输入,带或不带前导零,您可以尝试使用以下代码:
replace( $value, '^0*(..*)', '$1' )

这个可以工作的原因是^0*是贪婪的,(..*)捕获最后一个前导零之后的所有输入。$1指的是捕获的组。
请注意,仅包含零的输入将输出0

1
这个问题被标记为 xslt-1.0 - Sorack

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>

1
<xsl:value-of select="number(.) * 1"/>

适用于我。


0
所有的XSLT1解析器,例如流行的libXML2的XSLT模块,都有已注册函数的功能... 因此,我们可以假设使用它。还假设调用XSLT的语言是PHP:请参见这本关于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>

现在想象一个稍微复杂一点的问题,即要去掉一个包含多个数字的字符串的左侧空格,例如: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="replace($string, '^0+', '')"/> - Mikro Koder
感谢@JaarSingleton。是的,只有在解决复杂问题时才使用registerPHPFunctions。主要问题是标准的XSLT v1已被放弃(没有中介1.1、1.2与分组功能),以及XSLT V2的非免费DOM解析器。 - Peter Krauss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接