Marked as: Easy
Hi,
It's sometimes necessary to count occurrences of a string within another string, and here's a little code I've written to do that.
COUNTSTR: PROCEDURE /* needle, haystack< <, startpos>, endpos> */
IF ARG() < 2 THEN RETURN -1
IF DATATYPE( ARG(3), 'W' ) THEN
next = ARG(3)
ELSE
next = 1
needle = ARG(1)
haystack = ARG(2)
IF DATATYPE( ARG(4), 'W' ) THEN
haystack = SUBSTR( haystack, next, ABS( ARG(4) - next ) )
next = 1
count = 0
DO WHILE next > 0
next = POS( needle, haystack, next )
IF next > 0 THEN DO
next = next + LENGTH( needle )
count = count + 1
END
END
RETURN count
If you try to use html pages or some other xml-like file format, it's very useful if you can specify the section you want to extract and not deal with things around, the function COUNTSTR above then come in handy to take care of some of the work.
xml_balanced_tags_parse: procedure /* xml-code, tag<, setting> */
next = pos( '<'||translate( ARG(2)||ARG(3) ), translate( ARG(1) ) )
if next = 0 then Return ARG(1)
next = next + length( ARG(2)||ARG(3) ) + 2
open_tag = next
close_tag = pos( '</'||translate( ARG(2) ), translate( ARG(1) ), next )
count = COUNTSTR( '<'||translate( ARG(2) ), translate( ARG(1) ), next, close_tag )
do i = 1 to count
next = close_tag + length( ARG(2) ) + 3
close_tag = pos( '</'||translate( ARG(2) ), translate( ARG(1) ), next )
count = count + COUNTSTR( '<'||translate( ARG(2) ), translate( ARG(1) ), next, close_tag )
end
if close_tag = 0 then end_tag = length( ARG(1) )
else end_tag = close_tag - open_tag
Return substr( ARG(1), open_tag, max( 1, end_tag ) )
Example: retval = xml_balanced_tags_parse( xmlfile, 'div', ' style="color: blue;"' )
Please note that you have to specify the settings very accurately or it will ignore it and not find anything, that is, if something else may be present between "h1" and "style=..." in the example it will return nothing. It is possible to make it more relaxed/forgiving, but that is an exercise that I leave to you for the moment.
//Jan-Erik