Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Паскаль, Turbo Pascal, PascalABC.NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.09.2015, 12:28   #1
dima4239
Пользователь
 
Регистрация: 30.09.2015
Сообщений: 11
По умолчанию подскажите с кодом: Напишите программу, принимающую на вход текстовый CSV-файл с таблицей и преобразующую эту таблицу в XML формат

Код:
unit Unit1;

interface

uses
    System, System.Collections.Generic, MyUnit;
 

type
  TfrmMain = class;
    xmldcmnt1= TXMLDocument;
    btnconvert= TButton;
    lbledtFilename= TLabeledEdit;
    btnOpen= TButton;
    dlgOpenCSV = TOpenDialog;
    lstXML= TListBox;
    procedure btnOpenClick(Sender: TObject);
    procedure btnconvertClick(Sender: TObject);   forward;
    { forward declarations }
    procedure ExtractData(Data: string; const Values: TStrings);
    function  XMLRecord(XMLParentNode: IXMLNode; RecordIndex: Cardinal; RecordHeader, RecordValues: TStrings): IXMLNode;
    procedure ConvertCSVToXML(CSVFile: TFileName; XMLDoc: TXMLDocument);
  forward;
    { Public declarations }
  const ;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.btnconvertClick(Sender: TObject);
begin
  lstXML.Clear;

  xmldcmnt1.Active := False; // Если изначально XML документ был открыт, то закрываем его
  ConvertCSVToXML(lbledtFilename.Text, xmldcmnt1); // Конвертируем CSV файл в XML

  lstXML.Items.Text := FormatXMLData(xmldcmnt1.XML.Text); // Выводим полученный XML файл с форматированием
  xmldcmnt1.SaveToFile('Result.xml'); // Сохраняем полученный XML файл
end;

procedure TfrmMain.btnOpenClick(Sender: TObject);
begin
  if dlgOpenCSV.Execute then begin
    lbledtFilename.Text := dlgOpenCSV.FileName;
  end;
end;

procedure TfrmMain.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); // Открываем файл CSV на чтение
  Reset(fCSV);
  if not Eof(fCSV) then begin
    XMLDoc.Active := True;
    // указываем начальную кодировку, для того чтобы русский текст отображался корректно в Delphi 7
    XMLDoc.Encoding := 'Windows-1251';
    // Создаем началььный узел XML документа
    XMLDoc.DocumentElement := XMLDoc.CreateNode('RECORDS');
    // Задаем отступ для каждого узла XML относительно родительского, если задать "", то отступа не будет
    XMLDoc.NodeIndentStr := '';
    XMLDoc.Options := [doNodeAutoCreate, doNodeAutoIndent];
    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);  // все остальные данные получаем как записи таблицы
      // Преобразуем эти данные в узел XML документа
    XMLRecord(XMLDoc.DocumentElement, iRecordIndex, slHeader, slRecord);
    Inc(iRecordIndex);
  end;
  CloseFile(fCSV);
  slHeader.Free;
  slRecord.Free;
end;

procedure TfrmMain.ExtractData(Data: string; const Values: TStrings);
var
  sData: string;
  iPos: Integer;
  sValue: AnsiString;
{ Процедура преобразует данные хранящиеся в строке с разделителем "," в список значений}
begin
 {Данный алгоритм будет работать в Delphi 2009 и выше для младших версий
  необходимо "вручную" разбирать данную строку и заполнять список}
  Values.Clear;
//  Values.LineBreak := ',';
//  Values.Text := Data;
  {Делаем разбор значений "вручную"}
  sData := Data;
  while Pos(',', sData) > 0 do begin // Раздилителем значений в строке является ","
    iPos := Pos(',', sData);
    sValue := LeftStr(sData, iPos - 1);
    Values.Add(Trim(sValue));
    Delete(sData, 1, iPos);
  end;
  sData := Trim(sData);
  if sData <> '' then // Добавляем последене значение
    Values.Add(sData);
end;

