开发者

Initial number part or integer portion of a string in xsl

By using xsl template, can any one tell me the way to get first number portion of a string field

For examp开发者_开发技巧le:

'12'        -> should result in -> 12
'5 ASDF'    -> should result in -> 5
'34SDF56'   -> should result in -> 34


Here is a one-liner XPath solution: :)

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="text()">
  <xsl:variable name="vS" select="concat(.,'Z')"/>
  <xsl:value-of select=
   "substring-before(translate($vS,translate($vS,'0123456789',''),'Z'),'Z')"/>
   <xsl:text>&#xA;</xsl:text>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the following XML document:

<t>
 <x>12</x>
 <x>5 ASDF</x>
 <x>34SDF56</x>
</t>

the wanted, correct results are produced:

12
5
34


you could give this a go? should work supposing that you know the maximum length of numbers!

so here you could find a number upto 6 digits long! hope it helps

      <xsl:variable name="YourString" select="YourStringPath"/>
      <xsl:choose>
            <xsl:when test="substring($YourString,1,6) &gt; 0">
                  <xsl:value-of select="substring($YourString,1,6)"/>
            </xsl:when>
            <xsl:when test="substring($YourString,1,5) &gt; 0">
                  <xsl:value-of select="substring($YourString,1,5)"/>
            </xsl:when>
            <xsl:when test="substring($YourString,1,4) &gt; 0">
                  <xsl:value-of select="substring($YourString,1,4)"/>
            </xsl:when>
            <xsl:when test="substring($YourString,1,3) &gt; 0">
                  <xsl:value-of select="substring($YourString,1,3)"/>
            </xsl:when>
            <xsl:when test="substring($YourString,1,2) &gt; 0">
                  <xsl:value-of select="substring($YourString,1,2)"/>
            </xsl:when>
            <xsl:when test="substring($YourString,1,1) &gt; 0">
                  <xsl:value-of select="substring($YourString,1,1)"/>
            </xsl:when>
            <xsl:otherwise>default number here?</xsl:otherwise>         
      </xsl:choose>


The following template will emit all numeric digits of a string up to the first non-numeric (without having to know how many digits may be in the number):

   <xsl:template match="@num">
      <xsl:variable name="nonNumbers" select="translate(., '0123456789', '')"/>
      <xsl:attribute name="{name()}">
         <xsl:choose>
            <xsl:when test="$nonNumbers">
               <xsl:value-of select="substring-before(.,
                                        substring($nonNumbers, 1, 1))" />
            </xsl:when>
            <xsl:otherwise>
               <xsl:value-of select="."/>            
            </xsl:otherwise>
         </xsl:choose>
      </xsl:attribute>
   </xsl:template>

(Thanks to @Alejandro for the key idea, using substring() to get the first non-number, and then passing it to substring-before().) Here it is in the context of an identity transform:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="1.0">

   <xsl:template match="@num">
      <xsl:variable name="nonNumbers" select="translate(., '0123456789', '')"/>
      <xsl:attribute name="{name()}">
         <xsl:choose>
            <xsl:when test="$nonNumbers">
               <xsl:value-of select="substring-before(., substring($nonNumbers, 1, 1))" />
            </xsl:when>
            <xsl:otherwise>
               <xsl:value-of select="."/>            
            </xsl:otherwise>
         </xsl:choose>
      </xsl:attribute>
   </xsl:template>

   <!-- Identity transform -->
   <xsl:template match="@* | node()">
      <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

When run on the following input:

<?xml version="1.0" encoding="UTF-8"?>
<values>
   <value num="12"/>
   <value num="5 ASDF"/>
   <value num="34SDF56"/>
</values>

it produces the requested output:

<?xml version="1.0" encoding="utf-8"?>
<values>
   <value num="12"/>
   <value num="5"/>
   <value num="34"/>
</values>

Another way to do the @num template is the following, arguably more elegant but harder to read IMO:

 <xsl:template match="@num[translate(., '0123456789', '') = '']">
    <!-- alternatively, match="@num[number(.) > 0]" -->
    <xsl:copy />
 </xsl:template>
 <xsl:template match="@num">
    <xsl:attribute name="{name()}">
       <xsl:value-of select="substring-before(., substring(
                                 translate(., '0123456789', ''), 1, 1))" />
    </xsl:attribute>
 </xsl:template>

Notes:

  • The first of the two @num templates above takes priority over the second, because the first is more specific, having a predicate. So the first template is used to process @num's that it matches, and the second template processes all other @num's.
  • The first template matches @num's whose value is all digits, and merely copies the attribute. If we didn't make this exception, the second template would output empty string values for such @num's.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