Convert non-delimited text to name / value pairs in Delphi

I have a text file that comes into 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 would like to include that string in a series of name / value pairs in a given TStringList (there can be dozens of these <row> s in the file , so eventually I will want to iterate through the file, breaking each line into name / value pairs in turn).

The problem is that the data is clearly unlimited (technically, I suppose this space is limited). Now, if it weren't for the fact that some of the values ​​contain leading or trailing spaces, I could probably make some reasonable assumptions and code to split the string based on spaces. But since the values ​​themselves may or may not contain spaces, I see no obvious way to do this. Delphi 'TStringList.CommaText doesn't help and I tried playing with Delimiter but every time I get missing spaces inside the values.

Does anyone have Delphi's clever method for turning the sample above into something similar to 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 have no control over the format of the data to begin with - I can't go back and "make" it a comma in the source, for example. Although I think I could write some code to turn it into a comma separator - I'd rather find a good way to work with what I have.

It will be in Delphi 2007 if it matters.

+2


a source to share


2 answers


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;

      



+3


a source


You say it's not "obviously limited", but it's very obviously limited to me because it's very obvious XML. So use an XML parser. You can start with Delphi TXmlDocument

. You can pass each line of the line to the parser separately, but my suspicion is that all of those lines are enclosed in some other angle bracket tag. Feed the whole file to a parser and it can help you get a list of objects representing strings, and then you can query the values ​​of their attributes by name.



If you try to parse XML without paying attention to the nuances of XML parsing, sooner or later you will burn yourself out.

+12


a source







All Articles