Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Парсер HTML-символов. Парсер html-спец-символов (не тегов!) 
:(
    Опции темы
vtih
Дата 31.1.2007, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 2.12.2006

Репутация: нет
Всего: нет



    Смысл таков -- есть текст который сосотит например таким образом:

Цитата
"&me&my<brother founded mmm &amp m&m's; and &#123 we... - go! go & still...


    А выглядеть он должен так:

Цитата
"&me&my<brother founded mmm & m&m's; and { we - go! & & still...


    Вобщем нужен очень корректный парсер, который бы обходил все возможные ложные конструкуции и мог обработать конструкции с кодом числа, аля 
Код
& #123;

    Я попытался эту штуку реализовать, но честно скажу, голова просто закипела. Помогите пожалуйста! 

Код

function xHTML2Char(const s: string): Char;
begin
  Result := #0;
  if s = 'quot'   then Result := '"' else
  if s = 'amp'     then Result := '&' else
  if s = 'lt'     then Result := '<' else
  if s = 'gt'     then Result := '>' else
  if s = 'nbsp'   then Result := #32 else
  if s = 'iexcl'  then Result := '?';
  //.....................................
end;

function xHTML2Text(const xHTML: string): string;
var
  i, j: Integer;
  setPos: Boolean;
  srcHTML: string;
  e, q: Integer;
  xHTMLChar: string;
begin
  srcHTML := xHTML;
  SetLength(Result, Length(xHTML));
  i := 0; j := 0;
  e := 0; q := 0;
  xHTMLChar := #0;
  
  repeat
    Inc(i);
    setPos := False;
    if srcHTML[i] = '&' then
    begin
      j := i;
      repeat
        if srcHTML[j] = ';' then
        begin
          setPos := True;
          xHTMLChar := Copy(srcHTML, i + 1, j - i - 1);
          ShowMessage(xHTMLChar);
          if xHTMLChar[1] = '#' then
          begin
            //todo: advanced int check, -- TryStrToInt.
            xHTMLChar := Chr(StrToInt(Copy(xHTMLChar, 2, Length(xHTMLChar) - 1)));
          end else
          begin
            xHTMLChar := xHTML2Char(xHTMLChar);
            if xHTMLChar <> #0 then
            begin
              Inc(e);
              Result[e] := xHTMLChar[1];
              i := j + 1;
            end else
            begin
            //for q := i to j do
            //begin
              //ShowMessage('llllllllll');
              Inc(e);
              Result[e] := srcHTML[i];
            //end;
          end;
          end;
          //i := j;
        end;
        Inc(j);
      until j = Length(srcHTML);
      if setPos = False then
      begin
        Inc(e);
        Result[e] := srcHTML[i]; 
      end;
    end else
    begin
      Inc(e);
      Result[e] := srcHTML[i];
    end;
  until i >= Length(srcHTML);

  SetLength(Result, e);
end;



Может есть готовые решения, которые хорошо справяться с моей задачей?
PM MAIL   Вверх
W4FhLF
Дата 31.1.2007, 21:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 6
Всего: 121



Регулярные выражения используй. 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
CatATonik
Дата 1.2.2007, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 12.1.2007
Где: Москва

Репутация: 6
Всего: 8



Мне тоже такое скоро понадобится, поэтому сделал smile, немного черезчур, но работает:

Код

unit HTMLCharsCls;

interface

uses SysUtils, Classes;

type
  THTMLChar = record
    Tag: string;
    Char: WideChar;
  end;

  PHTMLCharArray = ^THTMLCharArray;
  THTMLCharArray = array[0..MaxInt div SizeOf(THTMLChar) - 1] of THTMLChar;

  THTMLChars = class
  private
    FCapacity: Integer;
    FCount: Integer;
    FList: PHTMLCharArray;
    function GetChar(Index: Integer): WideChar;
    function GetMap(const Tag: string): WideChar;
    function GetTag(Index: Integer): string;
  protected
    function  Add(const Tag: string; Char: WideChar): Integer;
    procedure Clear;
    procedure Delete(Index: Integer);
    procedure Init;
  public
    constructor Create;
    destructor Destroy; override;
    function  Find(const Tag: string; var Index: Integer): Boolean;
    property  Count: Integer read FCount;
    property  Map[const Tag: string]: WideChar read GetMap; default;
    property  Tags[Index: Integer]: string read GetTag;
    property  Chars[Index: Integer]: WideChar read GetChar;
  end;

  function ReplaceHTMLChars(const S: WideString): WideString;

var
  HTMLChars: THTMLChars;

implementation

const
  MaxTagLength = 15;
  WideNull = WideChar(#0);
  WideAmp  = WideChar('&');
  WideSep  = WideChar(';');

function ReplaceHTMLChars(const S: WideString): WideString;
var
  I, L: Integer;
  Tag: WideString;
  Ch: WideChar;
begin
  Result := '';
  I := 1;
  L := 1;
  while I <= Length(S) do
  begin
    if S[I] = WideAmp then
    begin
      if I > L then
      begin
        Result := Result + Copy(S, L, I - L);
        L := I;
      end;
      Inc(I);
      while (I <= Length(S)) and ((I - L) < MaxTagLength) do
      begin
        if S[I] = WideSep then
        begin
          Tag := Copy(S, L + 1, I - L - 1);
          Ch := HTMLChars[Tag];
          if Ch > #0 then
          begin
            Result := Result + Ch;
            L := I + 1;
          end;
          Break;
        end
        else if S[I] = WideAmp then
        begin
          Dec(I);
          Break;
        end;
        Inc(I);
      end;
    end;
    Inc(I);
  end;
  if I > L then
    Result := Result + Copy(S, L, I - L);
end;

{ THTMLChars }

constructor THTMLChars.Create;
begin
  FList := nil;
  FCapacity := 0;
  FCount := 0;
  Init;
end;

destructor THTMLChars.Destroy;
begin
  FreeMem(FList);
  FList := nil;
  FCount := 0;
  FCapacity := 0;
  inherited;
end;

procedure THTMLChars.Init;
begin
  Add('amp'   , #38);
  Add('gt'    , #62);
  Add('lt'    , #60);
  Add('quot'  , #34);
  Add('AElig' , #198);
  Add('Aacute', #193);
  Add('Acirc' , #194);
  Add('Agrave', #192);
  Add('Aring' , #197);
  Add('Atilde', #195);
  Add('Auml'  , #196);
  Add('Ccedil', #199);
  Add('ETH'   , #208);
  Add('Eacute', #201);
  Add('Ecirc' , #202);
  Add('Egrave', #200);
  Add('Euml'  , #203);
  Add('Iacute', #205);
  Add('Icirc' , #206);
  Add('Igrave', #204);
  Add('Iuml'  , #207);
  Add('Ntilde', #209);
  Add('Oacute', #211);
  Add('Ocirc' , #212);
  Add('Ograve', #210);
  Add('Oslash', #216);
  Add('Otilde', #213);
  Add('Ouml'  , #214);
  Add('THORN' , #222);
  Add('Uacute', #218);
  Add('Ucirc' , #219);
  Add('Ugrave', #217);
  Add('Uuml'  , #220);
  Add('Yacute', #221);
  Add('aacute', #225);
  Add('acirc' , #226);
  Add('acute' , #180);
  Add('aelig' , #230);
  Add('agrave', #224);
  Add('aring' , #229);
  Add('atilde', #227);
  Add('auml'  , #228);
  Add('brvbar', #166);
  Add('ccedil', #231);
  Add('cedil' , #184);
  Add('cent'  , #162);
  Add('copy'  , #169);
  Add('curren', #164);
  Add('deg'   , #176);
  Add('divide', #247);
  Add('eacute', #233);
  Add('ecirc' , #234);
  Add('egrave', #232);
  Add('eth'   , #240);
  Add('euml'  , #235);
  Add('euro'  , #8364);
  Add('frac12', #189);
  Add('frac14', #188);
  Add('frac34', #190);
  Add('iacute', #237);
  Add('icirc' , #238);
  Add('iexcl' , #161);
  Add('igrave', #236);
  Add('iquest', #191);
  Add('iuml'  , #239);
  Add('macr'  , #175);
  Add('micro' , #181);
  Add('middot', #183);
  Add('not'   , #172);
  Add('ntilde', #241);
  Add('oacute', #243);
  Add('ocirc' , #244);
  Add('ograve', #242);
  Add('ordf'  , #170);
  Add('ordm'  , #186);
  Add('oslash', #248);
  Add('otilde', #245);
  Add('ouml'  , #246);
  Add('para'  , #182);
  Add('plusmn', #177);
  Add('pound' , #163);
  Add('reg'   , #174);
  Add('sect'  , #167);
  Add('shy'   , #173);
  Add('sup1'  , #185);
  Add('sup2'  , #178);
  Add('sup3'  , #179);
  Add('szlig' , #223);
  Add('thorn' , #254);
  Add('times' , #215);
  Add('trade' , #8482);
  Add('uacute', #250);
  Add('ucirc' , #251);
  Add('ugrave', #249);
  Add('uml'   , #168);
  Add('uuml'  , #252);
  Add('yacute', #253);
  Add('yen'   , #165);
  Add('yuml'  , #255);
  Add('bdquo' , #8222);
  Add('bull'  , #8226);
  Add('emsp'  , #8195);
  Add('ensp'  , #8194);
  Add('laquo' , #171);
  Add('ldquo' , #8220);
  Add('lsaquo', #8249);
  Add('lsquo' , #8216);
  Add('mdash' , #8212);
  Add('nbsp'  , #160);
  Add('ndash' , #8211);
  Add('raquo' , #187);
  Add('rdquo' ,  #8221);
  Add('rsaquo', #8250);
  Add('rsquo' , #8217);
  Add('sbquo' , #8218);
end;

function  THTMLChars.Add(const Tag: string; Char: WideChar): Integer;
begin
  if Find(Tag, Result) then
    Result := -1
  else
  begin
    if FCount = FCapacity then
    begin
      Inc(FCapacity, 16);
      ReallocMem(FList, FCapacity * SizeOf(THTMLChar));
    end;

    if Result < FCount then
      Move(FList^[Result], FList^[Result + 1], (FCount - Result) * SizeOf(THTMLChar));

    Pointer(FList^[Result].Tag) := nil;
    FList^[Result].Char := Char;
    FList^[Result].Tag := LowerCase(Tag);

    Inc(FCount);
  end;
end;

procedure THTMLChars.Clear;
begin
  FreeMem(FList);
  FList := nil;
  FCount := 0;
  FCapacity := 0;
end;

procedure THTMLChars.Delete(Index: Integer);
begin
  Finalize(FList^[Index]);
  Dec(FCount);
  if Index < FCount then
    Move(FList^[Index + 1], FList^[Index], (FCount - Index) * SizeOf(THTMLChar));
end;

function THTMLChars.Find(const Tag: string; var Index: Integer): Boolean;
var
  L, H, I, C: Integer;
begin
  Result := False;
  L := 0;
  H := FCount - 1;
  while L <= H do
  begin
    I := (L + H) shr 1;
    C := CompareText(FList^[I].Tag, Tag);
    if C < 0 then
      L := I + 1
    else
    begin
      H := I - 1;
      if C = 0 then
      begin
        Result := True;
        L := I;
      end;
    end;
  end;
  Index := L;
end;

function THTMLChars.GetChar(Index: Integer): WideChar;
begin
  Result := FList[Index].Char;
end;

function THTMLChars.GetMap(const Tag: string): WideChar;
var
  Index: Integer;
begin
  if Find(Tag, Index) then
    Result := FList[Index].Char
  else
    Result := #0;
end;

function THTMLChars.GetTag(Index: Integer): string;
begin
  Result := FList[Index].Tag;
end;

initialization
  HTMLChars := THTMLChars.Create;

finalization
  HTMLChars.Free;


end.


PM MAIL   Вверх
Romkin
Дата 2.2.2007, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 189
Регистрация: 14.11.2006
Где: Москва

Репутация: 2
Всего: 5



Велосипед изобретаете?
В HTTPApp.pas есть функция HTMLDecode. Название ничего не говорит? smile
PM ICQ   Вверх
CatATonik
Дата 2.2.2007, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 12.1.2007
Где: Москва

Репутация: 6
Всего: 8



ага, которая декодит только четыре символа smile
PM MAIL   Вверх
Romkin
Дата 2.2.2007, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 189
Регистрация: 14.11.2006
Где: Москва

Репутация: 2
Всего: 5



А дописать? smile
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0770 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.