Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   replace string in text files (https://www.delphipraxis.net/203146-replace-string-text-files.html)

direktor 17. Jan 2020 18:22

replace string in text files
 
Hello,

I want to replace certain text in html files. Like I want to replace all text in html file from <header> to </header> and <footer> to </footer> - all text between beginning and ending of headers and footers. How can I do that? It's not stringreplace function. I need to replace all text between this header and footer tags. I can detect with Pos function where <header> begins and ends. So I get 2 integers I and J. I need to replace all text between I and J position of string occurance in text file. Any solutions? Thanks.

Dalai 17. Jan 2020 18:39

AW: replace string in text files
 
Well, the easy way would be something like this: Read the file into a TStringList variable (Delphi-Referenz durchsuchenTStringList.LoadFromFile) and replace everything in Delphi-Referenz durchsuchenTStringList.Text from (and including) <header> to </header> with "<header>your_new_text</header>" with the Delphi-Referenz durchsuchenStringReplace function. However, I doubt that this will be the fastest way in terms of performance (e.g. because the .Text property makes a copy of the whole string).

[EDIT]
It just came to me that StringReplace in Delphi doesn't work with offsets. So, you probably need to determine the offset of <header> and </header> tags with Delphi-Referenz durchsuchenPos function and use Delphi-Referenz durchsuchenCopy function to get the substring between these tags and then use StringReplace on that substring.
[/EDIT]

Regards
Dalai

Dennis07 17. Jan 2020 21:04

AW: replace string in text files
 
This might work, but is not a really secure and surely not the fastest way.
Have a look at LinaComponents, in WebCtrls.pas, there is a THtmlDocument class. It should give you an idea or perhaps even do exactly that. The problem with HTML are for example the comments, or text inside strings, that need to be ignored.
The source for the parsing goes as follows (original can be found in LinaComponent's WebCtrls unit):
Delphi-Quellcode:
procedure THtmlDocumentTag.LinesChange(Sender: TObject);
var
  Index: Integer;
  Current: PChar;
  CurrentTag: String;
  TagName: String;
  TagText: String;
  TagLines: TStrings;
  InTag, InTagArea: Boolean;
  TagKind: (tagOpen,tagClose,tagSingle,tagComment);
begin
  for Index := 0 to TagCount - 1 do
  begin
    Tags[Index].Free;
  end;
  SetLength(FTags,0);
  FText := '';
  TagName := '';
  TagText := '';
  TagLines := TStringList.Create;
  InTag := False;
  InTagArea := False;
  Current := PChar(Lines.Text);
  try
    try
      while Current^ <> #0 do
      begin
        if (Current^ = '<') and ((Current + 1)^ in Letters + ['!','/']) then
        begin
          InTag := True;
          InTagArea := True;
          if (Current + 1)^ in Letters then
          begin
            TagKind := tagOpen;
            if Length(TagName) <> 0 then
            begin
              TagText := TagText + Current^;
            end;
            //-->
            Inc(Current);
            Continue;
          end;
          if ((Current + 1)^ = '!') and ((Current + 2)^ = '-') and ((Current + 3)^ = '-') then
          begin
            TagKind := tagComment;
            if Length(TagName) <> 0 then
            begin
              TagText := TagText + Current^ + (Current + 1)^ + (Current + 2)^ + (Current + 3)^;
            end;
            //-->
            Inc(Current,4);
            Continue;
          end;
          if ((Current + 1)^ = '/') and ((Current + 2)^ in Letters) then
          begin
            TagKind := tagClose;
            //-->
            Inc(Current,2);
            Continue;
          end;
        end;
        if InTagArea then
        begin
          if InTag then
          begin
            case TagKind of
              tagSingle,
              tagOpen: if (Current^ = '>') or ((Current^ = '/') and (Length(Trim(CurrentTag)) <> 0)) then
                       begin
                         if Length(CurrentTag) <> 0 then
                         begin
                           InTag := False;
                           if Length(TagName) = 0 then
                           begin
                             TagName := CurrentTag;
                           end else
                           begin
                             TagText := TagText + Current^;
                           end;
                           CurrentTag := '';
                           //Parse spaces and parameters .... (to be added)
                           if Current^ = '/' then
                           begin
                             TagKind := tagSingle;
                             if Length(TagText) <> 0 then
                             begin
                               TagText := TagText + Current^;
                             end;
                           end;
                           //-->
                           Inc(Current);
                           Continue;
                         end;
                       end else
                       begin
                         CurrentTag := CurrentTag + Current^;
                         if Length(TagName) <> 0 then
                         begin
                           TagText := TagText + Current^;
                         end;
                         //-->
                         Inc(Current);
                         Continue;
                       end;
              tagClose: if Current^ = '>' then
                        begin
                          if (Length(CurrentTag) <> 0) and (Length(TagName) <> 0) then
                          begin
                            InTag := False;
                            if TrimRight(CurrentTag) = TagName then
                            begin
                              InTagArea := False;
                              SetLength(FTags,Length(FTags) + 1);
                              TagLines.Text := TagText;
                              FTags[TagCount - 1] := THtmlDocumentTag.Create(TagName,Document,Self,TagLines);
                              if Assigned(Document.OnTagAdd) then
                              begin
                                Document.OnTagAdd(Self,FTags[TagCount - 1]);
                              end;
                              TagLines.Clear;
                              TagName := '';
                              TagText := '';
                            end else
                            begin
                              TagText := TagText + '</' + CurrentTag + '>';
                            end;
                            CurrentTag := '';
                            //-->
                            Inc(Current);
                            Continue;
                          end;
                        end else
                        begin
                          CurrentTag := CurrentTag + Current^;
                          //-->
                          Inc(Current);
                          Continue;
                        end;
              tagComment: if (Current^ = '-') and ((Current + 1)^ = '-') and ((Current + 2)^ = '>') then
                          begin
                            InTag := False;
                            TagText := TagText + Current^ + (Current + 1)^ + (Current + 2)^;
                            //-->
                            Inc(Current,3);
                            Continue;
                          end else
                          begin
                            TagText := TagText + Current^;
                            //-->
                            Inc(Current);
                            Continue;
                          end;
            end;
          end else
          begin
            TagText := TagText + Current^;
            //-->
            Inc(Current);
            Continue;
          end;
        end else
        begin
          FText := FText + Current^;
          //-->
          Inc(Current);
          Continue;
        end;
        raise EHtmlParse.Create('HTML parse error on line ' + IntToStr(CharLine(Current,Lines.Text)) + ' at position ' + IntToStr(CharPosition(Current,Lines.Text)));
      end;
      if InTagArea then
      begin
        SetLength(FTags,Length(FTags) + 1);
        TagLines.Text := TagText;
        FTags[TagCount - 1] := THtmlDocumentTag.Create(TagName,Document,Self,TagLines);
        if Assigned(Document.OnTagAdd) then
        begin
          Document.OnTagAdd(Self,FTags[TagCount - 1]);
        end;
      end;
    finally
      TagLines.Free;
    end;
  except
    raise;
  end;
end;

Uwe Raabe 17. Jan 2020 21:12

AW: replace string in text files
 
Ignoring the problems mentioned by Dennis07 regarding comments:
Delphi-Quellcode:
function ReplaceBetweenTags(const Source, TagStart, TagEnd, ReplaceWith: string): string;
var
  posEnd: Integer;
  posStart: Integer;
begin
  posStart := Source.IndexOf(TagStart) + TagStart.Length;
  posEnd := Source.IndexOf(TagEnd, posStart);
  Result := Source.Substring(0, posStart) + ReplaceWith + Source.Substring(posEnd);
end;

direktor 18. Jan 2020 05:55

AW: replace string in text files
 
Dalai text is different every time so I can't use stringreplace function. I was thinking of creating 2 TStringLists and put together the whole file 1. copy up from header + 2. header replacement + 3. copy rest of file... Dennis thanks, long solution but I'll try. Uwe - Sie sind genial! Thank you all.

Dalai 18. Jan 2020 13:49

AW: replace string in text files
 
Zitat:

Zitat von direktor (Beitrag 1455465)
Dalai text is different every time so I can't use stringreplace function.

See my EDIT. StringReplace can be used after determining the tags' offsets and getting the text via Copy function (using the previously determined offsets).

Regards
Dalai

direktor 18. Jan 2020 19:57

AW: replace string in text files
 
I have another problem, how to pass the Space in string?

For example I want to find string 'this is just a test' and replace it with 'this is not a test'. Problem is Delphi will find only first word 'this' - everything after space is ignored. How do I make it find full string not that it stops at space? Or I'm using Delphi version which is too low? Should I use Unicode string compare?

'this is something else' - delphi will find stop here because 'this' is contained here
'this is just a test' - but I want to change this line of text

How to do?

Luckie 18. Jan 2020 20:16

AW: replace string in text files
 
Please open a new topic for a new problem. Thank you.

TurboMagic 20. Jan 2020 21:00

AW: replace string in text files
 
Another question: why so people write in English in German
Delphi-Praxis Forum eben there is an english one available nie?

p80286 20. Jan 2020 22:39

AW: replace string in text files
 
Es könnte sein, daß sie einfach höflich sind und nicht platt auf die englische Version verweisen.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:20 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz