Форум программистов, компьютерный форум, киберфорум
Delphi
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.81/135: Рейтинг темы: голосов - 135, средняя оценка - 4.81
0 / 0 / 0
Регистрация: 10.04.2012
Сообщений: 3

Программа редактирования XML - документа

10.04.2012, 12:54. Показов 25688. Ответов 21

Студворк — интернет-сервис помощи студентам
Необходимо написать программу на delphi, позволяющую редактировать дерево xml-документа
Буду очень благодарна за вашу помощь!
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
10.04.2012, 12:54
Ответы с готовыми решениями:

Программа редактирования XML документа
Всем добрый вечер. Имеется задача, написать XML парсер следующего типа. Пока нет конца документа выполнять: найти значение x, сравнить x и...

Обработка XML документа с использованием MSXML
Доброе утро. Получают xml-документ в качестве ответа на запрос var zapros:thttpsend; xml: TXMLDocument; begin ...

Добавить на форме редактирования отдельную кнопку для редактирования должностей
Народ нужна помощь кто может добавить на форме редактирования кнопку редактирования должностей отдельную то есть добавление удаление...

21
 Аватар для Mawrat
13114 / 5895 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
10.04.2012, 15:28
Могу предложить строить программу на двух компонентах - TXMLDocument (закладка Internet в палитре компонентов) и TTreeView (закладка Win32). С помощью компонента TXMLDocument читать/изменять XML документ, а с помощью TTreeView показывать древовидную структуру документа.
0
0 / 0 / 0
Регистрация: 10.04.2012
Сообщений: 3
10.04.2012, 15:44  [ТС]
А вы можете написать код? а то так сразу сходу непонятно
0
0 / 0 / 0
Регистрация: 10.04.2012
Сообщений: 3
10.04.2012, 19:00  [ТС]
Вот файл:
работа xml.docx
0
 Аватар для Mawrat
13114 / 5895 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
11.04.2012, 02:17
Лучший ответ Сообщение было отмечено как решение

Решение

О проекте.
На форме имеем:
1. TXMLDocument - для работы с DOM моделью XML документа.
2. TTreeView - для графического представления XML документа в виде дерева узлов.
3. TStringGrid - для показа атрибутов XML узла.
4. TOpenDialog - для выбора файла.
5. TButton - для запуска диалога открытия файла.
Я сейчас реализовал следующее. XML документ загружаем в TXMLDocument. Затем, рекурсивно обходим все узлы XML документа и для каждого такого узла создаём соответствующий узел в дереве TTreeView. К каждому узлу TTreeView прикрепляем ссылку на интерфейс соответствующего XML узла. Для TTreeView определяем обработчик события OnChange. - Это событие происходит в момент, когда произошёл выбор нового узла в дереве. В этом обработчике из данных узла дерева извлекаем ссылку на интерфейс соответствующего XML узла и в TStringGrid показываем сведения о всех атрибутах этого XML узла.
Здесь реализованы основные механизмы по загрузке данных, построению дерева, по связыванию и освобождению данных. Во время работы, через любой узел дерева мы имеем доступ к интерфейсу соответствующего XML узла.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, xmldom, XMLIntf, StdCtrls, msxmldom, XMLDoc, ComCtrls, Grids;
 
type
  TForm1 = class(TForm)
    XMLDocument1: TXMLDocument;
    TreeView1: TTreeView;
    StringGrid1: TStringGrid;
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
type
  TPXmlNode = ^IXMLNode;
 
//Удаление ссылок ни интерфейсы XML узлов и освобождение памяти, занятой под
//контейнеры типа TPXmlNode.
//И удаление узлов дерева.
procedure ClearTreeData(aTree : TTreeView);
var
  TreeNode : TTreeNode;
  PXmlNode : TPXmlNode;
  i : Integer;
begin
  if aTree = nil then Exit;
 
  //Перебираем все узлы дерева и удаляем связанные с ними ссылки на интерфейсы XML узлов.
  for i := 0 to aTree.Items.Count - 1 do begin
    TreeNode := aTree.Items[i];
    PXmlNode := TPXmlNode(TreeNode.Data);
    //Удаление из памяти контейнера типа TPXmlNode. При этом, автоматически удаляется
    //ссылка на интерфейс XML узла ( Finalize(TPXmlNode(TreeNode.Data)^) ).
    if PXmlNode <> nil then Dispose( TPXmlNode(TreeNode.Data) );
  end;
  //
  aTree.Items.Clear;
end;
 
//Процедура построена по рекурсивному алгоритму.
//Предназначена для перебора всех XML узлов поддерева с корнем в aXmlNode.
//Для текущего XML узла создаётся соответствующий узел в TTreeView.
//Ссылка на интерфейс XML узла прикрепляется в качестве данных к созданному узлу дерева.
//Для всех дочерних XML узлов выполняется рекурсивный вызов ProcXmlNode().
procedure ProcXmlNode(aXmlNode : IXMLNode; aTree : TTreeView; aTreeNode : TTreeNode);
var
  NewTreeNode : TTreeNode;
  PXmlNode : TPXmlNode;
  i : Integer;
begin
  //Создаём новый узел дерева.
  NewTreeNode := TTreeNode.Create(aTree.Items);
  //Создаём контейнер для хранения ссылки на интерфейс XML узла.
  New(PXmlNode);
  //Записываем в контейнер ссылку на интерфейс XML узла.
  PXmlNode^ := aXmlNode;
  //Добавляем узел в дерево. И прикрепляем к узлу указатель на контейнер, в котором
  //хранится ссылка на интерфейс соответствующего XML узла.
  if aTreeNode = nil then
    NewTreeNode := aTree.Items.AddNode(NewTreeNode, aTreeNode, aXmlNode.NodeName,
      PXmlNode, naAdd) //Узел верхнего уровня.
  else
    NewTreeNode := aTree.Items.AddNode(NewTreeNode, aTreeNode, aXmlNode.NodeName,
      PXmlNode, naAddChild) //Дочерний узел.
  ;
  //Для дочерних XML узлов выполняем рекурсивный вызов ProcXmlNode().
  for i := 0 to aXmlNode.ChildNodes.Count - 1 do
    ProcXmlNode(aXmlNode.ChildNodes[i], aTree, NewTreeNode)
  ;
end;
 
//Загрузка XML документа и построение дерева.
procedure TForm1.Button1Click(Sender: TObject);
var
  Od : TOpenDialog;
  XmlDoc : TXMLDocument;
  XmlNodeDoc : IXMLNode;
  Tree : TTreeView;
begin
  Tree := TreeView1;
  XmlDoc := XMLDocument1;
  Od := OpenDialog1;
  if Od.InitialDir = '' then
    Od.InitialDir := ExtractFilePath(Application.ExeName)
  ;
  if not Od.Execute then Exit;
  if not FileExists(Od.FileName) then begin
    ShowMessage('Файл с заданным именем не существует. Действие отменено.');
    Exit;
  end;
 
  //Удаление текущего дерева.
  ClearTreeData(TreeView1);
  //Загрузка нового XML документа.
  XmlDoc.LoadFromFile(Od.FileName);
 
  //Корневой узел (узел документа).
  XmlNodeDoc := XmlDoc.DocumentElement;
  //Построение дерева.
  ProcXmlNode(XmlNodeDoc, Tree, nil);
end;
 
//Если выбор (выделение) перешол на узел Node.
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
var
  XmlNode, AttrNode : IXMLNode;
  Sg : TStringGrid;
  i, Row, CntRow : Integer;
begin
  Sg := StringGrid1;
  //Получаем ссылку на интерфейс соответствующего XML узла.
  XmlNode := TPXmlNode(Node.Data)^;
  //Очищаем таблицу.
  for Row := Sg.FixedRows to Sg.RowCount - 1 do Sg.Rows[Row].Clear;
  //Устанавливаем количество строк таблицы, в соответствие с количеством атрибутов
  //XML узла.
  CntRow := Sg.FixedRows + XmlNode.AttributeNodes.Count;
  if XmlNode.IsTextElement then Inc(CntRow);
  if XmlNode.NodeType = ntText then Inc(CntRow);
  //Общее количество строк в таблице должно быть всегда больше
  //количества фиксированных строк (так устроен TStringGrid).
  if CntRow = Sg.FixedRows then Inc(CntRow);
  //Устанавливаем вычисленное количество строк.
  Sg.RowCount := CntRow;
  //Индекс первой нефиксированной строки.
  Row := Sg.FixedRows;
  //Если узел является текстовым или содержит простой текст.
  if (XmlNode.NodeType = ntText) or XmlNode.IsTextElement then begin
    Sg.Cells[0, Row] := XmlNode.NodeName;
    Sg.Cells[1, Row] := XmlNode.NodeValue;
    Inc(Row);
  end;
  //Перебираем все узлы атрибутов XML узла и сведения об этих узлах
  //записываем в таблицу.
  for i := 0 to XmlNode.AttributeNodes.Count - 1 do begin
    AttrNode := XmlNode.AttributeNodes.Get(i);
    Sg.Cells[0, Row] := AttrNode.NodeName;
    Sg.Cells[1, Row] := AttrNode.NodeValue;
    Inc(Row); //Индекс следующей строки в таблице.
  end;
end;
 
//Действия при создании формы.
procedure TForm1.FormCreate(Sender: TObject);
var
  Sg : TStringGrid;
begin
  Sg := StringGrid1;
  Sg.ColWidths[0] := 150;
  if Sg.ClientWidth > 150 then
    Sg.ColWidths[1] := Sg.ClientWidth - 150
  else
    Sg.ColWidths[1] := 150
  ;
  Sg.Cells[0, 0] := 'Атрибут';
  Sg.Cells[1, 0] := 'Значение';
end;
 
//При уничтожении формы, удаляем данные, связанные с узлами дерева.
procedure TForm1.FormDestroy(Sender: TObject);
begin
  ClearTreeData(TreeView1);
end;
 
end.
В папке с проектом имеется вложенная папка "XML-Files" - там, для примера, несколько файлов XML документов.
---
Софья222, эту программу можешь взять, в качестве основы. Сначала попытайся разобраться в коде этого проекта. А затем, следующим этапом, тебе нужно будет добавить в проект действия по редактированию XML данных. Основа для этого создана - узлы дерева содержат ссылки на интерфейсы соответствюущих XML узлов. Через эти интерфейсы можно изменять/добавлять/удалять параметры и сами XML узлы.
Цитата Сообщение от Софья222 Посмотреть сообщение
Вот файл:
работа xml.docx
В XML коде, который представлен в этом документе, надо немного изменить заголовок.
Заменить:
XML
1
2
<?xml version='1.0' standalone='yes'?>
<?xml-stylesheet type="text/xsl" href="rabota_to_json.xsl"?>
на:
XML
1
<?xml version='1.0' encoding="windows-1251" standalone='yes'?>
и сохранить в кодировке ANSI (windows-1251).
Или заменить на:
XML
1
<?xml version='1.0' encoding="utf-8" standalone='yes'?>
и сохранить в кодировке UTF-8. В этой кодировке можно сохранить с помощью обыкновенного блокнота Windows notepad.exe или с помощью Notepad++.
Миниатюры
Программа редактирования XML - документа  
Вложения
Тип файла: rar XMLEditor-01.rar (257.6 Кб, 839 просмотров)
5
 Аватар для Mawrat
13114 / 5895 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
11.04.2012, 15:45
Лучший ответ Сообщение было отмечено как решение

Решение

Добавил редактирование атрибутов и сохранение XML документа в файл.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, xmldom, XMLIntf, StdCtrls, msxmldom, XMLDoc, ComCtrls, Grids;
 
type
  TForm1 = class(TForm)         
    XMLDocument1: TXMLDocument;
    TreeView1: TTreeView;
    StringGrid1: TStringGrid;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure StringGrid1SetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: String);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
type
  TPXmlNode = ^IXMLNode;
 
//Удаление ссылок ни интерфейсы XML узлов и освобождение памяти, занятой под
//контейнеры типа TPXmlNode. Удаление узлов дерева.
procedure ClearTreeView(aTree : TTreeView);
var
  TreeNode : TTreeNode;
  PXmlNode : TPXmlNode;
  i : Integer;
begin
  if aTree = nil then Exit;
 
  //Перебираем все узлы дерева и удаляем связанные с ними ссылки на интерфейсы XML узлов.
  for i := 0 to aTree.Items.Count - 1 do begin
    TreeNode := aTree.Items[i];
    PXmlNode := TPXmlNode(TreeNode.Data);
    //Удаление из памяти контейнера типа TPXmlNode. При этом, автоматически удаляется
    //ссылка на интерфейс XML узла ( Finalize(TPXmlNode(TreeNode.Data)^) ).
    if PXmlNode <> nil then Dispose( TPXmlNode(TreeNode.Data) );
  end;
  //
  aTree.Items.Clear;
end;
 
procedure ClearStringGrid(aSg : TStringGrid);
var
  Row : Integer;
  PXmlNode : TPXmlNode;
begin
  for Row := aSg.FixedRows to aSg.RowCount - 1 do begin
    //Извлекаем контейнер с сылкой на интерфейс XML узла. Затем, удаляем контейнер
    //из памяти при этом происходит удаление ссылки. Далее - очищаем строку.
    PXmlNode := Pointer(aSg.Rows[Row].Objects[0]);
    if PXmlNode <> nil then Dispose(PXmlNode);
    aSg.Rows[Row].Clear;
  end;
  aSg.RowCount := aSg.FixedRows + 1;
end;
 
//Процедура построена по рекурсивному алгоритму.
//Предназначена для перебора всех XML узлов поддерева с корнем в aXmlNode.
//Для текущего XML узла создаётся соответствующий узел в TTreeView.
//Ссылка на интерфейс XML узла прикрепляется в качестве данных к созданному узлу дерева.
//Для всех дочерних XML узлов выполняется рекурсивный вызов ProcXmlNode().
procedure ProcXmlNode(aXmlNode : IXMLNode; aTree : TTreeView; aTreeNode : TTreeNode);
var
  NewTreeNode : TTreeNode;
  PXmlNode : TPXmlNode;
  i : Integer;
begin
  //Создаём новый узел дерева.
  NewTreeNode := TTreeNode.Create(aTree.Items);
  //Создаём контейнер для хранения ссылки на интерфейс XML узла.
  New(PXmlNode);
  //Записываем в контейнер ссылку на интерфейс XML узла.
  PXmlNode^ := aXmlNode;
  //Добавляем узел в дерево. И прикрепляем к узлу указатель на контейнер, в котором
  //хранится ссылка на интерфейс соответствующего XML узла.
  if aTreeNode = nil then
    NewTreeNode := aTree.Items.AddNode(NewTreeNode, aTreeNode, aXmlNode.NodeName,
      PXmlNode, naAdd) //Узел верхнего уровня.
  else
    NewTreeNode := aTree.Items.AddNode(NewTreeNode, aTreeNode, aXmlNode.NodeName,
      PXmlNode, naAddChild) //Дочерний узел.
  ;
  //Для дочерних XML узлов выполняем рекурсивный вызов ProcXmlNode().
  for i := 0 to aXmlNode.ChildNodes.Count - 1 do
    ProcXmlNode(aXmlNode.ChildNodes[i], aTree, NewTreeNode)
  ;
end;
 
//Загрузка XML документа и построение дерева.
procedure TForm1.Button1Click(Sender: TObject);
var
  XmlDoc : TXMLDocument;
  XmlNodeDoc : IXMLNode;
  Od : TOpenDialog;
