Преобразование текста без разделителей в пары имя / значение в Delphi

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

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

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

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

сумма ="192,00"
магазин = "10"
TRANSACTION_DATE = "2009-10-22T12: 08: 49,640"
comp_name = "бла" 
comp_ref = "C65551253E7A4589A54D7CCD468D8AFA" 
name = "Аккрингтон"

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

Это будет в Delphi 2007, если это будет иметь какое-либо значение.

2 ответа

Решение
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;

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

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

Другие вопросы по тегам