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

发布于 2024-08-31 19:49:14 字数 1075 浏览 13 评论 0原文

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

<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 但每次都会被值内的空格所困扰。

有没有人有一个聪明的德尔菲技术可以将上面的示例变成类似这样的东西? ;

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

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

如果有什么区别的话,那就是 Delphi 2007 中的内容了。

I've got a text file that arrives at my application as many lines of the following form:

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

and I'd like to turn this 'row' into a series of name/value pairs in a given TStringList (there could be dozens of these <row>s in the file, so eventually I will want to iterate through the file breaking each row into name/value pairs in turn).

The problem I've got is that the data isn't obviously delimited (technically, I suppose it's space delimited). Now if it wasn't for the fact that some of the values contain leading or trailing spaces, I could probably make a few reasonable assumptions and code something to break a row up based on spaces. But as the values themselves may or may not contain spaces, I don't see an obvious way to do this. Delphi' TStringList.CommaText doesn't help, and I've tried playing around with Delimiter but I get caught-out by the spaces inside the values each time.

Does anyone have a clever Delphi technique for turning the sample above into something resembling this? ;

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

Unfortunately, as is usually the case with this kind of thing, I don't have any control over the format of the data to begin with - I can't go back and 'make' it comma delimited at source, for instance. Although I guess I could probably write some code to turn it into comma delimited - would rather find a nice way to work with what I have though.

This would be in Delphi 2007, if it makes any difference.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

数理化全能战士 2024-09-07 19:49:14

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

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

You say it's not "obviously delimited," but to me, it's very obviously delimited because it's very obviously XML. So use an XML parser. You could start with Delphi's TXmlDocument. You could pass each "row" string to the parser separately, but my suspicion is that all those rows are enclosed by some other angle-bracket tag. Feed that entire file to the parser, and it can help you get a list of objects representing rows, and then you can ask for the values of their attributes by name.

If you try to parse XML without regard to the nuances of XML parsing, sooner or later you're going to get burned.

习惯成性 2024-09-07 19:49:14
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;
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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文