Trying not to use Regular Expression...
lazarus / 21-General
----------------------------------------------------------------------
Gustavo 'Gus' Carreno · 2021-09-17 15:22
Hey Y'all,
Let's say I have this string:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i var line:
String;begin line:= '
| Smileys
& Emotion |
';end;
QuoteNote:
Yes, I know, the author of the HTML opted for single quotes, not
double quotes, the biatch!!
So inconsiderate to us Pascal peeps!
As the maxim goes: I have an HTML parsing problem and I want to solve
it with RegExps... Now you have 2 problems!!
So I want to extract the text Smileys & Emotion that sits between
the .. tag.
How would I go about it without using Regular Expressions?
The best I can come up with is:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i var left,
right: Integer; line, extract: String;begin line:= '| Smileys & Emotion |
';
left:= Pos('''>'); Delete(line, 1, left+2); // Deletes the TH left:=
Pos('''>'); Delete(line, 1, left+2); // Deletes the A right:=
Pos('', line); extract:= Copy(line, 1, right);end;
But this is messy and I'm prone to mess up those indexes and counts on
both the Delete and Copy.
Can anyone suggest a better way than mine but with the caveat that we
don't use RegExps?
Is there another pattern matching thingamaboob that can manage this,
hidden inside an obscure String manipulation unit that I'm unaware of?
Many, MANY thanks in advance!!
Cheers,
Gus
----------------------------------------------------------------------
winni · 2021-09-17 15:40
Hi!
very simple code without error checking:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i var p,q :
Integer;sl : TStringList;beginsl := TStringList.create;repeatp :=
pos('<',line);if p > 0 then begin delete(line,1,p); q := pos
('>',line); if q > 0 then sl.add (copy (line,1,q-1));end;until (p=0)
or (q=0);ShowMessage (sl.text);sl.free;
Winni
----------------------------------------------------------------------
winni · 2021-09-17 16:15
Hi!
Ooops - that was the wrong answer.
You want the text between the tags.
Here we go:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i procedure
TForm1.Button3Click(Sender: TObject);var line : String; sl:
TStringList; p,q,r : integer;begin line:= '| Smileys & Emotion |
';
sl := TStringList.create; repeat p := pos (' 0
then begin delete (line,1,p+1); q := pos
('>',line); if q > 0 then begin delete
(line,1,q); r := pos ('',line); if r > 0 then
sl.add (copy (line,1,r-1)); end; // q end; // p
until (p=0) or (q=0); showMessage (sl.text); end;
Winni
----------------------------------------------------------------------
Gustavo 'Gus' Carreno · 2021-09-17 16:17
Hey Winni,
Quote from: winni on September 17, 2021, 05:40:27 pmHi!
very simple code without error checking:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i var p,q :
Integer;sl : TStringList;beginsl := TStringList.create;repeatp :=
pos('<',line);if p > 0 then begin delete(line,1,p); q := pos
('>',line); if q > 0 then sl.add (copy (line,1,q-1));end;until (p=0)
or (q=0);ShowMessage (sl.text);sl.free;
Winni
From just looking at the code, I'm guessing that this will return tr,
which is the first tag.
I guess I can use a modified approach to eliminate all the tags and be
left with only the string I'm looking for.
Not a complete solution but it does point me to another solution I
haven't thought of. For that alone, MANY thanks Winni!!!
Cheers,
Gus
----------------------------------------------------------------------
Gustavo 'Gus' Carreno · 2021-09-17 16:22
Hey Winni,
Quote from: winni on September 17, 2021, 06:15:23 pmHi!
Ooops - that was the wrong answer.
You want the text between the tags.
Here we go:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i procedure
TForm1.Button3Click(Sender: TObject);var line : String; sl:
TStringList; p,q,r : integer;begin line:= '| Smileys & Emotion |
';
sl := TStringList.create; repeat p := pos (' 0
then begin delete (line,1,p+1); q := pos
('>',line); if q > 0 then begin delete
(line,1,q); r := pos ('',line); if r > 0 then
sl.add (copy (line,1,r-1)); end; // q end; // p
until (p=0) or (q=0); showMessage (sl.text); end;
Winni
Yup, this makes a bit more sense, THANKS!!!
I'll have a better look at this and generalize it for the other 3
lines I have to parse.
And I'll also wait for more people to chime in with some other
approach. I like variety
Cheers,
Gus
----------------------------------------------------------------------
wp · 2021-09-17 16:40
My standard solution in such cases is the fasthtmlparser of FCL.
Search the forum, I presented worked-out solutions here several times
already. The basic idea is that this parser runs through the text and
fires an event OnFoundTag for every tag (part between '<' and '>') and
OnFoundText for every text (part between '>' and '<'). Super easy to
extract text or table content, but maybe a bit overkill for such a
short text phrase as requested here...
----------------------------------------------------------------------
Gustavo 'Gus' Carreno · 2021-09-17 16:57
Hey WP,
Quote from: wp on September 17, 2021, 06:40:35 pmMy standard solution
in such cases is the fasthtmlparser of FCL. Search the forum, I
presented worked-out solutions here several times already. The basic
idea is that this parser runs through the text and fires an event
OnFoundTag for every tag (part between '<' and '>') and OnFoundText
for every text (part between '>' and '<'). Super easy to extract text
or table content, but maybe a bit overkill for such a short text
phrase as requested here...
Ooooooohhhhh, I'm always in the looks for a fine HTML parser lib. I
don't think I've stumbled on this one!!!
Thanks WP, I'll have a search for your posts!!!
And yeah, a bit overkill since one file is ~6MB and the other file is
~33MB. Having events fired for each tag and text, OUCH
These are the Emoji lists that I mentioned in another post.
I'm trying to extract info from them and I'm gonna put them in a JSON
container, maybe...
Still need to suss out how I'm gonna include such big datasets in my
EmojiMap application.
Will need to see how phat is the JSON that I'll extract and if not
that big, maybe just add it as a Resource.
Nonetheless, many thanks for another approach!!
C'mon my fellow Pascalites, keep'em coming
Cheers,
Gus
----------------------------------------------------------------------
BobDog · 2021-09-17 22:45
A no frills way:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i Type
intArray = Array of int32; AOS=array of ansistring; // =========
number of partstring in somestring and fill array
=============// function tally(somestring:pchar;partstring:pchar;var
arr: intarray ):integer;vari,j,ln,lnp,count,num:integer
;filler:boolean;labelskip ,start,return;beginsetlength(arr,0); ln:=len
gth(somestring);lnp:=length(partstring);filler:=false;start:count:=0;i
:=-1;repeati:=i+1; if somestring[i] <> partstring[0] then goto skip
; if somestring[i] = partstring[0] then begin for j:=0 to
lnp-1 do begin if somestring[j+i]<>partstring[j] then goto
skip; end; count:=count+1; if filler = true then
arr[count]:=i+1 ; i:=i+lnp-1; end ; skip: until i>=ln-1
;SetLength(arr,count); // size is now known, repeat the operation to
fil arrarr[0]:=count; // save tally in [0]num:=count;if
filler=true then goto return;filler:=true; goto start; return:
result:=num;end; procedure
getstrings(a:ansistring;chars1:ansistring;chars2:ansistring;var
ans:AOS);varf,s:intarray;i,j,count:int32;labellbl;begincount:=0;if
(tally(pchar(a),pchar(chars1),f)=0) then exit;if
(tally(pchar(a),pchar(chars2),s)=0) then exit; for i:=1 to f[0] do
begin for j:=1 to s[0] do begin if ((i>f[0]) or (j>s[0])) then goto
lbl; if i=j then begin count:=count+1; setlength(ans,count);
ans[count-1]:= (a[f[i]+length(chars1) .. s[j]-length(chars2)+1]);
end; end; end; lbl:end; vara:ansistring;ans:AOS;i:int32; begin a:=
'starters qwerty tree
tail end ';a:=a+'
'
; getstrings(a,'',ans); for i:=low(ans) to high(ans) do
writeln(ans[i]); readln; end. end.
----------------------------------------------------------------------
Gustavo 'Gus' Carreno · 2021-09-17 22:50
Hey BobDog,
Quote from: BobDog on September 18, 2021, 12:45:52 amA no frills way:
WOW, that's a big hunk'a code to digest, LOL!!
Let me have some time to have a good look at it
Many thanks for the contribution, nonetheless!!!
I'm quite grateful that I have so many options to choose from!!!
Cheers,
Gus
----------------------------------------------------------------------
Jurassic Pork · 2021-09-18 00:32
hello,
you can also use the units sax_html, dom_html from fpc.
Here is an example to use them ( from a Leledumbo's source code) :
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i Program
ParseHtml;uses classes,sax_html,dom_html,dom;const testdata =
'| ' + 'Smileys
& Emotion' + ' |
';var doc: thtmldocument; els:
tdomnodelist; elm: tdomelement;begin
readhtmlfile(doc,tstringstream.create(testdata)); els :=
doc.GetElementsByTagName('a'); // display first tag found if
els.Count > 0 then writeln(tdomelement(els[0]).textcontent);
readln;end.
Friendly, J.P
----------------------------------------------------------------------
Gustavo 'Gus' Carreno · 2021-09-18 01:29
Hey J.P.,
Quote from: Jurassic Pork on September 18, 2021, 02:32:46 amyou can
also use the units sax_html, dom_html from fpc.
Many thanks for another HTML parser suggestion!!
I'll have a look at this one also!!
But for the sizes that I'm looking at: ~6MB and ~33MB, having the
whole DOM in mem is a bit too much
Nonetheless I welcome another parser to my list. Like I said, I'm
always looking for these gems!!
Cheers,
Gus