CFCase values with spaces are not found

173 views Asked by At

As anyone had this issue with parsing from html file with setting <cfcase> values that contain spaces in the value? If the value contains spaces ColdFusion isn't able to find the data match in the parsed html file.

For example:

<CFCASE value="LGT RAIN">
<CFSET application.condition="Lt Rain">
</CFCASE>`

The html file has the value "LGT RAIN", but due to the way its being parsed it is not defining the city's condition. Is there a work around like check the condition prior to running your switch statements? Like if "LGT RAIN" is found then set cfset value it to "LGTRAIN".

Here is sample link that I am parsing from.

https://forecast.weather.gov/product.php?site=CAE&issuedby=CAE&product=RWR&format=CI&version=1

<CFSET WeatherData = CFHTTP.FileContent>

Code:

<!--- Check For Condition with Two Word Phrase ---------------> 
<CFSET condition= #GetToken("#content#",#attributes.citystring# + 1, " ")#>
<br> 
<CFSET city = #attributes.citystring#> 
<CFIF (condition is "LGT") 
   or (condition is "HVY") 
   or (condition is "FRZ") 
   or (condition is "MIX") 
   or (condition is "NOT")> 
  <CFSET condition= ( 
    #GetToken("#content#",#attributes.citystring# + 1, " ")# 
    & " " & 
    #GetToken("#content#",#attributes.citystring# + 2, " ")#
  )>
  <br>
  <CFSET Temp = #GetToken("#content#",#attributes.citystring# + 3, " ")#>'
  .......
2

There are 2 answers

0
Dan Bracuk On

My experience with white space in text data messing up conditional logic has been with trailing spaces but the principles are the same. When in doubt look at your data. Here is a simple example:

MyVar = 'Lgt  Rain';  // two spaces between the words
if (MyVar == 'Lgt Rain'){ // one space between words
applicable code
}
else {
writeoutput(replace(MyVar, ' ', '-space-', 'all'));
}
2
Shawn On

There is a lot of missing context on what you're trying to ultimately do with the weather you get, so I made a couple of assumptions on ways to parse through the weather block.

You'll have to actually parse the page to get that actual block, but once you do, you can use my suggestions below to split those weather elements out. I got rid of the getToken() calls, because I think that may have been more work than you needed, and was essentially led to the problem with spaces. My code is still much wordier than I intended, but I tried to make sure I wasn't using anything above CF8. I think it should all work, but I don't have a CF8 server to test on.

https://trycf.com/gist/1993243eb476a629ec25f8c6e8ddff3c/acf?theme=monokai

I've included some notes inside the code as I went along.

<!--- Create a block of the parsed weather. --->
<cfsavecontent variable="myWX">ANDERSON       FAIR      49  16  26 W12G20    30.01F
LIBERTY        FAIR      49  14  24 W12G21    29.99F
SPARTANBURG    FAIR      45   9  23 NW12G21   30.00F
CLEMSON        FAIR      48  10  21 NW13G22   30.02F
GREENVILLE     FAIR      48  13  24 VRB3      29.99F
GREENWOOD      FAIR      49  13  23 W10G21    30.03F
GREER          FAIR      48   9  20 VRB7      29.99F
ROCK HILL      FAIR      46  17  31 NW10G22   29.99F
CHESTER        FAIR      45  12  26 W12G17    30.01F
LAURENS        FAIR      48  16  27 NW12G18   30.01F
</cfsavecontent>

 <!--- end of line character (this may change if your feed uses other eol)--->
<cfset crlf = chr(13)&chr(10)>

<!--- Make weather an array of strings for each city. --->
<cfset wxArray = ListToArray(myWX, crlf, false, true)> 

My suggestion is to put the different elements in a struct, then work with that. 1 row of city weather = 1 row of Struct.

My code below assumes you are parsing rows of a 65 character fixed-width record from the HTML, which is what it appears to be when you get at the individual rows.

<!--- Loop through the new weather array and make a new array of parsed weather. --->
<!--- Create initial weather array for output. --->
<cfset newWXArray = []> 
<cfloop array="#wxArray#" index="wxRow">
    <!--- NOTE: Yay go CF8s implicit struct creation! --->
    <cfset WXRow = {
        city = trim(mid(wxRow,1,15)) , <!--- trim() will remove leading/trailing spaces --->
        sky  = trim(mid(wxRow,16,10)) ,
        tmp  = trim(mid(wxRow,26,4)) ,
        dp   = trim(mid(wxRow,30,4)) ,
        rh   = trim(mid(wxRow,34,3)) ,
        wind = trim(mid(wxRow,37,10)) ,
        pres = trim(mid(wxRow,47,6)) , 
        rmks = trim(mid(wxRow,53,11))
    }>
    <!--- ArrayAppend() returns true/false, so this variable isn't used. --->
    <cfset throwaway = ArrayAppend(newWXArray, WXRow)>
</cfloop>

<cfdump var="#newWXArray#">

Now you have an array of all the cities, and can pull the individual pieces out for the city you need.

What's the weather like in Liberty? <br>

<cfset whichRow = 0> 
<cfloop from="1" to="#arrayLen(newWXArray)#" index="i"> 
    <cfif newWXArray[i].CITY IS "LIBERTY"> 
        <cfset whichRow = i> 
    </cfif> 
</cfloop> 

<cfoutput>
City >> #newWXArray[whichRow].CITY# <br>
Sky >> #newWXArray[whichRow].SKY# <br>
Temp >> #newWXArray[whichRow].TMP# <br>
DewPoint >> #newWXArray[whichRow].DP# <br>
Relative Humidity >> #newWXArray[whichRow].RH# <br>
Wind >> #newWXArray[whichRow].WIND# <br>
Pressure >> #newWXArray[whichRow].PRES# <br>
Remarks >> #newWXArray[whichRow].RMKS# <br>
</cfoutput>

Final Note:

I had forgotten how limited CF8 was. There is a lot of stuff you can do to make this MUCH easier if you are able to upgrade to a current version of ACF or Lucee.

Also, as I suggested, changing your link to pull the Text-Only version (https://forecast.weather.gov/product.php?site=CAE&issuedby=CAE&product=RWR&format=txt&version=1&glossary=1) will significantly reduce the amount of text you have to parse through.