begin
  Od := OpenDialog1;
  if Od.InitialDir = '' then Od.InitialDir := SaveDialog1.InitialDir;
  if Od.InitialDir = '' then
    Od.InitialDir := ExtractFilePath(Application.ExeName)
  ;
  if not Od.Execute then Exit;
  if not FileExists(Od.FileName) then begin
    ShowMessage('Файл с заданным именем не существует. Действие отменено.');
    Exit;
  end;
 
  XmlDoc := XMLDocument1;
 
  //Удаление текущего дерева и очистка таблицы.
  ClearTreeView(TreeView1);
  ClearStringGrid(StringGrid1);
  //Загрузка нового XML документа.
  XmlDoc.LoadFromFile(Od.FileName);
 
  //Корневой узел (узел документа).
  XmlNodeDoc := XmlDoc.DocumentElement;
  //Построение дерева.
  ProcXmlNode(XmlNodeDoc, TreeView1, nil);
end;
 
//Сохранение XML документа в файл.
procedure TForm1.Button2Click(Sender: TObject);
var
  Res : Integer;
  Sd : TSaveDialog;
begin
  Sd := SaveDialog1;
  if Sd.InitialDir = '' then Sd.InitialDir := OpenDialog1.InitialDir;
  if Sd.InitialDir = '' then
    Sd.InitialDir := ExtractFilePath(Application.ExeName)
  ;
  if not Sd.Execute then Exit;
  if FileExists(Sd.FileName) then begin
    Res := MessageBox(
      0
      , 'Файл с заданным именем уже существует. Перезаписать этот файл?'
      , 'Файл уже существует.'
      , MB_YESNO + MB_ICONQUESTION + MB_APPLMODAL
    );
    if Res = IDNO then Exit;
  end;
 
  XMLDocument1.SaveToFile(Sd.FileName);
end;
 
//Если выбор (выделение) перешол на узел Node.
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
var
  XmlNode, AttrNode : IXMLNode;
  Sg : TStringGrid;
  PXmlNode : TPXmlNode;
  i, Row, CntRow : Integer;
begin
  Sg := StringGrid1;
  //Получаем ссылку на интерфейс соответствующего XML узла.
  XmlNode := TPXmlNode(Node.Data)^;
  //Очищаем таблицу.
  for Row := Sg.FixedRows to Sg.RowCount - 1 do Sg.Rows[Row].Clear;
  //Устанавливаем количество строк таблицы, в соответствие с количеством атрибутов
  //XML узла.
  CntRow := Sg.FixedRows + XmlNode.AttributeNodes.Count;
  if XmlNode.IsTextElement then Inc(CntRow);
  if XmlNode.NodeType = ntText then Inc(CntRow);
  //Общее количество строк в таблице должно быть всегда больше
  //количества фиксированных строк (так устроен TStringGrid).
  if CntRow = Sg.FixedRows then Inc(CntRow);
  //Устанавливаем вычисленное количество строк.
  Sg.RowCount := CntRow;
  //Индекс первой нефиксированной строки.
  Row := Sg.FixedRows;
  //Если узел является текстовым или содержит простой текст.
  if (XmlNode.NodeType = ntText) or XmlNode.IsTextElement then begin
    Sg.Cells[0, Row] := XmlNode.NodeName;
    Sg.Cells[1, Row] := XmlNode.NodeValue;
    //Прикрепляем к первой (с индексом ноль) ячейке строки под видом объекта
    //контейнер с сылкой на интерфейс XML узла.
    New(PXmlNode);
    PXmlNode^ := XmlNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row);
  end;
  //Перебираем все узлы атрибутов XML узла и сведения об этих узлах
  //записываем в таблицу.
  for i := 0 to XmlNode.AttributeNodes.Count - 1 do begin
    AttrNode := XmlNode.AttributeNodes.Get(i);
    Sg.Cells[0, Row] := AttrNode.NodeName;
    Sg.Cells[1, Row] := AttrNode.NodeValue;
    //Прикрепляем ссылку на интерфейс XML атрибута к первой ячейке в строке.
    New(PXmlNode);
    PXmlNode^ := AttrNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row); //Индекс следующей строки в таблице.
  end;
end;
 
//Обработчик события, которое присходит в момент, когда пользователь изменяет
//текст в ячейке.
procedure TForm1.StringGrid1SetEditText(Sender: TObject; ACol,
  ARow: Integer; const Value: String);
var
  Sg : TStringGrid;
  PXmlNode : TPXmlNode;
begin
  Sg := Sender as TStringGrid;
  PXmlNode := TPXmlNode(Sg.Rows[ARow].Objects[0]);
  if PXmlNode = nil then Exit;
 
  PXmlNode^.NodeValue := Value;
end;
 
//Действия при создании формы.
procedure TForm1.FormCreate(Sender: TObject);
var
  Sg : TStringGrid;
begin
  Sg := StringGrid1;
  Sg.ColWidths[0] := 150;
  if Sg.ClientWidth > 150 then
    Sg.ColWidths[1] := Sg.ClientWidth - 150
  else
    Sg.ColWidths[1] := 150
  ;
  Sg.Cells[0, 0] := 'Атрибут';
  Sg.Cells[1, 0] := 'Значение';
end;
 
//При уничтожении формы, удаляем данные, связанные с узлами дерева и данные,
//связанные с ячейками таблицы.
procedure TForm1.FormDestroy(Sender: TObject);
begin
  ClearTreeView(TreeView1);
  ClearStringGrid(StringGrid1);
end;
 
end.
Следующие шаги могут быть такими:
1. Удаление/добавление атрибутов.
2. Удаление/добавление узлов.
3. Перенос атрибутов и узлов на другие позиции в дереве.
Вложения
Тип файла: rar XMLEditor-02.rar (258.3 Кб, 961 просмотров)
6
5 / 5 / 0
Регистрация: 14.10.2010
Сообщений: 210
26.10.2012, 06:55
хм... неплохо
Но вы не освобождаете память после загрузки xml-файла.
А если они будут под 100 Мб, печально будет
1
 Аватар для Mawrat
13114 / 5895 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
26.10.2012, 08:52
Память в коде освобождается - перед загрузкой нового XML документа и перед уничтожением формы.
Освобождение памяти выполняют две процедуры: ClearTreeView() и ClearStringGrid() - их определения идут самими первыми в разделе Implementation.
Перед загрузкой нового XML документа - строки 131, 132.
И перед уничтожением формы - строки 252, 253.

Добавлено через 9 минут
А вот всё-таки в одном месте есть утечка. - При выборе другого узла в дереве, таблица атрибутов очищается без освобождения... Туда тоже надо добавить вызов ClearStringGrid(). С учётом этого, исправленный метод TForm1.TreeView1Change() будет выглядеть так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//Если выбор (выделение) перешёл на узел Node.
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
var
  XmlNode, AttrNode : IXMLNode;
  Sg : TStringGrid;
  PXmlNode : TPXmlNode;
  i, Row, CntRow : Integer;
begin
  Sg := StringGrid1;
  //Получаем ссылку на интерфейс соответствующего XML узла.
  XmlNode := TPXmlNode(Node.Data)^;
  
  //Очищаем таблицу.
  //for Row := Sg.FixedRows to Sg.RowCount - 1 do Sg.Rows[Row].Clear; //Эту строку удалить из кода.
  ClearStringGrid(StringGrid1); //Эта строка добавлена.
  
  //Устанавливаем количество строк таблицы, в соответствие с количеством атрибутов
  //XML узла.
  CntRow := Sg.FixedRows + XmlNode.AttributeNodes.Count;
  if XmlNode.IsTextElement then Inc(CntRow);
  if XmlNode.NodeType = ntText then Inc(CntRow);
  //Общее количество строк в таблице должно быть всегда больше
  //количества фиксированных строк (так устроен TStringGrid).
  if CntRow = Sg.FixedRows then Inc(CntRow);
  //Устанавливаем вычисленное количество строк.
  Sg.RowCount := CntRow;
  //Индекс первой нефиксированной строки.
  Row := Sg.FixedRows;
  //Если узел является текстовым или содержит простой текст.
  if (XmlNode.NodeType = ntText) or XmlNode.IsTextElement then begin
    Sg.Cells[0, Row] := XmlNode.NodeName;
    Sg.Cells[1, Row] := XmlNode.NodeValue;
    //Прикрепляем к первой (с индексом ноль) ячейке строки под видом объекта
    //контейнер с сылкой на интерфейс XML узла.
    New(PXmlNode);
    PXmlNode^ := XmlNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row);
  end;
  //Перебираем все узлы атрибутов XML узла и сведения об этих узлах
  //записываем в таблицу.
  for i := 0 to XmlNode.AttributeNodes.Count - 1 do begin
    AttrNode := XmlNode.AttributeNodes.Get(i);
    Sg.Cells[0, Row] := AttrNode.NodeName;
    Sg.Cells[1, Row] := AttrNode.NodeValue;
    //Прикрепляем ссылку на интерфейс XML атрибута к первой ячейке в строке.
    New(PXmlNode);
    PXmlNode^ := AttrNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row); //Индекс следующей строки в таблице.
  end;
