Преобразование текста без разделителей в пары имя / значение в Delphi - PullRequest
2 голосов
/ 03 мая 2010

У меня есть текстовый файл, который поступает в мое приложение на столько строк следующего вида:

<row amount="192.00" store="10" transaction_date="2009-10-22T12:08:49.640"
 comp_name="blah                                            " 
 comp_ref="C65551253E7A4589A54D7CCD468D8AFA" 
 name="Accrington                                                  "/>

и я хотел бы превратить эту «строку» в серию пар имя / значение в заданном TStringList (в файле может быть несколько таких с, поэтому в итоге я захочет перебрать файл, разбив каждую строку на пары имя / значение по очереди).

Проблема, с которой я столкнулся, заключается в том, что данные явно не разграничены (технически, я полагаю, они разделены пробелами). Теперь, если бы не тот факт, что некоторые значения содержат начальные или конечные пробелы, я мог бы, вероятно, сделать несколько разумных предположений и написать что-то, чтобы разбить строку на основе пробелов. Но поскольку сами значения могут содержать или не содержать пробелы, я не вижу очевидного способа сделать это. Delphi 'TStringList.CommaText не помогает, и я попытался поэкспериментировать с Delimiter, но каждый раз меня ловят пробелы внутри значений.

Есть ли у кого-нибудь умная техника Delphi для превращения вышеприведенного образца во что-то похожее на это? ;

amount="192.00"
store="10"
transaction_date="2009-10-22T12:08:49.640"
comp_name="blah                                            " 
comp_ref="C65551253E7A4589A54D7CCD468D8AFA" 
name="Accrington                                                  "

К сожалению, как обычно бывает с такого рода вещами, я не имею никакого контроля над форматом данных для начала - я не могу вернуться и «сделать» запятую в источнике, так как пример. Хотя, наверное, я мог бы написать какой-нибудь код, чтобы превратить его в запятую, - хотя бы нашел хороший способ работать с тем, что у меня есть.

Это было бы в Delphi 2007, если это что-то меняет.

Ответы [ 2 ]

12 голосов
/ 03 мая 2010

Вы говорите, что это не "явно разграничено", но для меня, оно очень явно разграничено, потому что это очень очевидно XML Так что используйте парсер XML. Вы можете начать с Delphi's TXmlDocument. Вы можете передавать каждую строку «строки» парсеру отдельно, но я подозреваю, что все эти строки заключены в какой-то другой тег угловой скобки. Передайте весь этот файл анализатору, и он может помочь вам получить список объектов, представляющих строки, а затем вы можете запросить значения их атрибутов по имени.

Если вы попытаетесь проанализировать XML, не обращая внимания на нюансы синтаксического анализа XML, рано или поздно вы обожжетесь.

3 голосов
/ 03 мая 2010
procedure RowToStrings(const row: string; list: TStrings);
var
  i       : integer;
  iDelim  : integer;
  inQuotes: boolean;
begin
  iDelim := 0;
  inQuotes := false;
  for i := 1 to Length(row) do begin
    if (row[i] = ' ') and (not inQuotes) then begin
      list.Add(Copy(row, iDelim+1, i-iDelim-1));
      iDelim := i;
    end
    else if row[i] = '"' then
      inQuotes := not inQuotes;
  end;
  list.Add(Copy(row, iDelim+1, Length(row)-iDelim));
end;

procedure TForm37.Test;
var
  row: string;
begin
  row := 'amount="192.00" store="10" transaction_date="2009-10-22T12:08:49.640" ' +
         'comp_name="blah                                            " '          +
         'comp_ref="C65551253E7A4589A54D7CCD468D8AFA" '                           +
         'name="Accrington                                                  "';
  RowToStrings(row, ListBox1.Items);
end;
...