function TfrmMain.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;     // <RECORD id=”NN”>
  for i := 0 to RecordHeader.Count - 1 do begin
    XMLField := Result.AddChild('FIELD');       // Добавляем поля записи
    XMLField.Attributes['name'] := RecordHeader[i]; //<FIELD name=”Город” value=”Таганрог” />
    XMLField.Attributes['value'] := RecordValues[i];
  end;
end;

end.
Помогите разобраться, что не правильно?
dima4239 вне форума Ответить с цитированием
Старый 30.09.2015, 12:34   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

А как ведет себя программа?
Что не устраивает?
Отладку производил?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 30.09.2015, 13:16   #3
dima4239
Пользователь
 
Регистрация: 30.09.2015
Сообщений: 11
По умолчанию

Есть вот такое задание "Напишите программу, принимающую на вход текстовый CSV-файл, содержащий произвольную таблицу со значениями, разделенными запятой, и преобразующую содержание этого файла в XML формат. Первая строка CSV файла содержит названия полей. Следующий пример показывает принцип формирования выходного XML файла:

Вход:
Город, ТипУлицы, Улица
Таганрог, улица,Ленина
Ростов, улица,Б.Садовая
Москва,проспект,Жукова

Выход:
Код:
<RECORDS>
	<RECORD id=”1”>
		<FIELD name=”Город” value=”Таганрог” />
		<FIELD name=”ТипУлицы” value=”улица” />
		<FIELD name=”Улица” value=”Ленина” />
	<RECORD />
	<RECORD id=”2”>
		<FIELD name=”Город” value=”Ростов” />
		<FIELD name=”ТипУлицы” value=”улица” />
		<FIELD name=”Улица” value=”Б.Садовая” />
	<RECORD />
	<RECORD id=”3”>
		<FIELD name=”Город” value=”Москва” />
		<FIELD name=”ТипУлицы” value=”проспект” />
		<FIELD name=”Улица” value=”Жукова” />
	<RECORD />
</RECORDS>  "
Нужно по нему написать программу.
Ругается на ; после const пишет ожидается идентификатор.

Последний раз редактировалось Вадим Мошев; 30.09.2015 в 13:45.
dima4239 вне форума Ответить с цитированием
Старый 30.09.2015, 13:51   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Цитата:
Ругается на ; после const пишет ожидается идентификатор.
Правильно ругается. Откуда ты этот индокод выдрал?
Вместо const нужно ставить end.
И forward тут не к месту - убирай.

И еще: Я бы эту задачу решал двумя TStringList а не через TXMLDocument...
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 30.09.2015, 14:14   #5
dima4239
Пользователь
 
Регистрация: 30.09.2015
Сообщений: 11
По умолчанию

Цитата:
type
TfrmMain = class;
xmldcmnt1= TStringList;
btnconvert= TButton;
lbledtFilename= TLabeledEdit;
btnOpen= TButton;
dlgOpenCSV = TOpenDialog;
lstXML= TListBox;
procedure btnOpenClick(Sender: TObject);
procedure btnconvertClick(Sender: TObject);
{ forward declarations }
procedure ExtractData(Data: string; const Values: TStrings);
function XMLRecord(XMLParentNode: IXMLNode; RecordIndex: Cardinal; RecordHeader, RecordValues: TStrings): IXMLNode;
procedure ConvertCSVToXML(CSVFile: TFileName; XMLDoc: TXMLDocument);
{ Public declarations }
end;
Все равно просит вместо end написать forward.
С TStringList нужно переписывать класс?

Цитата:
Сообщение от Stilet Посмотреть сообщение
Правильно ругается. Откуда ты этот индокод выдрал?
Вот ссылка http://rfpro.ru/question/183230.

