2

我有一个文本文件到达我的应用程序,如下形式的多行:

<行金额="192.00" store="10" transaction_date="2009-10-22T12:08:49.640"
 comp_name="废话"
 comp_ref="C65551253E7A4589A54D7CCD468D8AFA"
 名称="阿克灵顿"/>

我想把这个“行”变成给定 TStringList 中的一系列名称/值对(文件中可能有几十个这样的<row>,所以最终我会想要遍历文件打破每个依次排列成名称/值对)。

我遇到的问题是数据没有明显分隔(从技术上讲,我想它是空格分隔的)。现在,如果不是因为某些值包含前导或尾随空格这一事实,我可能会做出一些合理的假设并编写一些代码来根据空格分解一行。但是由于值本身可能包含也可能不包含空格,因此我没有看到明显的方法来做到这一点。Delphi 的 TStringList.CommaText 没有帮助,我尝试过使用 Delimiter,但每次都会被值内的空格所吸引。

有没有人有一个聪明的德尔福技术将上面的样本变成类似的东西?;

金额="192.00"
商店="10"
transaction_date="2009-10-22T12:08:49.640"
comp_name="废话"
comp_ref="C65551253E7A4589A54D7CCD468D8AFA"
名称="阿克灵顿"

不幸的是,就像这种事情通常的情况一样,我无法控制一开始的数据格式 - 例如,我无法返回并在源代码处“制作”逗号分隔。尽管我想我可能会编写一些代码将其转换为逗号分隔 - 宁愿找到一种很好的方式来处理我所拥有的东西。

如果有什么不同的话,这将是在 Delphi 2007 中。

4

2 回答 2

12

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

如果您尝试解析 XML 而不考虑 XML 解析的细微差别,那么您迟早会被烧毁。

于 2010-05-03T15:34:39.853 回答
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;
于 2010-05-03T14:36:52.753 回答