├── demo-delphi
├── HtmParser.dpr
├── Unit1.dfm
├── Unit1.pas
└── HtmParser.dproj
├── README.md
├── htmtool.pas
├── demo-console
└── project1.lpr
├── arrhtmlparser.pas
├── fasthtmlparser.pas
└── htmutils.pas
/demo-delphi/HtmParser.dpr:
--------------------------------------------------------------------------------
1 | program HtmParser;
2 |
3 | uses
4 | Vcl.Forms,
5 | Unit1 in 'Unit1.pas' {Form1};
6 |
7 | {$R *.res}
8 |
9 | begin
10 | Application.Initialize;
11 | Application.MainFormOnTaskbar := True;
12 | Application.CreateForm(TForm1, Form1);
13 | Application.Run;
14 | end.
15 |
--------------------------------------------------------------------------------
/demo-delphi/Unit1.dfm:
--------------------------------------------------------------------------------
1 | object Form1: TForm1
2 | Left = 0
3 | Top = 0
4 | Caption = 'Form1'
5 | ClientHeight = 507
6 | ClientWidth = 714
7 | Color = clBtnFace
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -13
11 | Font.Name = 'Tahoma'
12 | Font.Style = []
13 | OldCreateOrder = False
14 | PixelsPerInch = 120
15 | TextHeight = 16
16 | object Button1: TButton
17 | Left = 486
18 | Top = 446
19 | Width = 189
20 | Height = 25
21 | Caption = 'Get Element By Name'
22 | TabOrder = 0
23 | end
24 | object Memo1: TMemo
25 | Left = 60
26 | Top = 26
27 | Width = 619
28 | Height = 409
29 | Lines.Strings = (
30 | 'Memo1')
31 | TabOrder = 1
32 | end
33 | object bGetElementByID: TButton
34 | Left = 486
35 | Top = 474
36 | Width = 189
37 | Height = 25
38 | Caption = 'Get Element By ID'
39 | TabOrder = 2
40 | OnClick = bGetElementByIDClick
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/demo-delphi/Unit1.pas:
--------------------------------------------------------------------------------
1 | unit Unit1;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
8 | fasthtmlparser;
9 |
10 | type
11 | TForm1 = class(TForm)
12 | Button1: TButton;
13 | Memo1: TMemo;
14 | bGetElementByID: TButton;
15 | procedure bGetElementByIDClick(Sender: TObject);
16 | private
17 | { Private declarations }
18 | public
19 | { Public declarations }
20 | end;
21 |
22 | var
23 | Form1: TForm1;
24 |
25 | implementation
26 |
27 | {$R *.dfm}
28 |
29 | procedure TForm1.bGetElementByIDClick(Sender: TObject);
30 | var
31 | s: string;
32 | Hp: THtmlParser;
33 | InnerHtml, Tag, TagEnd: string;
34 | begin
35 | s := '
some text
text about something
';
36 | Hp := THtmlParser.Create(s);
37 | InnerHtml := Hp.GetElementById('divbox1', Tag, TagEnd);
38 | Memo1.Lines.Add('Element name: divbox1');
39 | Memo1.Lines.Add('Element Inner HTML: ');
40 | Memo1.Lines.Add(InnerHtml);
41 | Memo1.Lines.Add('Tag: ');
42 | Memo1.Lines.Add(Tag);
43 |
44 | Hp.Free; Hp := nil;
45 | end;
46 |
47 | end.
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Fast HTML Parser
2 | HTML Parser for FPC and Delphi originally written by Jazarsoft
3 |
4 | * Modified for use as a pure command line unit (no dialogs) for freepascal.
5 | * Also added UPPERCASE tags so that when you check for i.e. it returns
6 | all tags like < FONT > and < FoNt > and < font >
7 |
8 | ## Versions
9 | Revision 18 is Version 1 of this tool
10 |
11 | After revision 18 version 2 of the tool is being worked on with more object methods to access
12 | elements by Name or ID for example just like a DOM.
13 |
14 | ## Todo
15 | * keep the entire HTML file in an array for later usage: htmltags[] and text[]
16 | * parse like this: OnSection(opentag, text, closetag); as a different parser
17 | kind so that globals are not needed to keep track of InTag booleans, etc.
18 | so that all are together, tag, text, closing tag, in the same procedure
19 | * associate a number (open tag) with the text label using a record or such
20 | i.e. < body > < b >some text< / b >< / body >
21 | where < b > is tag "2" and some text is text "1"
22 | * turn into a DLL using FPC or C so that other languages can use a callback
23 | to parse html fast in that language (i.e. golang, python, etc.)
24 |
25 | Use this parser for what reasons:
26 | * make your own web browsers,
27 | * make your own text copies of web pages for caching purposes
28 | * Grab content from websites -without- using regular expressions
29 | * Seems to be MUCH MUCH FASTER than regular expressions, as it is after all
30 | a true parser
31 | * convert website tables into spreadsheets (parse TD and TR, turn in to
32 | CSV or similar)
33 | * convert websites into txt files
34 | * convert website tables into CSV/Database (parse TD and TR)
35 | * find certain info from a web page.. i.e. all the bold text or hyperlinks in
36 | a page.
37 | * Parse websites remotely from a CGI app using something like Sockets or
38 | Synapse and SynWrap to first get the HTML site. This would allow you to
39 | dynamically parse info from websites and display data on your site in real
40 | time.
41 | * HTML editor.. WYSIWYG or a partial WYSIWYG editor. Ambitious, but possible.
42 | * HTML property editor. Not completely wysiwyg but ability to edit proprties
43 | of tags. Work would need to be done to parse each property in a tag.
44 |
45 |
46 |
--------------------------------------------------------------------------------
/htmtool.pas:
--------------------------------------------------------------------------------
1 | unit htmtool; {$IFDEF FPC}{$MODE OBJFPC}{$H+}{$ENDIF}
2 |
3 | interface
4 |
5 | function IsTag(TagType: string; Tag: string): boolean;
6 | function IsCloseTag(TagType: string; Tag: string): boolean;
7 | function Substr(sub, s: string): boolean;
8 | function StripTabs(s: string): string;
9 | function ReturnsToSpaces(s: string): string;
10 | function LessenSpaces(s: string): string;
11 | function CleanHtm1(s: string): string;
12 |
13 | implementation
14 |
15 | uses
16 | sysutils;
17 | { strips tabs, lessens spaces, converts returns to spaces }
18 |
19 | function CleanHtm1(s: string): string;
20 | begin
21 | result:= s;
22 | result:= stripTabs(result);
23 | result:= ReturnsToSpaces(result);
24 | result:= LessenSpaces(result);
25 | end;
26 |
27 | { strips double spaces into single spaces (recursively) }
28 | function LessenSpaces(s: string): string;
29 | var
30 | found: integer;
31 | begin
32 | result:= '';
33 | result:= s;
34 | found:= 0;
35 | repeat
36 | result:= stringreplace(result, ' ', ' ', [rfReplaceAll]);
37 | found:= pos(' ', result);
38 | until found < 1;
39 | end;
40 |
41 | { strips tabs }
42 | function StripTabs(s: string): string;
43 | const
44 | TABCHAR = #9;
45 | begin
46 | result:= '';
47 | result:= stringreplace(s, TABCHAR, '', [rfReplaceAll]);
48 | end;
49 |
50 | { strips returns but replaces them with spaces }
51 | function ReturnsToSpaces(s: string): string;
52 | const
53 | CR = #13;
54 | LF = #10;
55 | begin
56 | result:= '';
57 | result:= s;
58 | result:= stringreplace(result, CR+LF, ' ', [rfReplaceAll]);
59 | result:= stringreplace(result, CR, ' ', [rfReplaceAll]);
60 | result:= stringreplace(result, LF, ' ', [rfReplaceAll]);
61 | end;
62 |
63 | // same as POS but returns boolean
64 | function Substr(sub, s: string): boolean;
65 | begin
66 | result:= false;
67 | if pos(sub, s) > 0 then result:= true;
68 | end;
69 |
70 | // is a ''
71 | function IsCloseTag(TagType: string; Tag: string): boolean;
72 | begin
73 | result:= false;
74 | if uppercase(Tag) = ''+ uppercase(TagType) +'>' then result:= true;
75 | end;
76 |
77 | // is a '' or '', TagUp) > 0) or
87 | (pos('<' +TypeUp+' ', TagUp) > 0)
88 | then
89 | result:= true;
90 |
91 | end;
92 |
93 | end.
94 |
--------------------------------------------------------------------------------
/demo-console/project1.lpr:
--------------------------------------------------------------------------------
1 | { Demo for fast html parser
2 |
3 | Try arrays }
4 |
5 | program project1;
6 |
7 | {$mode objfpc}{$H+}
8 |
9 | uses
10 | fasthtmlparser, // html parser
11 | arrhtmlparser, // same as fasthtmlparser but stores all tags/text in an array for later use
12 | sysutils;
13 |
14 | const
15 | HTMStringA = 'some text
text in bold tag more text more bold
and the end of html';
16 | var
17 | InBold: boolean = false;
18 |
19 | procedure msg(s: string);
20 | begin writeln(s);
21 | end;
22 |
23 | procedure msg(s1,s2: string);
24 | begin writeln(s1,s2);
25 | end;
26 |
27 | procedure msg(s1: string; i: integer);
28 | begin writeln(s1,i);
29 | end;
30 |
31 |
32 | // TOnFoundTagP = procedure(NoCaseTag, ActualTag: string);
33 | // TOnFoundTextP = procedure(Text: string);
34 |
35 | procedure ExOnTag(NoCaseTag, ActualTag: string);
36 | begin
37 | if NoCaseTag = '' then begin
38 | InBold := true;
39 | msg('bold start');
40 | end;
41 |
42 | if NoCaseTag = ' ' then begin
43 | InBold := false;
44 | msg('bold end');
45 | end;
46 | end;
47 |
48 | procedure ExOnText(Text: string);
49 | begin
50 | if InBold then begin
51 | msg('Text tag: ', Text);
52 | end;
53 | end;
54 |
55 | procedure Example1;
56 | var
57 | hp: THTMLParser;
58 | begin
59 | hp := THTMLParser.create(HTMStringA);
60 | hp.OnFoundTagP := @ExOnTag;
61 | hp.OnFoundTextP := @ExOnText;
62 | hp.Exec;
63 | hp.free; hp := nil;
64 | end;
65 |
66 | procedure Example2;
67 | var
68 | ahp: TArrHTMLParser;
69 | i: integer;
70 | begin
71 | ahp := TArrHTMLParser.create(HTMStringA);
72 | ahp.OnFoundTagP := @ExOnTag;
73 | ahp.OnFoundTextP := @ExOnText;
74 | ahp.Exec;
75 | msg('Printing all tag items:');
76 | msg('Length of Tags array: ',length(ahp.Tags));
77 | // print out all tags in array
78 | for i := low(ahp.Tags) to high(ahp.Tags) do begin
79 | writeln(i,':',ahp.Tags[i]);
80 | end;
81 | msg('Printing all text items:');
82 | msg('Length of Texts array: ', length(ahp.Texts));
83 | // print out all texts in array
84 | for i := low(ahp.Texts) to high(ahp.Texts) do begin
85 | writeln(i,':',ahp.Texts[i]);
86 | end;
87 | ahp.free; ahp := nil;
88 | end;
89 |
90 | procedure Line;
91 | begin writeln('-----------------------------------------------');
92 | end;
93 |
94 | begin
95 | Example1;
96 | Line;
97 | Example2;
98 | Line;
99 | ReadLn; // pause program on exit for to quit
100 | end.
101 |
102 |
--------------------------------------------------------------------------------
/arrhtmlparser.pas:
--------------------------------------------------------------------------------
1 | {%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 | Array Html Parser
3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4 |
5 | Original AUTHOR : James Azarja, http://www.jazarsoft.com/
6 |
7 | CONTRIBUTORS : L505, http://z505.com
8 |
9 | NOTES: Same as FastHTMLParser but uses array to keep track of text and tags
10 |
11 | OTHER IDEAS:
12 | * associate start opening tag with text.. i.e. sometext
13 | where b is tag no. 2 associated to sometext is text no. 1
14 |
15 | LEGAL : Copyright (C) 2004 Jazarsoft, All Rights Reserved.
16 | Modified 2005 Lars (L505)
17 | --------------------------------------------------------------------------------
18 | LICENSE/TERMS
19 | --------------------------------------------------------------------------------
20 |
21 | This code may be used and modified by anyone so long as this header and
22 | copyright information remains intact.
23 |
24 | The code is provided "AS-IS" and without WARRANTY OF ANY KIND,
25 | expressed, implied or otherwise, including and without limitation, any
26 | warranty of merchantability or fitness for a particular purpose.
27 |
28 | In no event shall the author be liable for any special, incidental,
29 | indirect or consequential damages whatsoever (including, without
30 | limitation, damages for loss of profits, business interruption, loss
31 | of information, or any other loss), whether or not advised of the
32 | possibility of damage, and on any theory of liability, arising out of
33 | or in connection with the use or inability to use this software.
34 | }
35 |
36 | {$IFDEF FPC}{$MODE DELPHI}{$H+}{$ENDIF}
37 |
38 | // {$DEFINE DEBUGLN_ON}
39 |
40 | unit arrhtmlparser;
41 |
42 | interface
43 |
44 | uses
45 | {$IFDEF KOL_MCK}KOL;{$else}SysUtils;{$ENDIF}
46 | {$IFDEF DEBUGLN_ON}
47 | // dummy, default debugging
48 | procedure debugproc(s: string);
49 | // for custom debugging, assign this in your units
50 | var debugln: procedure(s: string) = debugproc;
51 | {$ENDIF}
52 |
53 | type
54 |
55 | // when tag content found in HTML, including names and values
56 | // case insensitive analysis available via NoCaseTag
57 | TOnFoundTag = procedure(NoCaseTag, ActualTag: string) of object;
58 | // procedural:
59 | TOnFoundTagP = procedure(NoCaseTag, ActualTag: string);
60 |
61 | // when text found in the HTML
62 | TOnFoundText = procedure(Text: string) of object;
63 | // procedural:
64 | TOnFoundTextP = procedure(Text: string);
65 |
66 | // Lars's modified html parser, case insensitive or case sensitive
67 | TArrHTMLParser = class(TObject)
68 | private
69 | procedure NilOnFoundTag(NoCaseTag, ActualTag: string);
70 | procedure NilOnFoundText(Text: string);
71 | public
72 | UseArrays: boolean; // store all html in tags[] and texts[] arrays for later access
73 | Tags: array of string; // keeps the whole file in an array of tags
74 | Texts: array of string; // and texts
75 | OnFoundTag: TOnFoundTag;
76 | OnFoundText: TOnFoundText;
77 | OnFoundTagP: TOnFoundTagP;
78 | OnFoundTextP: TOnFoundTextP;
79 | Raw: Pchar;
80 | constructor Create(sRaw: string);overload;
81 | constructor Create(pRaw: PChar);overload;
82 | procedure Exec;
83 | end;
84 |
85 | implementation
86 |
87 | // default debugging, do nothing, let user do his own by assigning DebugLn var
88 | procedure debugproc(s: string);
89 | begin
90 | end;
91 |
92 | function CopyBuffer(StartIndex: PChar; Length: Integer): string;
93 | var
94 | S: string;
95 | begin
96 | SetLength(S, Length);
97 | StrLCopy(@S[1], StartIndex, Length);
98 | Result:= S;
99 | end;
100 |
101 |
102 | { ************************ THTMLParser ************************************** }
103 |
104 | constructor TArrHTMLParser.Create(pRaw: Pchar);
105 | begin
106 | if pRaw = '' then exit;
107 | if pRaw = nil then exit;
108 | Raw:= pRaw;
109 | UseArrays := true;
110 | end;
111 |
112 | constructor TArrHTMLParser.Create(sRaw: string);
113 | begin
114 | // if sRaw = '' then exit;
115 | // Raw:= Pchar(sRaw);
116 | Create(pchar(sRaw));
117 | end;
118 |
119 | { default dummy "do nothing" class events if unassigned }
120 | procedure TArrHTMLParser.NilOnFoundTag(NoCaseTag, ActualTag: string);
121 | begin
122 | end;
123 |
124 | procedure TArrHTMLParser.NilOnFoundText(Text: string);
125 | begin
126 | end;
127 |
128 | { default dummy "do nothing" procedural events if unassigned }
129 | procedure NilOnFoundTagP(NoCaseTag, ActualTag: string);
130 | begin
131 | end;
132 |
133 | procedure NilOnFoundTextP(Text: string);
134 | begin
135 | end;
136 |
137 | procedure TArrHTMLParser.Exec;
138 | var
139 | L, TL, I: integer;
140 | Done: Boolean;
141 | TagStart, TextStart, P: PChar; // Pointer to current char.
142 | C: Char;
143 | OldTagsLen, OldTextsLen: integer;
144 | begin
145 | {$IFDEF DEBUGLN_ON}debugln('FastHtmlParser Exec Begin');{$ENDIF}
146 | { set nil events once rather than checking for nil each time tag is found }
147 | if not assigned(OnFoundText) then OnFoundText:= NilOnFoundText;
148 | if not assigned(OnFoundTag) then OnFoundTag:= NilOnFoundTag;
149 | if not assigned(OnFoundTextP) then OnFoundTextP:= NilOnFoundTextP;
150 | if not assigned(OnFoundTagP) then OnFoundTagP:= NilOnFoundTagP;
151 |
152 | TL:= StrLen(Raw);
153 | I:= 0;
154 | P:= Raw;
155 | Done:= False;
156 | if P <> nil then
157 | begin
158 | TagStart:= nil;
159 | repeat
160 | TextStart:= P;
161 | { Get next tag position }
162 | while Not (P^ in [ '<', #0 ]) do
163 | begin
164 | Inc(P); Inc(I);
165 | if I >= TL then
166 | begin
167 | Done:= True;
168 | Break;
169 | end;
170 | end;
171 | if Done then Break;
172 |
173 | { Is there any text before ? }
174 | if (TextStart <> nil) and (P > TextStart) then
175 | begin
176 | L:= P - TextStart;
177 | { Yes, copy to buffer, OO event:}
178 | OnFoundText( CopyBuffer(TextStart, L) );
179 | // procedural:
180 | OnFoundTextP( CopyBuffer(TextStart, L) );
181 | if UseArrays then begin // new code
182 | OldTextsLen := length(Texts);
183 | setlength(Texts, OldTextsLen+1);
184 | Texts[OldTextsLen] := CopyBuffer(TextStart, L);
185 | end;
186 | end else
187 | begin
188 | TextStart:= nil;
189 | end;
190 | { No }
191 |
192 | TagStart:= P;
193 | while Not (P^ in [ '>', #0]) do
194 | begin
195 | // Find string in tag
196 | if (P^ = '"') or (P^ = '''') then
197 | begin
198 | C:= P^;
199 | Inc(P); Inc(I); // Skip current char " or '
200 |
201 | // Skip until string end
202 | while Not (P^ in [C, #0]) do
203 | begin
204 | Inc(P);Inc(I);
205 | end;
206 | end;
207 |
208 | Inc(P);Inc(I);
209 | if I >= TL then
210 | begin
211 | Done:= True;
212 | Break;
213 | end;
214 | end;
215 | if Done then Break;
216 |
217 | { Copy this tag to buffer }
218 | L:= P - TagStart + 1;
219 | // OO event
220 | OnFoundTag(uppercase(CopyBuffer(TagStart, L)), CopyBuffer(TagStart, L ) ); //L505: added uppercase
221 | // procedural
222 | OnFoundTagP(uppercase(CopyBuffer(TagStart, L)), CopyBuffer(TagStart, L ) );
223 | if UseArrays then begin // new code
224 | OldTagsLen := length(Tags);
225 | setlength(Tags, OldTagsLen+1);
226 | Tags[OldTagsLen] := CopyBuffer(TagStart, L);
227 | end;
228 |
229 | Inc(P); Inc(I);
230 | if I >= TL then Break;
231 | until (Done);
232 | end;
233 | {$IFDEF DEBUGLN_ON}debugln('FastHtmlParser Exec End');{$ENDIF}
234 | end;
235 |
236 |
237 | end.
238 |
239 |
240 |
241 |
242 |
--------------------------------------------------------------------------------
/fasthtmlparser.pas:
--------------------------------------------------------------------------------
1 | {%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 | FastHTMLParser unit to parse HTML
3 | (disect html into its tags and text.)
4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 |
6 | Original AUTHOR : James Azarja, http://www.jazarsoft.com/
7 |
8 | CONTRIBUTORS : L505, http://z505.com
9 |
10 | NOTES: Modified by Lars to work with both freepascal and delphi, and contains
11 | more features
12 |
13 | LEGAL : Copyright (C) 2004 Jazarsoft, All Rights Reserved.
14 | Modified 2005 Lars (L505)
15 | --------------------------------------------------------------------------------
16 | LICENSE/TERMS
17 | --------------------------------------------------------------------------------
18 |
19 | This code may be used and modified by anyone so long as this header and
20 | copyright information remains intact.
21 |
22 | The code is provided "AS-IS" and without WARRANTY OF ANY KIND,
23 | expressed, implied or otherwise, including and without limitation, any
24 | warranty of merchantability or fitness for a particular purpose.
25 |
26 | In no event shall the author be liable for any special, incidental,
27 | indirect or consequential damages whatsoever (including, without
28 | limitation, damages for loss of profits, business interruption, loss
29 | of information, or any other loss), whether or not advised of the
30 | possibility of damage, and on any theory of liability, arising out of
31 | or in connection with the use or inability to use this software.
32 | }
33 |
34 | {$IFDEF FPC}{$MODE DELPHI}{$H+}{$ENDIF}
35 |
36 |
37 | // {$DEFINE DEBUGLN_ON}
38 |
39 | unit fasthtmlparser;
40 |
41 |
42 | interface
43 |
44 | uses
45 | {$IFDEF KOL_MCK}
46 | KOL,
47 | {$else}
48 | SysUtils,
49 | {$ENDIF}
50 | Dialogs, //DEBUG REMOVE THIS LATER
51 | htmtool, htmutils;
52 |
53 |
54 | {$IFDEF DEBUGLN_ON}
55 | // dummy, default debugging
56 | procedure debugproc(s: string);
57 | // for custom debugging, assign this in your units
58 | var debugln: procedure(s: string) = debugproc;
59 | {$ENDIF}
60 |
61 | type
62 |
63 | // when tag content found in HTML, including names and values
64 | // case insensitive analysis available via NoCaseTag
65 | TOnFoundTag = procedure(NoCaseTag, ActualTag: string) of object;
66 | // procedural:
67 | TOnFoundTagP = procedure(NoCaseTag, ActualTag: string);
68 |
69 | // when text found in the HTML
70 | TOnFoundText = procedure(Text: string) of object;
71 | // procedural:
72 | TOnFoundTextP = procedure(Text: string);
73 |
74 | // Lars's modified html parser, case insensitive or case sensitive
75 | THTMLParser = class(TObject)
76 | private
77 | FElementFound: boolean;
78 | FElementTag: string;
79 | FElementTagEnd: string;
80 | FElementHtml: string;
81 | FElementName: string;
82 | FElementId: string;
83 | FFindingElementName: boolean;
84 | FFindingElementId: boolean;
85 | procedure NilOnFoundTag(NoCaseTag, ActualTag: string);
86 | procedure NilOnFoundText(Text: string);
87 | procedure ElementOnFoundTag(NoCaseTag, ActualTag: string);
88 | procedure ElementOnFoundText(Text: string);
89 | public
90 | UseTagTextArray: boolean;
91 | OnFoundTag: TOnFoundTag;
92 | OnFoundText: TOnFoundText;
93 | OnFoundTagP: TOnFoundTagP;
94 | OnFoundTextP: TOnFoundTextP;
95 | Raw: Pchar;
96 | constructor Create(sRaw: string);overload;
97 | constructor Create(pRaw: PChar);overload;
98 | procedure Exec;
99 | function GetElementByName(name: string; var Tag: string; var TagEnd: string): string;
100 | function GetElementById(id: string; var Tag: string; var TagEnd: string): string;
101 | end;
102 |
103 |
104 | implementation
105 |
106 |
107 | // default debugging, do nothing, let user do his own by assigning DebugLn var
108 | procedure debugproc(s: string);
109 | begin
110 | end;
111 |
112 | function CopyBuffer(StartIndex: PChar; Length: Integer): string;
113 | var
114 | S: string;
115 | begin
116 | SetLength(S, Length);
117 | StrLCopy(@S[1], StartIndex, Length);
118 | Result:= S;
119 | end;
120 |
121 | { ************************ THTMLParser ************************************** }
122 |
123 | constructor THTMLParser.Create(pRaw: Pchar);
124 | begin
125 | if pRaw = '' then exit;
126 | if pRaw = nil then exit;
127 | Raw:= pRaw;
128 | FElementFound := false;
129 | FElementTag := '';
130 | FElementTagEnd := '';
131 | FElementHtml := '';
132 | FElementName := '';
133 | FElementId := '';
134 | FFindingElementName := false;
135 | FFindingElementId := false;
136 | end;
137 |
138 | constructor THTMLParser.Create(sRaw: string);
139 | begin
140 | if sRaw = '' then exit;
141 | Raw:= Pchar(sRaw);
142 | end;
143 |
144 | { default dummy "do nothing" class events if unassigned }
145 | procedure THTMLParser.NilOnFoundTag(NoCaseTag, ActualTag: string);
146 | begin
147 | end;
148 |
149 | procedure THTMLParser.NilOnFoundText(Text: string);
150 | begin
151 | end;
152 |
153 | procedure THTMLParser.ElementOnFoundTag(NoCaseTag, ActualTag: string);
154 | begin
155 | // tags inside
156 | if FElementFound then FElementHtml := FElementHtml + ActualTag;
157 |
158 | if (FElementId <> '') and (FFindingElementName) then begin
159 | if GetVal(ActualTag, 'name') = FElementName then begin
160 | FElementFound := true;
161 | FElementTag := ActualTag;
162 | // FElementName := '';
163 | end;
164 | end;
165 |
166 | if (FElementId <> '') and (FFindingElementId) then begin
167 | if GetVal(ActualTag, 'id') = FElementId then begin
168 | FElementFound := true;
169 | FElementTag := ActualTag;
170 | // FElementId := '';
171 | end;
172 | end;
173 | // closer tag
174 | if NoCaseTag[2] = '/' then FElementFound := false;
175 | end;
176 |
177 | procedure THTMLParser.ElementOnFoundText(Text: string);
178 | begin
179 | if FElementFound then begin
180 | FElementHtml := FElementHtml + Text;
181 | end;
182 | end;
183 |
184 | { default dummy "do nothing" procedural events if unassigned }
185 | procedure NilOnFoundTagP(NoCaseTag, ActualTag: string);
186 | begin
187 | end;
188 |
189 | procedure NilOnFoundTextP(Text: string);
190 | begin
191 | end;
192 |
193 | procedure THTMLParser.Exec;
194 | var
195 | L, TL, I: Integer;
196 | Done: Boolean;
197 | TagStart, TextStart, P: PChar; // Pointer to current char.
198 | C: Char;
199 | begin
200 | {$IFDEF DEBUGLN_ON}debugln('FastHtmlParser Exec Begin');{$ENDIF}
201 | { set nil events once rather than checking for nil each time tag is found }
202 | if not assigned(OnFoundText) then OnFoundText:= NilOnFoundText;
203 | if not assigned(OnFoundTag) then OnFoundTag:= NilOnFoundTag;
204 | if not assigned(OnFoundTextP) then OnFoundTextP:= NilOnFoundTextP;
205 | if not assigned(OnFoundTagP) then OnFoundTagP:= NilOnFoundTagP;
206 |
207 | TL:= StrLen(Raw);
208 | I:= 0;
209 | P:= Raw;
210 | Done:= False;
211 | if P <> nil then
212 | begin
213 | TagStart:= nil;
214 | repeat
215 | TextStart:= P;
216 | { Get next tag position }
217 | while Not (P^ in [ '<', #0 ]) do
218 | begin
219 | Inc(P); Inc(I);
220 | if I >= TL then
221 | begin
222 | Done:= True;
223 | Break;
224 | end;
225 | end;
226 | if Done then Break;
227 |
228 | { Is there any text before ? }
229 | if (TextStart <> nil) and (P > TextStart) then
230 | begin
231 | L:= P - TextStart;
232 | { Yes, copy to buffer, OO event:}
233 | OnFoundText( CopyBuffer(TextStart, L) );
234 | // procedural:
235 | OnFoundTextP( CopyBuffer(TextStart, L) );
236 | end else
237 | begin
238 | TextStart:= nil;
239 | end;
240 | { No }
241 |
242 | TagStart:= P;
243 | while Not (P^ in [ '>', #0]) do
244 | begin
245 | // Find string in tag
246 | if (P^ = '"') or (P^ = '''') then
247 | begin
248 | C:= P^;
249 | Inc(P); Inc(I); // Skip current char " or '
250 |
251 | // Skip until string end
252 | while Not (P^ in [C, #0]) do
253 | begin
254 | Inc(P);Inc(I);
255 | end;
256 | end;
257 |
258 | Inc(P);Inc(I);
259 | if I >= TL then
260 | begin
261 | Done:= True;
262 | Break;
263 | end;
264 | end;
265 | if Done then Break;
266 |
267 | { Copy this tag to buffer }
268 | L:= P - TagStart + 1;
269 | // OO event
270 | OnFoundTag(uppercase(CopyBuffer(TagStart, L)), CopyBuffer(TagStart, L ) ); //L505: added uppercase
271 | // procedural
272 | OnFoundTagP(uppercase(CopyBuffer(TagStart, L)), CopyBuffer(TagStart, L ) );
273 |
274 | Inc(P); Inc(I);
275 | if I >= TL then Break;
276 | until (Done);
277 | end;
278 | {$IFDEF DEBUGLN_ON}debugln('FastHtmlParser Exec End');{$ENDIF}
279 | end;
280 |
281 | function THTMLParser.GetElementByName(name: string; var Tag: string; var TagEnd: string): string;
282 | begin
283 | result := '';
284 | FFindingElementName := true;
285 | OnFoundTag := ElementOnFoundTag;
286 | OnFoundText := ElementOnFoundText;
287 | FElementName := name;
288 | Exec;
289 | OnFoundTag := NilOnFoundTag;
290 | OnFoundText := NilOnFoundText;
291 | Tag := FElementTag;
292 | TagEnd := FElementTagEnd;
293 | result := FElementHtml;
294 | FFindingElementName := false;
295 | FElementTag := '';
296 | FElementTagEnd := '';
297 | FElementHtml := '';
298 | FElementId := '';
299 | FElementName := '';
300 | end;
301 |
302 | function THTMLParser.GetElementById(id: string; var Tag: string; var TagEnd: string): string;
303 | begin
304 | result := '';
305 | FFindingElementId := true;
306 | OnFoundTag := ElementOnFoundTag;
307 | OnFoundText := ElementOnFoundText;
308 | FElementId := id;
309 | Exec;
310 | OnFoundTag := NilOnFoundTag;
311 | OnFoundText := NilOnFoundText;
312 | Tag := FElementTag;
313 | TagEnd := FElementTagEnd;
314 | result := FElementHtml;
315 | FFindingElementId := false;
316 | FElementTag := '';
317 | FElementTagEnd := '';
318 | FElementHtml := '';
319 | FElementId := '';
320 | FElementName := '';
321 | end;
322 |
323 | end.
324 |
325 |
--------------------------------------------------------------------------------
/htmutils.pas:
--------------------------------------------------------------------------------
1 | { modified from jsFastHtmlParser for use with freepascal
2 |
3 | Original Author:
4 | James Azarja
5 |
6 | Contributor:
7 | Lars aka L505
8 | http://z505.com }
9 |
10 | unit HtmUtils; {$ifdef fpc} {$MODE OBJFPC} {$H+}{$endif}
11 |
12 | interface
13 |
14 | { most commonly used }
15 | function GetVal(const tag, attribname_ci: string): string;
16 | function GetTagName(const Tag: string): string;
17 | function GetUpTagName(const tag: string): string;
18 |
19 | { less commonly used, but useful }
20 | function GetNameValPair(const tag, attribname_ci: string): string;
21 | function GetValFromNameVal(const namevalpair: string): string;
22 |
23 | { rarely needed nAmE= case sensitivity }
24 | function GetNameValPair_cs(const tag, attribname: string): string;
25 |
26 | { old code with bugs from James }
27 | function GetVal_JAMES(const tag, attribname_ci: string): string;
28 | function GetNameValPair_JAMES(const tag, attribname_ci: string): string;
29 |
30 | { other utilities }
31 | function CopyBuffer(StartIndex: PChar; Len: integer): string;
32 | function Ucase(s: string): string;
33 |
34 | implementation
35 |
36 | // Note: use sysutils if you have problems with your Win64/other platform
37 | uses
38 | {$IFDEF FPC}CompactSysUtils{$ELSE}Sysutils{$ENDIF};
39 |
40 | function CopyBuffer(StartIndex: PChar; Len: integer): string;
41 | var s : String;
42 | begin
43 | SetLength(s, Len);
44 | StrLCopy(@s[1], StartIndex, Len);
45 | result:= s;
46 | end;
47 |
48 | { upper case }
49 | function Ucase(s: string): string;
50 | begin
51 | {$IFDEF FPC}result:= upcase(s);{$ELSE}result:= uppercase(s);{$ENDIF}
52 | end;
53 |
54 | { return value of attrib, NAME case ignored, VALUE case preserved }
55 | function GetVal(const tag, attribname_ci: string): string;
56 | var nameval: string;
57 | begin
58 | result:= '';
59 | if tag = '' then exit;
60 | if attribname_ci = '' then exit;
61 | // returns full name=value pair
62 | nameval:= GetNameValPair(tag, attribname_ci);
63 | // extracts value portion only
64 | result:= GetValFromNameVal(nameval);
65 | end;
66 |
67 | { Return tag name, case preserved }
68 | function GetTagName(const tag: string): string;
69 | var
70 | P : Pchar;
71 | S : Pchar;
72 | begin
73 | P := Pchar(tag);
74 | while P^ in ['<',' ',#9] do inc(P);
75 | S := P;
76 | while Not (P^ in [' ','>',#0]) do inc(P);
77 | if P > S then
78 | Result := CopyBuffer( S, P-S);
79 | end;
80 |
81 | { Return tag name in uppercase }
82 | function GetUpTagName(const tag: string): string;
83 | var
84 | P : Pchar;
85 | S : Pchar;
86 | begin
87 | result:= '';
88 | if tag = '' then exit;
89 | P := Pchar(Ucase(tag));
90 | while P^ in ['<',' ',#9] do inc(P);
91 | S := P;
92 | while Not (P^ in [' ','>',#0]) do inc(P);
93 | if P > S then
94 | Result := CopyBuffer( S, P-S);
95 | end;
96 |
97 |
98 | { Return name=value pair ignore case of NAME, preserve case of VALUE
99 | Lars' fixed version }
100 | function GetNameValPair(const tag, attribname_ci: string): string;
101 | var
102 | P : Pchar;
103 | S : Pchar;
104 | UpperTag,
105 | UpperAttrib : string;
106 | Start: integer;
107 | L : integer;
108 | C : char;
109 | begin
110 | result:= '';
111 | if tag = '' then exit;
112 | if attribname_ci = '' then exit;
113 | // must be space before case insensitive NAME, i.e. nil then
120 | begin
121 | inc(S); // skip space
122 | P:= S;
123 |
124 | // Skip until hopefully equal sign
125 | while not (P^ in ['=', ' ', '>', #0]) do
126 | inc(P);
127 |
128 | if (P^ = '=') then inc(P);
129 |
130 | while not (P^ in [' ','>',#0]) do
131 | begin
132 | if (P^ in ['"','''']) then
133 | begin
134 | C:= P^;
135 | inc(P); { Skip quote }
136 | end else
137 | C:= ' ';
138 |
139 | { thanks to Dmitry [mail@vader.ru] }
140 | while not (P^ in [C, '>', #0]) do
141 | Inc(P);
142 |
143 | if (P^ <> '>') then inc(P); { Skip current character, except '>' }
144 |
145 | break;
146 | end;
147 |
148 | L:= P - S;
149 | Start:= S - Pchar(UpperTag);
150 | P:= Pchar(Tag);
151 | S:= P;
152 | inc(S, Start);
153 |
154 | result:= CopyBuffer(S, L);
155 | end;
156 | end;
157 |
158 | { Get value of attribute, e.g WIDTH=36 returns 36, preserves case of value }
159 | function GetValFromNameVal(const namevalpair: string): string;
160 | var
161 | P: Pchar;
162 | S: Pchar;
163 | C: Char;
164 | begin
165 | result:= '';
166 | if namevalpair = '' then exit;
167 | P:= Pchar(namevalpair);
168 | S:= StrPos(P, '=');
169 |
170 | if S <> nil then
171 | begin
172 | inc(S); // skip equal
173 | P:= S; // set P to a character after =
174 |
175 | if (P^ in ['"','''']) then
176 | begin
177 | C:= P^;
178 | Inc(P); { Skip current character }
179 | end else
180 | C:= ' ';
181 |
182 | S:= P;
183 | while not (P^ in [C, #0]) do
184 | inc(P);
185 |
186 | if (P <> S) then { Thanks to Dave Keighan (keighand@yahoo.com) }
187 | Result:= CopyBuffer(S, P - S)
188 | else
189 | Result:= '';
190 | end;
191 | end;
192 |
193 | { return name=value portion, case sensitive, case preserved, rarely useful }
194 | function GetNameValPair_cs(const Tag, attribname: string): string;
195 | var
196 | P : Pchar;
197 | S : Pchar;
198 | C : Char;
199 | begin
200 | result:= '';
201 | if tag = '' then exit;
202 | if attribname = '' then exit;
203 | P := Pchar(Tag);
204 | S := StrPos(P, Pchar(attribname));
205 | if S<>nil then
206 | begin
207 | P := S;
208 |
209 | // Skip attribute name
210 | while not (P^ in ['=',' ','>',#0]) do
211 | inc(P);
212 |
213 | if (P^ = '=') then inc(P);
214 |
215 | while not (P^ in [' ','>',#0]) do
216 | begin
217 |
218 | if (P^ in ['"','''']) then
219 | begin
220 | C:= P^;
221 | inc(P); { Skip current character }
222 | end else
223 | C:= ' ';
224 |
225 | { thanks to Dmitry [mail@vader.ru] }
226 | while not (P^ in [C, '>', #0]) do
227 | inc(P);
228 |
229 | if (P^<>'>') then inc(P); { Skip current character, except '>' }
230 | break;
231 | end;
232 |
233 | if P > S then
234 | Result:= CopyBuffer(S, P - S)
235 | else
236 | Result:= '';
237 | end;
238 | end;
239 |
240 |
241 | { ----------------------------------------------------------------------------
242 | BELOW FUNCTIONS ARE OBSOLETE OR RARELY NEEDED SINCE THEY EITHER CONTAIN BUGS
243 | OR THEY ARE TOO CASE SENSITIVE (FOR THE TAG NAME PORTION OF THE ATTRIBUTE }
244 |
245 | { James old buggy code for testing purposes.
246 | Bug: when finding 'ID', function finds "width", even though width <> "id" }
247 | function GetNameValPair_JAMES(const tag, attribname_ci: string): string;
248 | var
249 | P : Pchar;
250 | S : Pchar;
251 | UT,
252 | UA : string;
253 | Start: integer;
254 | L : integer;
255 | C : char;
256 | begin
257 | UA:= Ucase(attribname_ci);
258 | UT:= Ucase(Tag);
259 | P:= Pchar(UT);
260 | S:= StrPos(P, Pchar(UA));
261 | if S <> nil then
262 | begin
263 |
264 | P := S;
265 |
266 | // Skip attribute name
267 | while not (P^ in ['=',' ','>',#0]) do
268 | inc(P);
269 |
270 | if (P^ = '=') then inc(P);
271 |
272 | while not (P^ in [' ','>',#0]) do
273 | begin
274 |
275 | if (P^ in ['"','''']) then
276 | begin
277 | C:= P^;
278 | inc(P); { Skip current character }
279 | end else
280 | C:= ' ';
281 |
282 | { thanks to Dmitry [mail@vader.ru] }
283 | while not (P^ in [C, '>', #0]) do
284 | Inc(P);
285 |
286 | if (P^ <> '>') then inc(P); { Skip current character, except '>' }
287 | break;
288 | end;
289 |
290 | L:= P - S;
291 | Start:= S - Pchar(UT);
292 | P:= Pchar(Tag);
293 | S:= P;
294 | inc(S, Start);
295 | result:= CopyBuffer(S, L);
296 | end;
297 | end;
298 |
299 |
300 | { James old buggy code for testing purposes }
301 | function GetVal_JAMES(const tag, attribname_ci: string): string;
302 | var namevalpair: string;
303 | begin
304 | namevalpair:= GetNameValPair_JAMES(tag, attribname_ci);
305 | result:= GetValFromNameVal(namevalpair);
306 | end;
307 |
308 |
309 | end.
310 |
311 |
312 |
313 |
314 |
315 | (* alternative, not needed
316 |
317 | { return value (case preserved) from a name=value pair, ignores case in given NAME= portion }
318 | function GetValFromNameVal(namevalpair: string): string;
319 |
320 | type
321 | TAttribPos = record
322 | startpos: longword; // start pos of value
323 | len: longword; // length of value
324 | end;
325 |
326 | { returns case insensitive start position and length of just the value
327 | substring in name=value pair}
328 | function ReturnPos(attribute: string): TAttribPos;
329 | var
330 | P : Pchar;
331 | S : Pchar;
332 | C : Char;
333 | begin
334 | result.startpos:= 0;
335 | result.len:= 0;
336 | P:= Pchar(uppercase(Attribute));
337 | // get substring including and everything after equal
338 | S:= StrPos(P, '=');
339 | result.startpos:= pos('=', P);
340 |
341 | if S <> nil then
342 | begin
343 | inc(S);
344 | // set to character after =
345 | inc(result.startpos);
346 | P:= S;
347 |
348 | if (P^ in ['"','''']) then
349 | begin
350 | C:= P^;
351 | // skip quote
352 | inc(P);
353 | inc(result.startpos);
354 | end else
355 | C:= ' ';
356 |
357 | S:= P;
358 | // go to end quote or end of value
359 | while not (P^ in [C, #0]) do
360 | inc(P);
361 |
362 | if (P <> S) then
363 | begin
364 | result.len:= p - s;
365 | end;
366 | end;
367 |
368 | end;
369 |
370 | var
371 | found: TAttribPos;
372 | begin
373 | found:= ReturnPos(namevalpair);
374 | // extract using coordinates
375 | result:= MidStr(namevalpair, found.startpos, found.len);
376 | end;
377 |
378 | *)
379 |
380 |
381 |
382 |
383 |
--------------------------------------------------------------------------------
/demo-delphi/HtmParser.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {B3B4203E-9C17-4618-9FE3-653DB7CBC04F}
4 | 18.1
5 | VCL
6 | HtmParser.dpr
7 | True
8 | Debug
9 | Win32
10 | 1
11 | Application
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Cfg_1
34 | true
35 | true
36 |
37 |
38 | true
39 | Base
40 | true
41 |
42 |
43 | true
44 | Cfg_2
45 | true
46 | true
47 |
48 |
49 | $(BDS)\bin\delphi_PROJECTICON.ico
50 | HtmParser
51 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
52 | .\$(Platform)\$(Config)
53 | .\$(Platform)\$(Config)
54 | false
55 | false
56 | false
57 | false
58 | false
59 |
60 |
61 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
62 | $(BDS)\bin\default_app.manifest
63 | DBXSqliteDriver;bindcompdbx;IndyIPCommon;RESTComponents;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;PowStringGrids;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;FireDACASADriver;inetdb;ChromeTabs_R;SVGPackage;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ModScrCamDSeattle_Package;FireDACIBDriver;fmx;fmxdae;xmlrtl;soapmidas;Tee;fmxobj;vclwinx;InternetExplorerActiveX;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;speechlib;vclx;DCEF_DX10;bindcomp;appanalytics;dsnap;ModScrCamDSeattle_PackageDsgn;FireDACCommon;IndyIPClient;bindcompvcl;SynEdit_R;RESTBackendComponents;TeeUI;VCLRESTComponents;vclribbon;dbxcds;VclSmp;soapserver;adortl;FireDACODBCDriver;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;inetdbxpress;IndyProtocols;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
64 | true
65 | 1033
66 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
67 |
68 |
69 | DBXSqliteDriver;bindcompdbx;IndyIPCommon;RESTComponents;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;FireDACASADriver;inetdb;ChromeTabs_R;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;xmlrtl;soapmidas;Tee;fmxobj;vclwinx;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;DCEF_DX10;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;SynEdit_R;RESTBackendComponents;TeeUI;VCLRESTComponents;vclribbon;dbxcds;VclSmp;soapserver;adortl;FireDACODBCDriver;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;inetdbxpress;IndyProtocols;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
70 |
71 |
72 | DEBUG;$(DCC_Define)
73 | true
74 | false
75 | true
76 | true
77 | true
78 |
79 |
80 | true
81 | c:\important\fasthtmlparser\trunk\;$(DCC_UnitSearchPath)
82 | 1033
83 | true
84 | true
85 | false
86 |
87 |
88 | false
89 | RELEASE;$(DCC_Define)
90 | 0
91 | 0
92 |
93 |
94 | true
95 | true
96 |
97 |
98 |
99 | MainSource
100 |
101 |
102 |
103 | dfm
104 |
105 |
106 | Cfg_2
107 | Base
108 |
109 |
110 | Base
111 |
112 |
113 | Cfg_1
114 | Base
115 |
116 |
117 |
118 | Delphi.Personality.12
119 | Application
120 |
121 |
122 |
123 | HtmParser.dpr
124 |
125 |
126 | Microsoft Office 2000 Sample Automation Server Wrapper Components
127 | Microsoft Office XP Sample Automation Server Wrapper Components
128 |
129 |
130 |
131 |
132 |
133 | HtmParser.exe
134 | true
135 |
136 |
137 |
138 |
139 | 0
140 | .dll;.bpl
141 |
142 |
143 | 1
144 | .dylib
145 |
146 |
147 | Contents\MacOS
148 | 1
149 | .dylib
150 |
151 |
152 | 1
153 | .dylib
154 |
155 |
156 | 1
157 | .dylib
158 |
159 |
160 |
161 |
162 | Contents\Resources
163 | 1
164 |
165 |
166 |
167 |
168 | classes
169 | 1
170 |
171 |
172 |
173 |
174 | Contents\MacOS
175 | 0
176 |
177 |
178 | 1
179 |
180 |
181 | Contents\MacOS
182 | 1
183 |
184 |
185 |
186 |
187 | 1
188 |
189 |
190 | 1
191 |
192 |
193 | 1
194 |
195 |
196 |
197 |
198 | res\drawable-xxhdpi
199 | 1
200 |
201 |
202 |
203 |
204 | library\lib\mips
205 | 1
206 |
207 |
208 |
209 |
210 | 0
211 |
212 |
213 | 1
214 |
215 |
216 | Contents\MacOS
217 | 1
218 |
219 |
220 | 1
221 |
222 |
223 | library\lib\armeabi-v7a
224 | 1
225 |
226 |
227 | 1
228 |
229 |
230 |
231 |
232 | 0
233 |
234 |
235 | Contents\MacOS
236 | 1
237 | .framework
238 |
239 |
240 |
241 |
242 | 1
243 |
244 |
245 | 1
246 |
247 |
248 | 1
249 |
250 |
251 |
252 |
253 | 1
254 |
255 |
256 | 1
257 |
258 |
259 | 1
260 |
261 |
262 |
263 |
264 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
265 | 1
266 |
267 |
268 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
269 | 1
270 |
271 |
272 |
273 |
274 | library\lib\x86
275 | 1
276 |
277 |
278 |
279 |
280 | 1
281 |
282 |
283 | 1
284 |
285 |
286 | 1
287 |
288 |
289 |
290 |
291 | 1
292 |
293 |
294 | 1
295 |
296 |
297 | 1
298 |
299 |
300 |
301 |
302 | library\lib\armeabi
303 | 1
304 |
305 |
306 |
307 |
308 | 0
309 |
310 |
311 | 1
312 |
313 |
314 | Contents\MacOS
315 | 1
316 |
317 |
318 |
319 |
320 | 1
321 |
322 |
323 | 1
324 |
325 |
326 | 1
327 |
328 |
329 |
330 |
331 | res\drawable-normal
332 | 1
333 |
334 |
335 |
336 |
337 | res\drawable-xhdpi
338 | 1
339 |
340 |
341 |
342 |
343 | res\drawable-large
344 | 1
345 |
346 |
347 |
348 |
349 | 1
350 |
351 |
352 | 1
353 |
354 |
355 | 1
356 |
357 |
358 |
359 |
360 | ../
361 | 1
362 |
363 |
364 | ../
365 | 1
366 |
367 |
368 |
369 |
370 | res\drawable-hdpi
371 | 1
372 |
373 |
374 |
375 |
376 | library\lib\armeabi-v7a
377 | 1
378 |
379 |
380 |
381 |
382 | Contents
383 | 1
384 |
385 |
386 |
387 |
388 | ../
389 | 1
390 |
391 |
392 |
393 |
394 | 1
395 |
396 |
397 | 1
398 |
399 |
400 | 1
401 |
402 |
403 |
404 |
405 | res\values
406 | 1
407 |
408 |
409 |
410 |
411 | res\drawable-small
412 | 1
413 |
414 |
415 |
416 |
417 | res\drawable
418 | 1
419 |
420 |
421 |
422 |
423 | 1
424 |
425 |
426 | 1
427 |
428 |
429 | 1
430 |
431 |
432 |
433 |
434 | 1
435 |
436 |
437 |
438 |
439 | res\drawable
440 | 1
441 |
442 |
443 |
444 |
445 | 0
446 |
447 |
448 | 0
449 |
450 |
451 | Contents\Resources\StartUp\
452 | 0
453 |
454 |
455 | 0
456 |
457 |
458 | 0
459 |
460 |
461 | 0
462 |
463 |
464 |
465 |
466 | library\lib\armeabi-v7a
467 | 1
468 |
469 |
470 |
471 |
472 | 0
473 | .bpl
474 |
475 |
476 | 1
477 | .dylib
478 |
479 |
480 | Contents\MacOS
481 | 1
482 | .dylib
483 |
484 |
485 | 1
486 | .dylib
487 |
488 |
489 | 1
490 | .dylib
491 |
492 |
493 |
494 |
495 | res\drawable-mdpi
496 | 1
497 |
498 |
499 |
500 |
501 | res\drawable-xlarge
502 | 1
503 |
504 |
505 |
506 |
507 | res\drawable-ldpi
508 | 1
509 |
510 |
511 |
512 |
513 | 1
514 |
515 |
516 | 1
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 | True
529 | False
530 |
531 |
532 | 12
533 |
534 |
535 |
536 |
537 |
538 |
--------------------------------------------------------------------------------