end;
1
0 / 0 / 0
Регистрация: 20.01.2014
Сообщений: 3
20.01.2014, 17:33
Ув. Mawrat!
Спасибо за столь подробный код.
Есть у меня вопрос.
Мы смотрим атрибуты XML узла по событию Change TTreeView.
Как можно увидеть атрибуты XML узла не по событию, а указывая номер элемента TTreeView?
0
 Аватар для Mawrat
13114 / 5895 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
20.01.2014, 18:48
Цитата Сообщение от dn1983 Посмотреть сообщение
Как можно увидеть атрибуты XML узла не по событию, а указывая номер элемента TTreeView?
Для этого можно за основу взять код обработчика TForm1.TreeView1Change(). Только элемент Node : TTreeNode мы будем получать не через параметр, а будем выбирать его по индексу из коллекции TreeView1.Items. Оформить код можно в виде нового метода в классе формы TForm1:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, xmldom, XMLIntf, StdCtrls, msxmldom, XMLDoc, ComCtrls, Grids;
 
type
  TForm1 = class(TForm)
    ...
    ...
    ...
    TreeView1: TTreeView;
    Button3: TButton;
    Edit1: TEdit;
    ...
    ...
    ...
  private
    { Private declarations }
  public
    { Public declarations }
    function AttrByIndexNode(const aInd : Integer) : Boolean;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
...
...
...
 
//Очистка таблицы.
procedure ClearStringGrid(aSg : TStringGrid);
var
  Row : Integer;
  PXmlNode : TPXmlNode;
begin
  for Row := aSg.FixedRows to aSg.RowCount - 1 do
  begin
    //Извлекаем контейнер с сылкой на интерфейс XML узла. Затем, удаляем контейнер
    //из памяти при этом происходит удаление ссылки. Далее - очищаем строку.
    PXmlNode := Pointer(aSg.Rows[Row].Objects[0]);
    if PXmlNode <> nil then
      Dispose(PXmlNode);
    aSg.Rows[Row].Clear;
  end;
  aSg.RowCount := aSg.FixedRows + 1;
end;
 
//Попытка показать сведения об атрибутах XML узла, представленного элементом TreeView1.Items[aInd].
function TForm1.AttrByIndexNode(const aInd : Integer) : Boolean;
var
  XmlNode, AttrNode : IXMLNode;
  Sg : TStringGrid;
  PXmlNode : TPXmlNode;
  Node : TTreeNode;
  i, Row, CntRow : Integer;
begin
  Result := False;
  if (aInd < 0) or (aInd >= TreeView1.Items.Count) then
    Exit;
 
  //Получаем ссылку на узел TreeView по индексу.
  Node := TreeView1.Items[aInd];
  //Ссылка на таблицу атрибутов.
  Sg := StringGrid1;
  //Очищаем таблицу.
  ClearStringGrid(Sg);
 
  //Получаем ссылку на интерфейс соответствующего XML узла.
  XmlNode := TPXmlNode(Node.Data)^;
  //Устанавливаем количество строк таблицы, в соответствие с количеством атрибутов
  //XML узла.
  CntRow := Sg.FixedRows + XmlNode.AttributeNodes.Count;
  if XmlNode.IsTextElement then
    Inc(CntRow);
  if XmlNode.NodeType = ntText then
    Inc(CntRow);
  //Общее количество строк в таблице должно быть всегда больше
  //количества фиксированных строк (так устроен TStringGrid).
  if CntRow = Sg.FixedRows then
    Inc(CntRow);
  //Устанавливаем вычисленное количество строк.
  Sg.RowCount := CntRow;
  //Индекс первой нефиксированной строки.
  Row := Sg.FixedRows;
  //Если узел является текстовым или содержит простой текст.
  if (XmlNode.NodeType = ntText) or XmlNode.IsTextElement then
  begin
    Sg.Cells[0, Row] := XmlNode.NodeName;
    if not VarIsNull(XmlNode.NodeValue) then
      Sg.Cells[1, Row] := XmlNode.NodeValue;
    //Прикрепляем к первой (с индексом ноль) ячейке строки под видом объекта
    //контейнер с сылкой на интерфейс XML узла.
    New(PXmlNode);
    PXmlNode^ := XmlNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row);
  end;
  //Перебираем все узлы атрибутов XML узла и сведения об этих узлах
  //записываем в таблицу.
  for i := 0 to XmlNode.AttributeNodes.Count - 1 do
  begin
    AttrNode := XmlNode.AttributeNodes.Get(i);
    Sg.Cells[0, Row] := AttrNode.NodeName;
    if not VarIsNull(AttrNode.NodeValue) then
      Sg.Cells[1, Row] := AttrNode.NodeValue;
    //Прикрепляем ссылку на интерфейс XML атрибута к первой ячейке в строке.
    New(PXmlNode);
    PXmlNode^ := AttrNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row); //Индекс следующей строки в таблице.
  end;
 
  Result := True;
end;
 
//Вывод сведений об атрибутах XML узла, который представлен элементом TreeView1.Items[Ind].
procedure TForm1.Button3Click(Sender: TObject);
var
  Ind : Integer;
begin
  //Читаем значение индекса из Edit1.
  if not TryStrToInt(Edit1.Text, Ind) then
  begin
    MessageBox(Handle, 'Индекс элемента задан неверно. Действие отменено.',
      'Ошибка!', MB_OK + MB_ICONERROR + MB_APPLMODAL);
    Exit;
  end;
  
  //Попытка получить сведения об атрибутах XML узла.
  if not AttrByIndexNode(Ind) then
  begin
    MessageBox(Handle, PChar('Элемент дерева с индексом ' + IntToStr(Ind)
      + ' не найден. Действие отменено.'), 'Элемент не найден!',
      MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
end;
 
...
...
...
 
end.
2
0 / 0 / 0
Регистрация: 20.01.2014
Сообщений: 3
21.01.2014, 12:13
Спасибо за пример - с ним разобрался.
Только вот столкнулся с проблемой.
В функции AttrByIndexNode я сделал небольшие дополнения.
И после добавления строчки if (tmp='name') then LPtemplate:=AttrNode.NodeValue;
срабатывает исключение (строчка 67 в коде ниже):
Could not convert variant of type (Null) into type (String);
Буду благодарен за помощь, вот вся функция:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//Попытка показать сведения об атрибутах XML узла, представленного элементом TreeView1.Items[aInd].
function TForm1.AttrByIndexNode(const aInd : Integer) : Boolean;
var
  XmlNode, AttrNode : IXMLNode;
  Sg : TStringGrid;
  PXmlNode : TPXmlNode;
  Node : TTreeNode;
  i, Row, CntRow : Integer;
  tmp: string;
begin
  Result := False;
  if (aInd < 0) or (aInd >= TreeView1.Items.Count) then
    Exit;
 
  //Получаем ссылку на узел TreeView по индексу.
  Node := TreeView1.Items[aInd];
  //Ссылка на таблицу атрибутов.
  Sg := StringGrid1;
  //Очищаем таблицу.
  ClearStringGrid(Sg);
 
  //Получаем ссылку на интерфейс соответствующего XML узла.
  XmlNode := TPXmlNode(Node.Data)^;
  //Устанавливаем количество строк таблицы, в соответствие с количеством атрибутов
  //XML узла.
  CntRow := Sg.FixedRows + XmlNode.AttributeNodes.Count;
  if XmlNode.IsTextElement then
    Inc(CntRow);
  if XmlNode.NodeType = ntText then
    Inc(CntRow);
  //Общее количество строк в таблице должно быть всегда больше
  //количества фиксированных строк (так устроен TStringGrid).
  if CntRow = Sg.FixedRows then
    Inc(CntRow);
  //Устанавливаем вычисленное количество строк.
  Sg.RowCount := CntRow;
  //Индекс первой нефиксированной строки.
  Row := Sg.FixedRows;
  //Если узел является текстовым или содержит простой текст.
  if (XmlNode.NodeType = ntText) or XmlNode.IsTextElement then
  begin
    Sg.Cells[0, Row] := XmlNode.NodeName;
    if not VarIsNull(XmlNode.NodeValue) then
      Sg.Cells[1, Row] := XmlNode.NodeValue;
    //Прикрепляем к первой (с индексом ноль) ячейке строки под видом объекта
    //контейнер с сылкой на интерфейс XML узла.
    New(PXmlNode);
    PXmlNode^ := XmlNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row);
  end;
  //Перебираем все узлы атрибутов XML узла и сведения об этих узлах
  //записываем в таблицу.
  for i := 0 to XmlNode.AttributeNodes.Count - 1 do
  begin
    AttrNode := XmlNode.AttributeNodes.Get(i);
    Sg.Cells[0, Row] := AttrNode.NodeName;
