Поиск по блогу

среда, 13 января 2010 г.

Добавление и удаление узлов (вершин) в XML в Delphi (с использованием компонента TTreeView)

Приветствую всех подписчиков и читателей блога "Парсинг от А до Я"! Поздравляю с прошедшими праздниками и желаю в новом году терпения и усердия на пути к достижению поставленных целей. Надеюсь, что вы так же, как я, набрались сил и наполнились энтузиазмом за эти каникулы.

Сегодня появилось немного свободного времени, и я решила посвятить его развитию блога. Итак, проанализировав запросы, по которым приходят на этот ресурс, я решила дополнить его статьей о работе с XML в Delphi. Я уже затрагивала этот вопрос в материале "Отображение XML в виде дерева (TreeView): Delphi". К сожалению, тогда была невнимательной и как-то упустила комментарии о том, что в листинге отображены не все процедуры. В этот раз постараюсь исправиться и наряду с объяснениями выложить исходники того, о чем пойдет речь.

Итак, в той статье было описано отображение XML в TTreeView. А сейчас попытаемся сделать из просмотрщика редактор XML. Не сразу, постепенно. Понимаю, что как таковой самописный редактор XML вам не понадобится, тем более, что в сети можно найти много бесплатных утилит с полным набором требуемых функций, но новичкам будет полезно посмотреть, как сделать это своими руками. Вдруг в каком-нибудь вашем проекте вы решите поработать с XML... Собственно, я и решила написать этот пост про XML, так как стала переделывать RSSAdder: он будет работать не с ini-файлом, а с xml, и пользователям не придется совершать пляски с бубном, чтобы добавить в список новый агрегатор или изменить настройки у существующего.

На первом этапе добавим возможность добавлять узлы на один уровень с выбранным и дочерние узлы. Для этого поместим на форму соответствующие кнопочки и создадим экшэны со следующими обработчиками.

Добавление узла на один уровень с узлом, выбранным в TreeView:

procedure TMainF.acAddNodeExecute(Sender: TObject);
var
idx : integer ;
S : String ;
xN : IXMLNode ;
trN : TTreeNode ;
R : TNodeRec ;
begin
if CurrNode = nil then CurrNode := XDoc.Node;
S := InputBox('Добавить новый узел на один уровень с "' + CurrNode.NodeName+ '"','имя узла:','');
if S <> '' then
begin
try
xn := CurrNode.ParentNode.AddChild(S);
trN := TreeView.Items.AddChildObject(TreeView.Selected.Parent,S,
pointer(xn.ParentNode.ChildNodes.IndexOf(xn)));
R := TNodeRec.Create;
R.XMLNode := xn;
R.TreeNode := trN;
idx := CurrentNodeListIndex;
if idx = -1 then idx := 0;
XDocNodesList.Insert(idx,R);
except
end ;
end ;
acRefreshMemBody.Execute ;
end;


Порядок действий следующий:
- выбираете узел (напомню, что рутовый узел может быть только один, поэтому у вас не получится добавить узел на один уровень с рутовым);
- нажимаете кнопку добавления узла;
- вводите его имя (без пробелов, соблюдая все правила именования узлов в XML);
add node XML in Delphi
- получаете результат.
add node XML in Delphi result

Добавление дочернего элемента к узлу, выбранному в TreeView:

procedure TMainF.acAddChildNodeExecute(Sender: TObject);
var
idx : integer ;
S : String ;
xN : IXMLNode ;
trN : TTreeNode ;
R : TNodeRec ;
begin
if CurrNode = nil then exit;
if CurrNode.ParentNode = nil then exit;
S:=InputBox('Добавить дочерний узел к "' + CurrNode.NodeName + '"','имя узла:','');
if S <> '' then
begin
try
xn := CurrNode.AddChild(S);
trN := TreeView.Items.AddChildObject(TreeView.Selected,S,
pointer(xn.ParentNode.ChildNodes.IndexOf(xn)));
R:=TNodeRec.Create;
R.XMLNode := xn;
R.TreeNode := trN;
idx := CurrentNodeListIndex;
if idx = -1 then idx := 0;
XDocNodesList.Insert(idx,R);
except
end;
end;
acRefreshMemBody.Execute;
end;


Порядок действий:
- выбираете узел;
- нажимаете кнопку добавления дочернего узла;
- вводите его имя (без пробелов, соблюдая все правила именования узлов в XML);
add subnode XML in Delphi
- получаете результат.
add subnode XML in Delphi result

Здесь CurrentNodeListIndex — функция, возвращающая индекс текущего узла:

function TMainF.CurrentNodeListIndex: integer;
var
i : integer;
begin
Result := -1;
for i := 0 to XDocNodesList.Count - 1 do
if TNodeRec(XDocNodesList[i]).XMLNode = CurrNode then
begin
Result := i;
break;
end;
end;


Ну и для полноты картины - удаление узла:

procedure TMainF.acRemoveNodeExecute(Sender: TObject);
var
pNode : IXMLNode;
begin
if CurrNode = nil then exit;
pNode := CurrNode.ParentNode;
if pNode = nil then exit;
pNode.ChildNodes.Delete(CurrNode.NodeName);
TreeView.Selected.Delete;
TreeView.Selected := TreeView.TopItem;
CurrNode := XDoc.Node;
acRefreshMemBody.Execute;
end;



Итак, сейчас вершины можно добавлять. Но это не принесет вам счастья, пока не реализована функция сохранения XML :) XML сохраняется одной командой:

XDoc.SaveToFile(FName);


В исходниках добавлены процедуры "Сохранить" и "Сохранить как...".

Все исходники можно скачать и изучить (8 Кб) (выкладываю опять же на Яндекс; возможно, дома переложу куда-нибудь, но пока что нет возможности). В папке с проектом лежит xml-файл, на котором можно потестировать работу программы.

Это первый этап, на следующих этапах предстоит еще реализовать работу с атрибутами. И это будет не менее занимательно, так что подписывайтесь на RSS блога, чтобы не пропустить :)))
___

Продолжение статьи: Добавление и удаление атрибутов узлов (вершин) в XML в Delphi (с использованием компонента TTreeView)
___

Статьи схожей тематики:



4 комментария:

  1. Исходники выдают ошибку при клике в дерево
    http://www.traylers.ru/111.JPG

    ОтветитьУдалить
  2. Трейлер, ну неудивительно, там в try...except заключено. Я не заморачивалась на мелочи, это код на скорую руку. Если вы запустите не под отладчиком, а скомпилируете и запустите - этого, естественно, не будет.
    Доработайте сами, это не проблема.

    Там выпадает на CurrNode.Text - проверьте на наличие значения этого свойства с помощью VarIsNull. Добавьте перед каждым обращением

    if not VarIsNull(CurrNode.Text) then
    ...

    и ваша "проблема" будет решена :)

    ОтветитьУдалить
  3. Здравствуйте, я начинающий программист, не могли бы вы конкретнее объяснить, куда именно вставлять проверку на ноль? пробовала по-разному, все равно ошибка.. почему она возникает?

    ОтветитьУдалить
  4. Арина, в обработчике посмотрите, где она возникает. Если честно, сейчас вообще нет времени смотреть, да и код этот старый-престарый, уже не помню даже, о чем речь)) Посмотрите, где там try...except.

    ОтветитьУдалить

Комментарии модерируются, вопросы не по теме удаляются, троллинг тоже.

К сожалению, у меня нет столько свободного времени, чтобы отвечать на все частные вопросы, так что, может, свой вопрос лучше задать на каком-нибудь форуме?

Поделиться