OSDN Git Service

・スレタイの特定ワードを非表示にする機能に「©bbspink.com」も追加
[gikonavigoeson/gikonavi.git] / GikoXMLDoc.pas
1 unit GikoXMLDoc;
2
3 {!
4 \file           GikoXMLDoc.pas
5 \brief  XMLIntf, XMLDoc \82 \82½\82è\82Ì\83N\83\8d\81[\83\93<br>
6                                 Delphi 6 Personal \97p
7
8 $Id: GikoXMLDoc.pas,v 1.10 2004/10/09 15:07:20 yoffy Exp $
9 }
10 interface
11
12 //==================================================
13 uses
14 //==================================================
15
16         Classes, SysUtils, Windows,
17         YofUtils;
18
19 //==================================================
20 type
21 //==================================================
22
23         // \82í\82¯\82í\82©\82ç\82¸\8dì\82Á\82Ä\82é\82©\82ç\83o\83O\82¾\82ç\82¯\82©\82à
24         XMLDictionary = Record
25                 Name : string;
26                 Value : string;
27         end;
28
29         IXMLNode = class
30         private
31                 FNodeName : string;
32                 FCapacity : Integer;
33                 FCount : Integer;
34                 FAttributeCount : Integer;
35                 FChildNodes : IXMLNode;
36                 FNodes : array of IXMLNode;
37                 FAttributes : array of XMLDictionary;
38                 function GetAttribute( const Name : string ) : string;
39                 function GetNode( Index : Integer ) : IXMLNode;
40         public
41                 constructor     Create;
42                 destructor      Destroy; override;
43
44                 property NodeName : string read FNodeName write FNodeName;
45                 property Attributes[ const Name : string ] : string read GetAttribute;
46                 property Node[ Index : Integer ] : IXMLNode read GetNode; default;
47                 property ChildNodes : IXMLNode read FChildNodes write FChildNodes;
48                 property Count : Integer read FCount write FCount;
49                 procedure Add( node : IXMLNode );
50                 procedure AddAttribute( const Name : string; const Value : string );
51         end;
52
53         IXMLDocument = class( IXMLNode )
54         private
55                 function GetDocumentElement() : IXMLNode;
56         public
57                 property DocumentElement : IXMLNode read GetDocumentElement;
58         end;
59
60 function XMLCloseCheck(
61         var p                           : PChar;
62         const tail      : PChar;
63         var node : IXMLNode;
64         out tag : string;
65         out closed : boolean // \8cÄ\82Ñ\8fo\82µ\82½\83\8b\81[\83`\83\93\82ª node \82ð\95Â\82\82é\82×\82«\82È\82ç true
66 ) : boolean; // ch \82ð\82±\82Ì\83\8b\81[\83`\83\93\82ª\8f\88\97\9d\82µ\82½\82È\82ç true
67
68 function XMLReadNode(
69         var p                           : PChar;
70         const tail      : PChar;
71         var node : IXMLNode
72 ) : string; // node \88È\8aO\82Ì\83m\81[\83h\82ª\95Â\82\82ç\82ê\82½\8fê\8d\87\82Ì\83m\81[\83h\96¼
73
74 procedure LoadXMLDocument(
75         const fileName : string;
76     var doc : IXMLDocument
77 );
78
79 //==================================================
80 const
81 //==================================================
82         kXMLWhite : TSysCharSet = [#0..#$20];
83         kXMLNodeNameStop : TSysCharSet = [#0..#$20, '/', '>'];
84         kXMLAttributeNameStop : TSysCharSet = [#0..#$20, '=', '/', '>'];
85         kXMLDQuote : TSysCharSet = ['"'];
86         kXMLTagStart : TSysCharSet = ['<'];
87         kXMLTagEnd : TSysCharSet = ['>'];
88         kXMLKanji : TSysCharSet = [#$81..#$9f, #$E0..#$fc];
89
90 //==================================================
91 implementation
92 //==================================================
93
94 // Constructor
95 constructor     IXMLNode.Create;
96 begin
97
98         inherited;
99
100         FCapacity := 0;
101         FCount := 0;
102
103 end;
104
105 // Destructor
106 destructor      IXMLNode.Destroy;
107 var
108         i : Integer;
109 begin
110
111         for i := FCount - 1 downto 0 do
112                 FNodes[ i ].Free;
113         FChildNodes.Free;
114
115         inherited;
116
117 end;
118
119 function IXMLNode.GetAttribute( const Name : string ) : string;
120 var
121         i : Integer;
122 begin
123
124         i := 0;
125         while i < FAttributeCount do
126         begin
127                 if Name = FAttributes[ i ].Name then
128                 begin
129                         Result := FAttributes[ i ].Value;
130                         exit;
131                 end;
132
133                 Inc( i );
134         end;
135
136 end;
137
138 function IXMLNode.GetNode( Index : Integer ) : IXMLNode;
139 begin
140
141         Result := FNodes[ Index ];
142
143 end;
144
145 procedure IXMLNode.Add( node : IXMLNode );
146 begin
147
148         Inc( FCount );
149         if FCount > FCapacity then begin
150                 FCapacity := FCapacity + (FCapacity shr 2) + 1;
151                 SetLength( FNodes, FCapacity );
152         end;
153
154         FNodes[ FCount - 1 ] := node;
155
156 end;
157
158 procedure IXMLNode.AddAttribute(
159         const Name : string;
160         const Value : string
161 );
162 var
163         index : Integer;
164 begin
165
166         index := FAttributeCount;
167         Inc( FAttributeCount );
168         SetLength( FAttributes, FAttributeCount );
169
170         FAttributes[ index ].Name := Name;
171         FAttributes[ index ].Value := Value;
172
173 end;
174
175 function IXMLDocument.GetDocumentElement() : IXMLNode;
176 begin
177
178         Result := FChildNodes[ 0 ];
179
180 end;
181
182 {!
183 \brief  tok \82ð\92T\82·
184 \param  p                       \92T\8dõ\8aJ\8en\88Ê\92u
185 \param  tail    \8fI\97¹\88Ê\92u + 1
186 \param  tok             \92T\82·\83L\83\83\83\89\83N\83^
187 \return tok \82ª\8dÅ\8f\89\82É\8c©\82Â\82©\82Á\82½\88Ê\92u
188 }
189 function AnsiStrTok(
190         p                       : PChar;
191         const tail      : PChar;
192         const tok : TSysCharSet
193 ) : PChar;
194 begin
195
196         while p < tail do
197         begin
198                 if p^ in tok then
199                 begin
200                         Break;
201                 end else if p^ in kXMLKanji then
202                         p := p + 2
203                 else
204                         Inc( p );
205         end;
206
207         Result := p;
208
209 end;
210
211 {!
212 \brief  tok \82Å\82Í\96³\82¢\83L\83\83\83\89\83N\83^\82ð\92T\82·
213 \param  p                       \92T\8dõ\8aJ\8en\88Ê\92u
214 \param  tail    \8fI\97¹\88Ê\92u + 1
215 \param  tok             \92T\82·\83L\83\83\83\89\83N\83^
216 \return tok \82Å\82Í\82È\82¢\83L\83\83\83\89\83N\83^\82ª\8dÅ\8f\89\82É\8c©\82Â\82©\82Á\82½\88Ê\92u
217 }
218 function AnsiStrNonTok(
219         p                       : PChar;
220         const tail      : PChar;
221         const tok : TSysCharSet
222 ) : PChar;
223 begin
224
225         while p < tail do
226         begin
227                 if p^ in tok then
228                 begin
229                         if p^ in kXMLKanji then
230                                 p := p + 2
231                         else
232                                 Inc( p );
233                 end else begin
234                         Break;
235                 end;
236         end;
237
238         Result := p;
239
240 end;
241
242 function XMLCloseCheck(
243         var p : PChar;
244         const tail      : PChar;
245         var node : IXMLNode;
246         out tag : string;
247         out closed : boolean
248 ) : boolean; // ch \82ð\82±\82Ì\83\8b\81[\83`\83\93\82ª\8f\88\97\9d\82µ\82½\82È\82ç true
249 var
250         found           : PChar;
251 begin
252
253         closed := false;
254         Result := false;
255         tag := '';
256
257         case p^ of
258         '>':
259                 begin
260                         // \8aJ\8en\83^\83O\82Ì\8dÅ\8cã\82Ü\82Å\93Ç\82ñ\82¾
261                         Inc( p );       // '>' \94ò\82Î\82µ
262                         Result := true;
263                 end;
264
265         '?':
266                 begin
267                         // <?xml?> \82Ý\82½\82¢\82È\82â\82Â\81B\82æ\82Á\82Ä\96³\8e\8b
268                         p := AnsiStrTok( p, tail, kXMLTagEnd );
269                         p := AnsiStrTok( p, tail, kXMLTagStart );
270                         Inc( p );       // '<' \94ò\82Î\82µ
271                         p := AnsiStrNonTok( p, tail, kXMLWhite );
272                         //closed := true;
273                         Result := true;
274                 end;
275
276         '/':
277                 begin
278                         // \83^\83O\96¼\82ð\93Ç\82Ý\8d\9e\82ñ\82Å\95Ô\82·
279                         Inc( p );       // '/' \94ò\82Î\82µ
280                         found := AnsiStrTok( p, tail, kXMLTagEnd );
281 //                      tag := Copy( p, 0, found - p ); // \89½\8cÌ\82©\8c\83\92x
282                         SetLength( tag, found - p );
283                         CopyMemory( PChar( tag ), p, found - p );
284
285                         p := found + 1; // '>' \94ò\82Î\82µ
286                         closed := true;
287                         Result := true;
288                 end;
289         end;
290
291 end;
292
293 function XMLReadNode(
294         var p : PChar;
295         const tail      : PChar;
296         var node : IXMLNode
297 ) : string; // node \88È\8aO\82Ì\83m\81[\83h\82ª\95Â\82\82ç\82ê\82½\8fê\8d\87\82Ì\83m\81[\83h\96¼
298 var
299         child : IXMLNode;
300
301         found : PChar;
302         tag : string;
303
304         isClosed : boolean;
305
306         nodeName : string;
307         attributeName : string;
308         attributeValue : string;
309 label
310         NextNode;
311 begin
312         try
313                 // node \82Ì\93Ç\82Ý\8d\9e\82Ý(1 \83\8b\81[\83v\82É\82Â\82« 1 \83m\81[\83h)
314                 node.ChildNodes := IXMLNode.Create;
315
316                 while p < tail do
317                 begin
318                         // NodeName \93Ç\82Ý\8d\9e\82Ý
319                         p := AnsiStrNonTok( p, tail, kXMLWhite );
320
321                         while p < tail do
322                         begin
323                                 if XMLCloseCheck( p, tail, node, tag, isClosed ) then
324                                 begin
325                                         if isClosed then
326                                         begin
327                                                 Result := tag;
328                                                 exit;
329                                         end;
330
331                                         goto NextNode;
332                                 end else if p^ = '<' then
333                                 begin
334                                         // \90V\8bK\83m\81[\83h
335                                         Inc( p );
336                                         child := IXMLNode.Create;
337                                         tag := XMLReadNode( p, tail, child );
338                                         node.ChildNodes.Add( child );
339
340                                         // \83^\83O\82ª\95Â\82\82ç\82ê\82½
341                                         if Length( tag ) > 0 then
342                                         begin
343                                                 // \8e©\95ª\82Ì\82à\82Ì\82©\83`\83F\83b\83N\82µ\82Ä\81A\88á\82¦\82Î\90e\82É\95Ô\82·
344                                                 if tag <> node.NodeName then
345                                                         Result := tag;
346                                                 exit;
347                                         end;
348
349                                         goto NextNode;
350                                 end else if p^ in kXMLWhite then
351                                 begin
352                                         // NodeName \8a®\97¹
353                                         break;
354                                 end else begin
355                                         found := AnsiStrTok( p, tail, kXMLNodeNameStop );
356                                         SetLength( nodeName, found - p );
357                                         CopyMemory( PChar( nodeName ), p, found - p );
358                                         node.NodeName := nodeName;
359
360                                         p := found;
361                                 end;
362                         end;
363
364                         // Attribute \82Ì\93Ç\82Ý\8d\9e\82Ý
365                         while p < tail do
366                         begin
367                                 // Attribute \82Ì\96¼\91O\82ð\93Ç\82Ý\8d\9e\82Ý
368                                 attributeName := '';
369                                 attributeValue := '';
370
371                                 p := AnsiStrNonTok( p, tail, kXMLWhite );
372
373                                 while p < tail do
374                                 begin
375                                         if XMLCloseCheck( p, tail, node, tag, isClosed ) then
376                                         begin
377                                                 if isClosed then
378                                                 begin
379                                                         // \83^\83O\82ª\95Â\82\82ç\82ê\82½\82Ì\82Å\83\8a\83^\81[\83\93
380                                                         // \81¦NodeName \82ð\92Ê\89ß\82µ\82Ä\82é\82Ì\82Å\93r\92\86\82Å\95Â\82\82Ä\82é\82±\82Æ\82É\82È\82é\81B
381                                                         // \82æ\82Á\82Ä\93Æ\97§\83m\81[\83h\81B
382                                                         exit;
383                                                 end;
384
385                                                 // \8e\9f\82Ì\83m\81[\83h\82Ö
386                                                 goto NextNode;
387                                         end else if p^ = '=' then
388                                         begin
389                                                 // \82±\82±\82©\82ç\82Í\92l\82ª\8en\82Ü\82é\82Ì\82Å\96¼\91O\82Í\8fI\97¹
390                                                 Inc( p );
391                                                 break;
392                                         end else if p^ in kXMLWhite then
393                                         begin
394                                                 // Value \82ª\91\8dÝ\82µ\82È\82¢(\8bK\8ai\8aO)\82Ì\82Å\8e\9f\82Ì\83m\81[\83h\82Ö
395                                                 goto NextNode;
396                                         end else begin
397                                                 found := AnsiStrTok( p, tail, kXMLAttributeNameStop );
398                                                 SetLength( attributeName, found - p );
399                                                 CopyMemory( PChar( attributeName ), p, found - p );
400
401                                                 p := found;
402                                         end;
403                                 end;
404
405                                 // Attribute \82Ì\92l\82ð\93Ç\82Ý\8d\9e\82Ý
406                                 p := AnsiStrNonTok( p, tail, kXMLWhite );
407
408                                 while p < tail do
409                                 begin
410                                         if XMLCloseCheck( p, tail, node, tag, isClosed ) then
411                                         begin
412                                                 if isClosed then
413                                                 begin
414                                                         if Length( attributeName ) > 0 then
415                                                                 // \8bK\8ai\8aO\82¾\82¯\82Ç\82Ë
416                                                                 node.AddAttribute( attributeName, attributeValue );
417
418                                                         // \83^\83O\82ª\95Â\82\82ç\82ê\82½\82Ì\82Å\83\8a\83^\81[\83\93
419                                                         // \81¦NodeName \82ð\92Ê\89ß\82µ\82Ä\82é\82Ì\82Å\93r\92\86\82Å\95Â\82\82Ä\82é\82±\82Æ\82É\82È\82é\81B
420                                                         // \82æ\82Á\82Ä\93Æ\97§\83m\81[\83h\81B
421                                                         exit;
422                                                 end;
423
424                                                 // \8e\9f\82Ì\83m\81[\83h\82Ö
425                                                 goto NextNode;
426                                         end else if p^ = '"' then
427                                         begin
428                                                 // \92l\82ª "" \82Å\8a\87\82ç\82ê\82Ä\82é\82Ì\82Å(\82Ä\82¢\82¤\82©\8a\87\82ç\82ê\82Ä\82È\82«\82á\82¢\82¯\82È\82¢\82ñ\82¾\82¯\82Ç)
429                                                 // \92l\82ð\88ê\8a\87\93Ç\82Ý\8d\9e\82Ý
430                                                 Inc( p );
431                                                 found := AnsiStrTok( p, tail, kXMLDQuote );
432 //                                              attributeValue := Copy( p, 0, found - p );      // \89½\8cÌ\82©\8c\83\92x
433                                                 SetLength( attributeValue, found - p );
434                                                 CopyMemory( PChar( attributeValue ), p, found - p );
435
436                                                 node.AddAttribute( attributeName, HtmlDecode( attributeValue ) );
437
438                                                 // \92l\82ð\93Ç\82Ý\8fI\82í\82Á\82½\82Ì\82Å\8fI\97¹
439                                                 p := found + 1; // '"' \94ò\82Î\82µ
440                                                 break;
441                                         end else if p^ in kXMLWhite then
442                                         begin
443                                                 // \8bK\8ai\8aO\82¾\82¯\82Ç\82Ë
444                                                 node.AddAttribute( attributeName, HtmlDecode( attributeValue ) );
445
446                                                 goto NextNode;
447                                         end else begin
448                                                 // \8bK\8ai\8aO\82¾\82¯\82Ç\88ê\89\9e\8eæ\82Á\82Ä\82¨\82­
449                                                 attributeValue := attributeValue + p^;
450
451                                                 if p^ in kXMLKanji then
452                                                 begin
453                                                         attributeValue := attributeValue + (p + 1)^;
454                                                         p := p + 2;
455                                                 end else begin
456                                                         Inc( p );
457                                                 end;
458                                         end;
459                                 end;
460                         end; // Attribute \82Ì\93Ç\82Ý\8d\9e\82Ý
461
462                         NextNode:;
463                 end; // // node \82Ì\93Ç\82Ý\8d\9e\82Ý(1 \83\8b\81[\83v\82É\82Â\82« 1 \83m\81[\83h)
464         finally
465         end;
466 end;
467
468 procedure LoadXMLDocument(
469         const fileName : string;
470         var doc : IXMLDocument
471 );
472 type
473         xmlMode = ( xmlHoge );
474 var
475         xmlFile : TMappedFile;
476         p                               : PChar;
477 begin
478                 //Result := IXMLDocument.Create;
479         //doc := IXMLDocument.Create;
480
481         xmlFile := TMappedFile.Create( fileName );
482
483         try
484                 p := xmlFile.Memory;
485                 XMLReadNode( p, p + xmlFile.Size, IXMLNode( doc ) );
486                 //XMLReadNode( xmlFile, IXMLNode( Result ) );
487         finally
488                 xmlFile.Free;
489         end;
490
491         //Result := doc;
492
493 end;
494
495 end.