//    showmessage(AttrNode.NodeName+' '+AttrNode.NodeValue);
//    AttrNode.NodeValue:='dimonbest123';
    if not VarIsNull(AttrNode.NodeValue) then
      Sg.Cells[1, Row] := AttrNode.NodeValue;
//    if (AttrNode.NodeValue='template_buttons_drive_2_hor')then     showmessage(AttrNode.NodeValue);
    tmp:=AttrNode.NodeName;
    if (tmp='name') then LPtemplate:=AttrNode.NodeValue;
    //Прикрепляем ссылку на интерфейс XML атрибута к первой ячейке в строке.
    New(PXmlNode); //---------На этой строчке ошибка
    PXmlNode^ := AttrNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row); //Индекс следующей строки в таблице.
  end;
 
  Result := True;
end;
0
 Аватар для Mawrat
13114 / 5895 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
21.01.2014, 15:34
Цитата Сообщение от dn1983 Посмотреть сообщение
Could not convert variant of type (Null) into type (String);
Ошибка, видимо, возникает в строке №64 при выполнении команды LPtemplate:=AttrNode.NodeValue;
Delphi
64
    if (tmp='name') then LPtemplate:=AttrNode.NodeValue;
Если в XML коде значение атрибута задано в виде пустой строки, то в этом случае AttrNode.NodeValue вернёт значение Null (тип Variant). Null не содержит строкового представления, поэтому возникает ошибка. В этом случае можно самостоятельно определить строковое представление, например, Null -> ''. Для более точного представления можно использовать следующие правила:
- Атрибут с именем "name" не найден -> LPTemplate = '---'
- AttrNode.NodeValue = Null -> LPTemplate = ''
- Во всех других случаях -> LPTemplate = AttrNode.NodeValue

В этом случае код будет таким:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
var
  LPTemplate : String;
 
...
 
//Попытка показать сведения об атрибутах XML узла, представленного элементом TreeView1.Items[aInd].
function TForm1.AttrByIndexNode(const aInd : Integer) : Boolean;
var
  XmlNode, AttrNode : IXMLNode;
  Sg : TStringGrid;
  PXmlNode : TPXmlNode;
  Node : TTreeNode;
  i, Row, CntRow : Integer;
begin
  Result := False;
  if (aInd < 0) or (aInd >= TreeView1.Items.Count) then
    Exit;
 
  //Получаем ссылку на узел TreeView по индексу.
  Node := TreeView1.Items[aInd];
  //Ссылка на таблицу атрибутов.
  Sg := StringGrid1;
  //Очищаем таблицу.
  ClearStringGrid(Sg);
 
  //Получаем ссылку на интерфейс соответствующего XML узла.
  XmlNode := TPXmlNode(Node.Data)^;
  //Устанавливаем количество строк таблицы, в соответствие с количеством атрибутов
  //XML узла.
  CntRow := Sg.FixedRows + XmlNode.AttributeNodes.Count;
  if XmlNode.IsTextElement then
    Inc(CntRow);
  if XmlNode.NodeType = ntText then
    Inc(CntRow);
  //Общее количество строк в таблице должно быть всегда больше
  //количества фиксированных строк (так устроен TStringGrid).
  if CntRow = Sg.FixedRows then
    Inc(CntRow);
  //Устанавливаем вычисленное количество строк.
  Sg.RowCount := CntRow;
  //Индекс первой нефиксированной строки.
  Row := Sg.FixedRows;
  //Если узел является текстовым или содержит простой текст.
  if (XmlNode.NodeType = ntText) or XmlNode.IsTextElement then
  begin
    Sg.Cells[0, Row] := XmlNode.NodeName;
    if not VarIsNull(XmlNode.NodeValue) then
      Sg.Cells[1, Row] := XmlNode.NodeValue;
    //Прикрепляем к первой (с индексом ноль) ячейке строки под видом объекта
    //контейнер с сылкой на интерфейс XML узла.
    New(PXmlNode);
    PXmlNode^ := XmlNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row);
  end;
 
  //Перебираем все узлы атрибутов XML узла и сведения об этих узлах
  //записываем в таблицу.
  LPTemplate := '---'; //Признак того, что атрибут с именем "name" не найден.
  for i := 0 to XmlNode.AttributeNodes.Count - 1 do
  begin
    AttrNode := XmlNode.AttributeNodes.Get(i);
    Sg.Cells[0, Row] := AttrNode.NodeName;
    if not VarIsNull(AttrNode.NodeValue) then
      Sg.Cells[1, Row] := AttrNode.NodeValue;
 
    if AttrNode.NodeName = 'name' then
      if VarIsNull(AttrNode.NodeValue) then
        LPTemplate := ''
      else
        LPTemplate := AttrNode.NodeValue;
 
    //Прикрепляем ссылку на интерфейс XML атрибута к первой ячейке в строке.
    New(PXmlNode);
    PXmlNode^ := AttrNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row); //Индекс следующей строки в таблице.
  end;
 
  Result := True;
end;
 
//Вывод сведений об атрибутах XML узла, который представлен элементом TreeView1.Items[Ind].
procedure TForm1.Button3Click(Sender: TObject);
var
  Ind : Integer;