Последний раз редактировалось Stilet; 30.09.2015 в 14:42.
dima4239 вне форума Ответить с цитированием
Старый 30.09.2015, 14:47   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Цитата:
Все равно просит вместо end написать forward.
Потому что ты все сделал неправильно.
Я даже не знаю как сказать, но твой проект нужно целиком выбросить.
Создать новый. Накидать на него компонентов...
Вот это:
Цитата:
TfrmMain = class;
xmldcmnt1= TStringList;
btnconvert= TButton;
какая-то странная ересь...
Наверное должно было выглядеть как
Код:
TfrmMain = class(TForm)
 btnconvert:TButton;
 lbledtFilename:TLabeledEdit;
 btnOpen:TButton;
 dlgOpenCSV:TOpenDialog;
 lstXML:TListBox;
 procedure btnOpenClick(Sender: TObject);
 procedure btnconvertClick(Sender: TObject); 
 procedure ExtractData(Data: string; const Values: TStrings);
 function XMLRecord(XMLParentNode: IXMLNode; RecordIndex: Cardinal; RecordHeader, RecordValues: TStrings): IXMLNode;
 procedure ConvertCSVToXML(CSVFile: TFileName; XMLDoc: TXMLDocument);
public
{ Public declarations }
 xmldcmnt1:TStringList;
end;
...
Ты похоже вручную решил описать код класса не зная как именно это делать правильно.
Переделай проект наново с нуля.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 30.09.2015, 15:00   #7
dima4239
Пользователь
 
Регистрация: 30.09.2015
Сообщений: 11
По умолчанию

Можешь объяснить алгоритм, как нужно сделать?
dima4239 вне форума Ответить с цитированием
Старый 30.09.2015, 15:18   #8
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Могу.
С помошью функции:
Код:
procedure CSVtoXML(aFrom,aTo:String);
var f,t,s:TStringList; i:integer;
begin
 f:=TStringList.Create(); t:=TStringList.Create(); s:=TStringList.Create();
 f.LoadFromFile(aFrom); s.Delimiter:=',';
 t.Append('<RECORDS>');
 for i:=1 to f.count-1 do begin
  s.DelimitedText:=f[i];
  t.Append('     <RECORD id=”'+IntToStr(i)+'”>');
  t.Append('         <FIELD name=”Город” value=”'+s[0]+'” />');
  t.Append('         <FIELD name=”ТипУлицы” value=”'+s[1]+” />');
  t.Append('         <FIELD name=”Улица” value=”'+s[2]+” />');
  t.Append('     </RECORD>');
 end;
 t.Append('</RECORDS>');
 t.SaveToFile(aTo);
 f.free; t.free;
end;
В нее передаются имя исходного и результирующего файлов.
Единственное что нужно уточнить в твоей Делфи Delimiter будет ли реагировать на пробелы или нет. Если да - нужно менять s.DelimitedText:=f[i]; на что-то типа
Код:
s.Text:=StringReplace(f[i],',',#13#10,[rfReplaceAll]);
Идею усек?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 30.09.2015, 15:24   #9
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

Виталий, согласен, я бы тоже обошёлся без XML-ware компонент (если, конечно, их использование не обязательно по заданию!).
Но хочу заметить, что в задании идёт речь про
Цитата:
CSV-файл, содержащий произвольную таблицу со значениями
нужно прочитать имена полей в отдельный массив/лист и брать имена полей оттуда во вложенном цикле.
а в остальном с идеей алгоритма согласен.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 30.09.2015, 15:30   #10
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Цитата:
нужно прочитать имена полей в отдельный массив/лист и брать имена полей оттуда во вложенном цикле.
Пусть автор хотя бы осилит "накидывание компонентов на форму"
У него уже тут хромает правильнописание. Оно может быть хорошее, но почему-то хромает
I'm learning to live...
Stilet вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Открыть csv файл при помощи opendialog и загрузить в таблицу Evdoz C# (си шарп) 1 28.05.2015 18:48
плохо соображаю в qbesic ` е, подскажите как написать эту программу Vlad0697 Помощь студентам 0 16.05.2014 11:31
работа с БД - записывать действия с таблицей через DBNavigator в текстовый файл Света12 Общие вопросы Delphi 2 16.05.2012 09:32
Написать программу, преобразующую файл *.csv в файл *.xls Lamer_ok Фриланс 1 17.12.2011 14:24
Написать программу, преобразующую файл АВС.ТХТ в файл 123.ТХТ [Паскаль] Djoker Помощь студентам 1 12.12.2010 19:45