在Delphi中将非分隔文本转换为名称/值对

时间:2010-05-03 14:06:30

标签: delphi string name-value

我有一个文本文件到达我的应用程序,其格式如下:

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

我想把这个'row'变成给定TStringList中的一系列名称/值对(文件中可能有几十个&lt; row&gt; ,所以最终我想要遍历文件,依次将每一行分成名称/值对。

我遇到的问题是数据没有明显的分隔(从技术上讲,我认为它是以空格分隔的)。现在,如果不是因为某些值包含前导或尾随空格这一事实,我可能会做出一些合理的假设并编写一些代码来基于空格来划分一行。但由于价值本身可能包含或不包含空格,我没有看到明显的方法来做到这一点。 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                                                  "

不幸的是,通常就是这种情况的情况,我对数据的格式没有任何控制权 - 我不能回过头来'make'以逗号分隔来源,因为实例。虽然我想我可能会编写一些代码来将其转换为逗号分隔 - 但我宁愿找到一种很好的方式来处理我的工作。

这将在Delphi 2007中,如果它有任何区别。

2 个答案:

答案 0 :(得分:12)

你说它不是“明显划界”,但对我而言,非常显然是划界的,因为它非常明显是XML。所以使用XML解析器。你可以从Delphi的TXmlDocument开始。您可以将每个“行”字符串分别传递给解析器,但我怀疑所有这些行都被其他一些角括号标记包围。将整个文件提供给解析器,它可以帮助您获取表示行的对象列表,然后您可以按名称请求其属性的值。

如果你试图解析XML而不考虑XML解析的细微差别,迟早你会被烧毁。

答案 1 :(得分:3)

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;