begin
  //Читаем значение индекса из Edit1.
  if not TryStrToInt(Edit1.Text, Ind) then
  begin
    MessageBox(Handle, 'Индекс элемента задан неверно. Действие отменено.',
      'Ошибка!', MB_OK + MB_ICONERROR + MB_APPLMODAL);
    Exit;
  end;
 
  //Попытка получить сведения об атрибутах XML узла.
  if not AttrByIndexNode(Ind) then
  begin
    MessageBox(Handle, PChar('Элемент дерева с индексом ' + IntToStr(Ind)
      + ' не найден. Действие отменено.'), 'Элемент не найден!',
      MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
 
  Label1.Caption := LPTemplate;
end;
Но то, что здесь для возврата значения используется глобальная переменная (LPTemplate) - в чистовом варианте кода нужно избежать такого подхода. Если нужно находить значения атрибутов по заданному индексу родительского узла и по имени атрибута - для этого лучше специальную процедуру написать.
2
0 / 0 / 0
Регистрация: 20.01.2014
Сообщений: 3
22.01.2014, 19:16
Еще раз спасибо - разобрался.
Появился надеюсь последний вопрос - удаление.
Удалить с treeview я знаю как:
Delphi
1
treeview1.Items.Item[strtoint(edit1.Text)].Delete;
А вот как сделать аналогичное удаление с xml файла?
0
 Аватар для Mawrat
13114 / 5895 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
23.01.2014, 19:13
Удаление будет из нескольких этапов состоять. У нас устройство такое. К каждому узлу TreeView через поле TTreeNode.Data привязан контейнер, который хранит ссылку на интерфейс XML узла. Поэтому нам надо удалить узел TreeView, освободить память, занятую под контейнер и затем удалить сам XML узел.
Вот, как это можно сделать:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//Попытка удалить XML узел. При этом будет удалён XML узел и соответствующий узел TreeView.
function TForm1.DelNode(const aInd : Integer) : Boolean;
var
  XmlNode : IXMLNode;
  PXmlNode : TPXmlNode;
  Node : TTreeNode;
begin
  Result := False;
  if (aInd < 0) or (aInd >= TreeView1.Items.Count) then
    Exit;
 
  //Получаем ссылку на узел TreeView по индексу.
  Node := TreeView1.Items[aInd];
  //Получаем указатель на контейнер, который хранит ссылку на интерфейс XML узла.
  PXmlNode := Pointer(Node.Data);
  //Получаем ссылку на интерфейс соответствующего XML узла.
  XmlNode := PXmlNode^;
 
  //Проверяем - если XML узел оказался корневым узлом XML документа, то отменяем
  //операцию удаления. Потому, что корневой узел XML документа удалить нельзя.
  if XmlNode.ParentNode = nil then
    Exit;
 
  //Приступаем к удалению.
 
  //1. Удаление узла TreeView.
  //Если узел выделен в TreeView, то выполняем очистку таблицы атрибутов.
  if Node.Selected then
    ClearStringGrid(StringGrid1);
  //Удаление узла TreeView.
  Node.Delete;
 
  //2. Освобождаем память, занятую для контейнера, который хранит ссылку на
  //интерфейс XML узла.
  Dispose(PXmlNode);
 
  //3. Удаляем XML узел. Здесь мы обращаемся к узлу, который является родительским
  //по отношению к удаляемому узлу: XmlNode.ParentNode и через его коллекцию
  //дочерних элементов XmlNode.ParentNode.ChildNodes выполняем удаление по индексу
  XmlNode.ParentNode.ChildNodes.Delete(XmlNode.ParentNode.ChildNodes.IndexOf(XmlNode));
 
  Result := True;
end;
 
//Кнопка "Удалить узел по индексу".
procedure TForm1.Button4Click(Sender: TObject);
var
  Ind : Integer;
begin
  //Читаем значение индекса из Edit1.
  if not TryStrToInt(Edit1.Text, Ind) then
  begin
    MessageBox(Handle, 'Индекс элемента задан неверно. Действие отменено.',
      'Ошибка!', MB_OK + MB_ICONERROR + MB_APPLMODAL);
    Exit;
  end;
 
  //Попытка удалить XML узел.
  if not DelNode(Ind) then
  begin
    MessageBox(Handle, PChar('Элемент дерева с индексом ' + IntToStr(Ind)
      + ' удалить не удалось. Действие отменено.'), 'Отмена!',
      MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
end;
5
1 / 1 / 0
Регистрация: 12.06.2015
Сообщений: 67
18.07.2015, 08:07
Интересно и хорошо сделано как пример в дальнейшем программировании.
.
Можно ли у видеть окончательную версию продукта ?
В виде исходников и архива ?
.
0
1 / 1 / 0
Регистрация: 12.06.2015
Сообщений: 67
19.07.2015, 17:40
Есть некий XML файл.
Файл XML нормальный,
но последней строкой или несколькими строками содержит электронную подпись.
.
Использую стандартный компонент TXMLDocument .
.
var
XML : TXMLDocument
.
Упрощенный код.
.
XML:=TXMLDocument.Create(self);
XML.LoadFromFile('Имя файла');
.
Как сделать так, чтобы при загрузки файла XML не выдавалась следующая ошибка:



Т.е. игнорировать ошибку ?
.
0
1 / 1 / 0
Регистрация: 12.06.2015
Сообщений: 67
22.07.2015, 20:49
Ну как то так...
.

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, xmldom, XMLIntf, StdCtrls, msxmldom, XMLDoc, ComCtrls, Grids;
 
type
  TForm1 = class(TForm)
    XMLDocument1: TXMLDocument;
    TreeView1: TTreeView;
    StringGrid1: TStringGrid;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure StringGrid1SetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: String);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    function AttrByIndexNode(const aInd : Integer) : Boolean;
    function DelNode(const aInd : Integer) : Boolean;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
type
  TPXmlNode = ^IXMLNode;
 
var
  LPTemplate : String;
 
 
// Удаление ссылок ни интерфейсы XML узлов и освобождение памяти, занятой под
// контейнеры типа TPXmlNode. Удаление узлов дерева.
procedure ClearTreeView(aTree : TTreeView);
var
  TreeNode : TTreeNode;
  PXmlNode : TPXmlNode;
  i : Integer;
begin
  if aTree = nil then Exit;
 
  // Перебираем все узлы дерева и удаляем связанные с ними ссылки на интерфейсы XML узлов.
  for i := 0 to aTree.Items.Count - 1 do begin
    TreeNode := aTree.Items[i];
    PXmlNode := TPXmlNode(TreeNode.Data);
    // Удаление из памяти контейнера типа TPXmlNode. При этом, автоматически удаляется
    // ссылка на интерфейс XML узла ( Finalize(TPXmlNode(TreeNode.Data)^) ).
    if PXmlNode <> nil then Dispose( TPXmlNode(TreeNode.Data) );
  end;
  //
  aTree.Items.Clear;
end;
 
// Очистка таблицы.
procedure ClearStringGrid(aSg : TStringGrid);
var
  Row : Integer;
  PXmlNode : TPXmlNode;
begin
  for Row := aSg.FixedRows to aSg.RowCount - 1 do
  begin
    // Извлекаем контейнер с сылкой на интерфейс XML узла. Затем, удаляем контейнер
    // из памяти при этом происходит удаление ссылки. Далее - очищаем строку.
    PXmlNode := Pointer(aSg.Rows[Row].Objects[0]);
    if PXmlNode <> nil then
      Dispose(PXmlNode);
    aSg.Rows[Row].Clear;
  end;
  aSg.RowCount := aSg.FixedRows + 1;
end;
 
// Процедура построена по рекурсивному алгоритму.
// Предназначена для перебора всех XML узлов поддерева с корнем в aXmlNode.
// Для текущего XML узла создаётся соответствующий узел в TTreeView.
// Ссылка на интерфейс XML узла прикрепляется в качестве данных к созданному узлу дерева.
// Для всех дочерних XML узлов выполняется рекурсивный вызов ProcXmlNode().
procedure ProcXmlNode(aXmlNode : IXMLNode; aTree : TTreeView; aTreeNode : TTreeNode);
var
  NewTreeNode : TTreeNode;
  PXmlNode    : TPXmlNode;
  i           : Integer;
begin
  // Создаём новый узел дерева.
  NewTreeNode:=TTreeNode.Create(aTree.Items);
 
  // Создаём контейнер для хранения ссылки на интерфейс XML узла.
  New(PXmlNode);
 
  // Записываем в контейнер ссылку на интерфейс XML узла.
  PXmlNode^:=aXmlNode;
 
  // Добавляем узел в дерево. И прикрепляем к узлу указатель на контейнер, в котором
  // хранится ссылка на интерфейс соответствующего XML узла.
  if (aTreeNode = nil)
    then NewTreeNode:=aTree.Items.AddNode(NewTreeNode, aTreeNode, aXmlNode.NodeName, PXmlNode, naAdd)   // Узел верхнего уровня.
    else NewTreeNode:=aTree.Items.AddNode(NewTreeNode, aTreeNode, aXmlNode.NodeName, PXmlNode, naAddChild);   // Дочерний узел.
  
  // Для дочерних XML узлов выполняем рекурсивный вызов ProcXmlNode().
  for i:=0 to aXmlNode.ChildNodes.Count - 1 do
    ProcXmlNode(aXmlNode.ChildNodes[i], aTree, NewTreeNode);
end;
 
// Загрузка XML документа и построение дерева.
procedure TForm1.Button1Click(Sender: TObject);
var
  XmlDoc     : TXMLDocument;
  XmlNodeDoc : IXMLNode;
  Od         : TOpenDialog;
begin
  Od:=OpenDialog1;
  if (Od.InitialDir = '') then Od.InitialDir:=SaveDialog1.InitialDir;
  if (Od.InitialDir = '') then Od.InitialDir:=ExtractFilePath(Application.ExeName);
 
  if not Od.Execute then Exit;
  
  if not FileExists(Od.FileName) then 
  begin
    ShowMessage('Файл с заданным именем не существует. Действие отменено.');
    Exit;
  end;
 
  XmlDoc:=XMLDocument1;
 
  // Удаление текущего дерева и очистка таблицы.
  ClearTreeView(TreeView1);
  ClearStringGrid(StringGrid1);
  
  // Загрузка нового XML документа.
  XmlDoc.LoadFromFile(Od.FileName);
 
  // Корневой узел (узел документа).
  XmlNodeDoc:=XmlDoc.DocumentElement;
  
  // Построение дерева.
  ProcXmlNode(XmlNodeDoc, TreeView1, nil);
end;
 
// Сохранение XML документа в файл.
procedure TForm1.Button2Click(Sender: TObject);
var
  Res : Integer;
  Sd  : TSaveDialog;
begin
  Sd:=SaveDialog1;
  if (Sd.InitialDir = '') then Sd.InitialDir:=OpenDialog1.InitialDir;
  if (Sd.InitialDir = '') then Sd.InitialDir:=ExtractFilePath(Application.ExeName);
 
  if not Sd.Execute then Exit;
  
  if FileExists(Sd.FileName) then 
  begin
    Res:=MessageBox(0, 'Файл с заданным именем уже существует. Перезаписать этот файл?', 
                       'Файл уже существует.', 
                        MB_YESNO + MB_ICONQUESTION + MB_APPLMODAL);
    if (Res = IDNO) then Exit;
  end;
 
  XMLDocument1.SaveToFile(Sd.FileName);
end;
 
// Попытка показать сведения об атрибутах XML узла, представленного элементом TreeView1.Items[aInd].
function TForm1.AttrByIndexNode(const aInd : Integer) : Boolean;
var
  XmlNode, AttrNode : IXMLNode;
  Sg : TStringGrid;
  PXmlNode : TPXmlNode;
  Node : TTreeNode;
  i, Row, CntRow : Integer;
begin
  Result := False;
  if (aInd < 0) or (aInd >= TreeView1.Items.Count) then Exit;
 
  // Получаем ссылку на узел TreeView по индексу.
  Node := TreeView1.Items[aInd];
 
  // Ссылка на таблицу атрибутов.
  Sg := StringGrid1;
  
  // Очищаем таблицу.
  ClearStringGrid(Sg);
 
  // Получаем ссылку на интерфейс соответствующего XML узла.
  XmlNode := TPXmlNode(Node.Data)^;
 
  // Устанавливаем количество строк таблицы, в соответствие с количеством атрибутов
  // XML узла.
  CntRow := Sg.FixedRows + XmlNode.AttributeNodes.Count;
  if XmlNode.IsTextElement then Inc(CntRow);
  if XmlNode.NodeType = ntText then Inc(CntRow);
  
  // Общее количество строк в таблице должно быть всегда больше
  // количества фиксированных строк (так устроен TStringGrid).
  if CntRow = Sg.FixedRows then Inc(CntRow);
  
  // Устанавливаем вычисленное количество строк.
  Sg.RowCount := CntRow;
  
  // Индекс первой нефиксированной строки.
  Row := Sg.FixedRows;
  
  // Если узел является текстовым или содержит простой текст.
  if ((XmlNode.NodeType = ntText) or XmlNode.IsTextElement) then
  begin
    Sg.Cells[0, Row] := XmlNode.NodeName;
    if not VarIsNull(XmlNode.NodeValue) then
      Sg.Cells[1, Row] := XmlNode.NodeValue;
 
    // Прикрепляем к первой (с индексом ноль) ячейке строки под видом объекта
    // контейнер с сылкой на интерфейс XML узла.
    New(PXmlNode);
    PXmlNode^ := XmlNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row);
  end;
 
  // Перебираем все узлы атрибутов XML узла и сведения об этих узлах
  // записываем в таблицу.
  LPTemplate:='---';   // Признак того, что атрибут с именем "name" не найден.
 
  for i:=0 to XmlNode.AttributeNodes.Count - 1 do
  begin
    AttrNode:=XmlNode.AttributeNodes.Get(i);
    Sg.Cells[0, Row]:=AttrNode.NodeName;
    if not VarIsNull(AttrNode.NodeValue) then Sg.Cells[1, Row] := AttrNode.NodeValue;
 
    if AttrNode.NodeName = 'name' then
      if VarIsNull(AttrNode.NodeValue) then LPTemplate := ''
      else LPTemplate := AttrNode.NodeValue;
 
    // Прикрепляем ссылку на интерфейс XML атрибута к первой ячейке в строке.
    New(PXmlNode);
    PXmlNode^:=AttrNode;
    Sg.Rows[Row].Objects[0]:=TObject(PXmlNode);
    Inc(Row);   // Индекс следующей строки в таблице.
  end;
 
  Result := True;
