Вопрос № 183230: Уважаемые эксперты! Пожалуйста, ответьте на вопрос: Нужно написать программу, принимающую на вход текстовый CSV-файл, содержащий произвольную таблицу со значениями, разделенными запятой, и преобразующую содержание этого файла в XML формат. Первая ...
Вопрос № 183230:
Уважаемые эксперты! Пожалуйста, ответьте на вопрос: Нужно написать программу, принимающую на вход текстовый CSV-файл, содержащий произвольную таблицу со значениями, разделенными запятой, и преобразующую содержание этого файла в XML формат. Первая строка CSV файла содержит названия полей. Следующий пример показывает принцип формирования выходного XML файла:
Вход: Город, ТипУлицы, Улица Таганрог, улица,Ленина Ростов, улица,Б.Садовая Москва,проспект,Жукова
P.S. Сделал так чтобы csv файл читался и данные попадали в StringGrid,потом логически понимаю что нужно построить структуру xml файла и из StringGrid выгрузить в xml,но как это сделать я не знаю...с xml никогда не работал,помогите пожалуйста Возможно и не надо помещать данные в StringGrid,если правильно
понимаю то память тратится в пустую...
Отвечает Киселёва Алёна aka Verena (Профессор) :
Здравствуйте, angel.nero! Поскольку Striker Loner пропал, отвечаю на основании его ответа из мини-форума. Совсем не обязательно грузить данный файл в StringGrid.
Алгоритм работы будет такой: 1. Пока не кончились строки, делаем. 2. Получаем строку из файла. 3. Преобразуем её в список значений. 4. Если это самая первая строка, то принимаем её за заголовки и идем на 2. 5. Формируем узел XML файла.
Код :
procedure ExtractData(Data: string; const Values: TStrings);
{ Процедура преобразует данные хранящиеся в строке с разделителем "," в список значений}
begin
{Данный алгоритм будет работать в Delphi 2009 и выше для младших версий
необходимо "вручную" разбирать данную строку и заполнять список}
Values.Clear;
Values.LineBreak := ',';
Values.Text := Data;
end;
function XMLRecord(XMLParentNode: IXMLNode; RecordIndex: Cardinal;
RecordHeader, RecordValues: TStrings): IXMLNode;
{ функция возвращает ссылку на ужел в основном XML документе для данной записи
XMLParentNode - корневой узел XML документа
RecordIndex - порядковый новер записи
RecordHeader - заголовок записи
RecordValues - значения записи}
var
XMLField: IXMLNode;
i: Integer;
begin
if RecordHeader.Count <> RecordValues.Count then begin
Result := nil;
Exit;
end;
Result := XMLParentNode.AddChild('RECORD');
Result.Attributes['id'] := RecordIndex;
for i := 0 to RecordHeader.Count - 1 do begin
XMLField := Result.AddChild('FIELD');
XMLField.Attributes['name'] := RecordHeader[i];
XMLField.Attributes['value'] := RecordValues[i];
end;
end;
procedure ConvertCSVToXML(CSVFile: TFileName; XMLDoc: TXMLDocument);
{ Процедура преобразует входящий CSVFile в XML документ}
var
fCSV: TextFile;
sData: string;
slHeader: TStringList;
slRecord: TStringList;
iRecordIndex: Cardinal;
begin
slHeader := TStringList.Create;
slRecord := TStringList.Create;
AssignFile(fCSV, CSVFile);
Reset(fCSV);
if not Eof(fCSV) then begin
XMLDoc.Active := True;
XMLDoc.DocumentElement := XMLDoc.CreateNode('RECORDS');
iRecordIndex := 0;
end;
while not Eof(fCSV) do begin
Readln(fCSV, sData);
if iRecordIndex = 0 then begin
Inc(iRecordIndex);
ExtractData(sData, slHeader);
Continue;
end;
ExtractData(sData, slRecord);
XMLRecord(XMLDoc.DocumentElement, iRecordIndex, slHeader, slRecord);
Inc(iRecordIndex);
end;
CloseFile(fCSV);
slHeader.Free;
slRecord.Free;
end;
procedure TForm1.btnconvertClick(Sender: TObject);
begin
lstXML.Clear;
xmldcmnt1.Active := False;
ConvertCSVToXML(lbledtFilename.Text, xmldcmnt1);
lstXML.Items.Text := FormatXMLData(xmldcmnt1.XML.Text);
end;
Во вложении лежит оттестированый проект в Delphi 2010/2006 (должен пойти и на 7) с комментариями к каждой функции, за исключением ExtractData (там и так все должно быть понятно). Теперь XML документ формируется в кодировке Windows-1251, поэтому должен нормально отображаться в Delphi 7/2006/2010. Документ форматируется в ListBox'е для удобства чтения и оценки результата. Как необходимо форматировать документ, описано в процедуре конвертирования, поэтому сохраняемый
файл будет в нужном форматировании и кодировке.
Прикрепленный файл:загрузить »
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.