Steen
Steen

Reputation: 2877

in xslt 1.0 if value contains number inside string value

I have a complex adress string, or rather different possible formats, which I need to split into road name, house number, floor, position (left,right,middel door) or door/room number

I have managed to do all apart from the last bit, with the pseudo "contains":

<xsl:choose>
                <xsl:when test="contains(@addressFarLeft, ANY_NUMERIC_VALUE_ANYWHERE)">
                  <door>NUMERICVALUE</door>
                </xsl:when>
                <xsl:otherwise></xsl:otherwise>
              </xsl:choose>

Im pretty sure I cant just use some form of contains, but what then?

Value is set dynamically, but here are a few possible values:

<xsl:variable name="addressFarLeftValue">.th.</xsl:variable> =>
no numeric value, do nothing

<xsl:variable name="addressFarLeftValue">.1.</xsl:variable> =>
   produce:  <door>1</door>

<xsl:variable name="addressFarLeftValue">, . tv </xsl:variable> =>
no numeric value, do nothing

<xsl:variable name="addressFarLeftValue">,th, 4.</xsl:variable> =>
   produce:   <door>1</door>

Any suggestions?

Upvotes: 1

Views: 5970

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243459

The wanted numeric value can be obtained using the "double-translate" method, first shown by Michael Kay:

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

 <xsl:variable name="addressFarLeftValue1" select="',th, 4.'"/> 
 <xsl:variable name="addressFarLeftValue2" select="', . tv'"/>  


 <xsl:variable name="vDoorNumber1" select=
  "translate($addressFarLeftValue1,
             translate($addressFarLeftValue1, '0123456789', ''),
             '')"/>
 <xsl:variable name="vDoorNumber2" select=
  "translate($addressFarLeftValue2,
             translate($addressFarLeftValue2, '0123456789', ''),
             '')"/>

 <xsl:template match="/">
     "<xsl:value-of select="$vDoorNumber2"/>"
==========
   "<xsl:value-of select="$vDoorNumber1"/>"
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied to any XML document (not used), the wanted, correct result is produced:

     ""
==========
   "4"

Upvotes: 4

Tim C
Tim C

Reputation: 70598

If you want to test whether a string contains a numeric value, one approach could be to use the 'translate' function to remove all numeric digits from the string, and if the resultant string doesn't match the initial string, you know it must have contained a number. If the string doesn't change, then it didn't.

<xsl:choose>
  <xsl:when test="translate($addressFarLeft, '1234567890', '') != $addressFarLeft">
    <door>1</door>
  </xsl:when>
  <xsl:otherwise/>

So, <xsl:variable name="addressFarLeftValue">.1.</xsl:variable> outputs <door>1</door>, but <xsl:variable name="addressFarLeftValue">.th.</xsl:variable> doesn't output anything.

IF you wanted to extract the actual number, then assuming there was only one occurence of a number in the string, you could do this...

<xsl:value-of 
   select="translate(
      @addressFarLeft, 
      translate(@addressFarLeft, '1234567890', ''), 
      '')" />

So, <xsl:variable name="addressFarLeftValue">,th, 42.</xsl:variable> outputs 42

If you had multiple numbers present, such as ,th, 42, ab, 1 this approach would fail though.

Upvotes: 5

Related Questions