end;
 
 
procedure TForm1.Button3Click(Sender: TObject);
var
  Ind : Integer;
begin
  // Читаем значение индекса из Edit1.
  if not TryStrToInt(Edit1.Text, Ind) then
  begin
    MessageBox(Handle, 'Индекс элемента задан неверно. Действие отменено.',
                       'Ошибка!', MB_OK + MB_ICONERROR + MB_APPLMODAL);
    Exit;
  end;
 
  // Попытка получить сведения об атрибутах XML узла.
  if not AttrByIndexNode(Ind) then
  begin
    MessageBox(Handle, PChar('Элемент дерева с индексом ' + IntToStr(Ind)
                           + ' не найден. Действие отменено.'), 'Элемент не найден!',
               MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
  Label1.Caption := LPTemplate;
end;
 
procedure TForm1.Button4Click(Sender: TObject);
var
  Ind : Integer;
begin
  // Читаем значение индекса из Edit1.
  if not TryStrToInt(Edit1.Text, Ind) then
  begin
    MessageBox(Handle, 'Индекс элемента задан неверно. Действие отменено.',
                       'Ошибка!', MB_OK + MB_ICONERROR + MB_APPLMODAL);
    Exit;
  end;
 
  // Попытка удалить XML узел.
  if not DelNode(Ind) then
  begin
    MessageBox(Handle, PChar('Элемент дерева с индексом ' + IntToStr(Ind)
                           + ' удалить не удалось. Действие отменено.'), 'Отмена!',
               MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
end;
 
// Попытка удалить XML узел. При этом будет удалён XML узел и соответствующий узел TreeView.
function TForm1.DelNode(const aInd : Integer) : Boolean;
var
  XmlNode : IXMLNode;
  PXmlNode : TPXmlNode;
  Node : TTreeNode;
begin
  Result := False;
  if (aInd < 0) or (aInd >= TreeView1.Items.Count) then Exit;
 
  // Получаем ссылку на узел TreeView по индексу.
  Node := TreeView1.Items[aInd];
 
  // Получаем указатель на контейнер, который хранит ссылку на интерфейс XML узла.
  PXmlNode := Pointer(Node.Data);
  
  // Получаем ссылку на интерфейс соответствующего XML узла.
  XmlNode := PXmlNode^;
 
  // Проверяем - если XML узел оказался корневым узлом XML документа, то отменяем
  // операцию удаления. Потому, что корневой узел XML документа удалить нельзя.
  if XmlNode.ParentNode = nil then Exit;
 
  // Приступаем к удалению.
 
  // 1. Удаление узла TreeView.
  // Если узел выделен в TreeView, то выполняем очистку таблицы атрибутов.
  if Node.Selected then ClearStringGrid(StringGrid1);
  
  // Удаление узла TreeView.
  Node.Delete;
 
  // 2. Освобождаем память, занятую для контейнера, который хранит ссылку на
  // интерфейс XML узла.
  Dispose(PXmlNode);
 
  // 3. Удаляем XML узел. Здесь мы обращаемся к узлу, который является родительским
  // по отношению к удаляемому узлу: XmlNode.ParentNode и через его коллекцию
  // дочерних элементов XmlNode.ParentNode.ChildNodes выполняем удаление по индексу
  XmlNode.ParentNode.ChildNodes.Delete(XmlNode.ParentNode.ChildNodes.IndexOf(XmlNode));
 
  Result := True;
end;
 
// Если выбор (выделение) перешол на узел Node.
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
var
  XmlNode, AttrNode : IXMLNode;
  Sg : TStringGrid;
  PXmlNode : TPXmlNode;
  i, Row, CntRow : Integer;
begin
  Sg := StringGrid1;
  
  // Получаем ссылку на интерфейс соответствующего XML узла.
  XmlNode := TPXmlNode(Node.Data)^;
  
  // Очищаем таблицу.
  // for Row := Sg.FixedRows to Sg.RowCount - 1 do Sg.Rows[Row].Clear;   // Эту строку удалить из кода.
  ClearStringGrid(StringGrid1);   // Эта строка добавлена.
  
  // Устанавливаем количество строк таблицы, в соответствие с количеством атрибутов
  // XML узла.
  CntRow := Sg.FixedRows + XmlNode.AttributeNodes.Count;
  if XmlNode.IsTextElement then Inc(CntRow);
  if XmlNode.NodeType = ntText then Inc(CntRow);
  
  // Общее количество строк в таблице должно быть всегда больше
  // количества фиксированных строк (так устроен TStringGrid).
  if CntRow = Sg.FixedRows then Inc(CntRow);
  
  // Устанавливаем вычисленное количество строк.
  Sg.RowCount := CntRow;
  
  // Индекс первой нефиксированной строки.
  Row := Sg.FixedRows;
  
  // Если узел является текстовым или содержит простой текст.
  if (XmlNode.NodeType = ntText) or XmlNode.IsTextElement then 
  begin
    Sg.Cells[0, Row] := XmlNode.NodeName;
    Sg.Cells[1, Row] := XmlNode.NodeValue;
    
    // Прикрепляем к первой (с индексом ноль) ячейке строки под видом объекта
    // контейнер с сылкой на интерфейс XML узла.
    New(PXmlNode);
    PXmlNode^ := XmlNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row);
  end;
  
  // Перебираем все узлы атрибутов XML узла и сведения об этих узлах
  // записываем в таблицу.
  for i:=0 to XmlNode.AttributeNodes.Count - 1 do 
  begin
    AttrNode := XmlNode.AttributeNodes.Get(i);
    Sg.Cells[0, Row] := AttrNode.NodeName;
    Sg.Cells[1, Row] := AttrNode.NodeValue;
    
    // Прикрепляем ссылку на интерфейс XML атрибута к первой ячейке в строке.
    New(PXmlNode);
    PXmlNode^ := AttrNode;
    Sg.Rows[Row].Objects[0] := TObject(PXmlNode);
    Inc(Row);   // Индекс следующей строки в таблице.
  end;
end;
 
// Обработчик события, которое присходит в момент, когда пользователь изменяет
// текст в ячейке.
procedure TForm1.StringGrid1SetEditText(Sender: TObject; ACol,
  ARow: Integer; const Value: String);
var
  Sg       : TStringGrid;
  PXmlNode : TPXmlNode;
begin
  Sg:=Sender as TStringGrid;
  PXmlNode:=TPXmlNode(Sg.Rows[ARow].Objects[0]);
  if (PXmlNode = nil) then Exit;
 
  PXmlNode^.NodeValue := Value;
end;
 
// Действия при создании формы.
procedure TForm1.FormCreate(Sender: TObject);
var
  Sg : TStringGrid;
begin
  Sg := StringGrid1;
  Sg.ColWidths[0] := 150;
  if Sg.ClientWidth > 150 then Sg.ColWidths[1] := Sg.ClientWidth - 150
  else Sg.ColWidths[1] := 150;
 
  Sg.Cells[0, 0] := 'Атрибут';
  Sg.Cells[1, 0] := 'Значение';
end;
 
// При уничтожении формы, удаляем данные, связанные с узлами дерева и данные,
// связанные с ячейками таблицы.
procedure TForm1.FormDestroy(Sender: TObject);
begin
  ClearTreeView(TreeView1);
  ClearStringGrid(StringGrid1);
end;
 
end.
0
1 / 1 / 0
Регистрация: 12.06.2015
Сообщений: 67
22.07.2015, 20:54
Есть вопрос по вот такому коду.
.

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
program Project2_XML;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
  System.SysUtils,
  ActiveX,
  ComObj, Classes,
  XMLIntf, XMLDoc;
 
 
var
  XML     : TXMLDocument;
  XMLNode : IXMLNode;
 
 
procedure ProcXMLNode(aXMLNode : IXMLNode);
var
  i : Integer;
begin
  for i:=0 to aXMLNode.ChildNodes.Count - 1 do
    begin
//      WriteLn('aXmlNode.ChildNodes[i].Text= ', aXmlNode.ChildNodes[i].Text);
      ProcXMLNode(aXMLNode.ChildNodes[i]);
    end;
end;
 
begin
  try
    { TODO -oUser -cConsole Main : Insert code here }
 
 
    WriteLn;
 
    CoInitialize(nil);
 
 
 
    XML:=TXMLDocument.Create(nil);
    XML.Active:=True;
 
    XML.LoadFromFile('UVBN858811507010001.xml');
 
    XMLNode:=XML.DocumentElement;
//    ProcXMLNode(XMLNode);
 
    XML.Active:=False;
    XML.Free;
 
 
 
    CoUninitialize;
 
 
 
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
Вопрос.
Ругается на строчку
XMLNode:=XML.DocumentElement;
EAccessViolation: Access violation at address 004E5F40 in module 'Project2_XML.exe'. Read of address 00000049
.
Ну никак я не пойму отчего и почему ???
.
0
70 / 14 / 4
Регистрация: 10.07.2018
Сообщений: 314
02.10.2018, 20:14
Цитата Сообщение от Mawrat Посмотреть сообщение
Следующие шаги могут быть такими:
1. Удаление/добавление атрибутов.
2. Удаление/добавление узлов.
3. Перенос атрибутов и узлов на другие позиции в дереве.
Все отлично и все хорошо, но вот потребовалось внести изменения и сохранить в файл. и тут концов не сыщеш как это сделать.
0
5967 / 4543 / 1094
Регистрация: 29.08.2013
Сообщений: 28,157
Записей в блоге: 3
02.10.2018, 20:41
Цитата Сообщение от Юг Посмотреть сообщение
тут концов не сыщеш как это сделать.
а комментарии почитать?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
02.10.2018, 20:41
Помогаю со студенческими работами здесь

Вытащить данные из xml документа
Доброго часа! Помогите плиз. Есть задача вытащить из xml документа &lt;artist&gt;Алиса&lt;/artist&gt; в один listbox, а...

Ошибка в создании xml документа
Пытаюсь создать xml документ: Xml:=TXMLDocument.Create(nil); with Xml do begin with AddChild ('NesYo') do ...

Взять данные с XML документа
Всем привет. Есть файл res.xml Хочу с него взять данные по магазину shop=&quot;PbIHOK_FX&quot; 0.81 1.42 1.02 2.26 2.22 ...

Формирование XML документа с узлами с одинаковыми именами
Здравствуйте. Может кто-нибудь подсказать, как создать в XML документе два узла с одинаковыми именами. Типа &lt;ArrayOfNUMPAS&gt; ...

Загрузка данных из XML документа. В RadioButton.Caption не отображается значение!
Есть часть программы(тест), которая берет значения из XML файла(test.xml), по средствам XMLDocument и вставляет в RadioButton.Caption, но...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru