代码之家  ›  专栏  ›  技术社区  ›  robsoft

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

  •  2
  • robsoft  · 技术社区  · 15 年前

    我有一个文本文件,它会在我的申请表中出现以下几行:

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

    我想在给定的tstringlist中将这个“row”转换成一系列的名称/值对(可能有几十个这样的名称/值对) <第>行 在文件中,所以最终我将要遍历文件,依次将每一行分成名称/值对)。

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

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

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

    不幸的是,像通常这种情况一样,我对要开始的数据格式没有任何控制权-例如,我不能返回并在源代码处用逗号分隔。虽然我想我可以写一些代码把它转换成逗号分隔的-但我还是想找到一种很好的方法来处理我所拥有的东西。

    这将是在德尔福2007年,如果它有什么不同。

    2 回复  |  直到 15 年前
        1
  •  3
  •   gabr    15 年前
    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;
    
        2
  •  12
  •   Rob Kennedy    15 年前

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

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