Так как в последнее время очень много работаю с XML-документами различно сложности, то в процессе работы родилась небольшая идея - написать микро-приложение с помощью которого можно проследить логику документа в принципе, т.е. посмотреть уровень вложенности узлов, в случае необходимости - отметить определенные узлы как-либо и т.д. Пока количество узлов и их аттрибутов не велико, то с задачей вполне справиться любой браузер, но, когда у каждого узла по куче атрибутов, а сам документ имеет большую вложенность узлов, то как-то становиться жалко ломать глаза.Вот и родилась идея этого приложения, как вспомогательного инструмента для разбора XML и предоставления его в виде TreeView.
< ' ' >Работать будем сегодня вот с чем:
- модули xmldoc, XMLIntf;
- XML-файл по-сложнее и по-больше
- ну и конечно же TreeView.
Цель нашей работы - сопоставить каждому узлу в XML-документе узел в TreeView и по клику в дереве выводить, например, значения атрибутов узла.
Первыое, что пришло в голову- это сделать запись вида:
type TNodeRecord = record XMLNode: IXMLNode; TrNode: TTreeNode; end;
Так, используя эту запись можно всегда найти узел XML по, например, имени узла в TreeView и наоборот.
Теперь, определим следующие типы данных и класс:
type PTreeView = ^TTreeView; PNodeRecord = ^TNodeRecord; type TNodeList = class(TList) private procedure SetRecord(index: Integer; Ptr: PNodeRecord); function GetRecord(index: Integer): PNodeRecord; public constructor Create; procedure Clear; destructor Destroy; override; property NodeItem[i: Integer]: PNodeRecord read GetRecord write SetRecord; end;
В этом списке мы и будем хранить все наше "богатство". Если потребуется, то можно будет дописать, например дополнительные методы поиска по атрибутам и т.д.
Теперь непосредственно сам класс, реализующий работу с деревом и XML-документом:
type TXMLTree = class private FTreeView: PTreeView;//указатель на дерево FXMLDoc: IXMLDocument;//XML-документ FFileName: string; FNodeList: TNodeList; procedure LoadTopElements; procedure Recurse; public function XMLNodeFromTreeText(const cText: string):IXMLNode; property NodeList: TNodeList read FNodeList; constructor Create(const aFileName:string; aTree:PTreeView); end
На данный момент с использованием класса можно сделать следующее:
- Загрузить XML-документ и постоить дерево TreeView
- Получить список всех узлов
- Получить целиком (вместе с атрибутами) узел XML-документа, которому соответствует узел TreeView c текстом cText
- Загрузить в TreeView только узлы первого уровня.
Дерево TreeView строится при этом рекурсивно:
procedure TXMLTree.Recurse; var iNode: IXMLNode; procedure ProcessNode(Node: IXMLNode; TreeNode: TTreeNode); var cNode: IXMLNode; s: string; NodeRec: PNodeRecord; begin if Node = nil then Exit; s:=Node.NodeName; TreeNode := FTreeView.Items.AddChild(TreeNode, s); New(NodeRec); with NodeRec^ do begin XMLNode:=Node; TrNode:=TreeNode; end; FNodeList.Add(NodeRec); end; cNode := Node.ChildNodes.First; while cNode <> nil do begin ProcessNode(cNode, TreeNode); cNode := cNode.NextSibling; end; end; begin iNode := FXMLDoc.DocumentElement.ChildNodes.First;//стартуем с первого элемента while iNode <> nil do begin ProcessNode(iNode, nil); // Рекурсия iNode:=iNode.NextSibling; end; end;
Можно, конечно, поругаться на рекурсию, типа опасно и т.д., но в данном случае никаких зависаний, залипаний и пр. ошибок быть не должно. Проверял на достаточно сложных документах с большим количеством уровней, узлов и т.д. - работает шустро.
Поиск узла XML-документа по тексту в TreeView осущесвляется следующим образом:
function TXMLTree.XMLNodeFromTreeText(const cText: string): IXMLNode; var LCount: Integer; LList: PPointerList; i:integer; begin LCount:= FNodeList.Count; LList :=FNodeList.List; for i := 0 to LCount - 1 do begin if PNodeRecord(LList[i])^.TrNode.Text=cText then begin Result:=PNodeRecord(LList[i])^.XMLNode; break; end; end; end;
Теперь, что касается вообще работы с объектом. При построении дерева можно как угодно менять название узла в TreeView -функция поиска все равно будет работать.
Ну, а после того, как узел TreeView сопоставлен с IXMLNode - можно делать все что угодно, в т.ч. и читать атрибуты узла.
Кстати, чуть не забыл, те, кто желает ознакомиться с методами работы с приведенным в посте списком TList - приглашаю в этот пост моего блога.
Если Вы всё ещё не знаете как сделать свой сайт без лишних хлопот и учили, то Вам поможет блог bezproblemweb.ru - вс, что Вам необходимо знать: выбор хостинга, регистрация домена и т.д.
Специально для женской аудитории моего блога - материалы для наращивания ногтей на любой вкус и цвет. Все, что Вам необходимо, чтобы Ваши коготки были в порядке и всегда блестели :)
Всерьез заботитесь о своем здоровье? Остеопатия - один из методов традиционной безмедикаментозной медицины должен Вас заинтересовать
-----------------------------
| Делись! | Загружай! | Плюсуй! |
| | |









25 Апр 2010 в 8:48 дп
Что-то я не совсем понял как работает. А можно полный исходник? А то я начал делать, у меня некоторые переменные не видит почему-то.
25 Апр 2010 в 8:58 дп
Можно, как раз собирался оформить полноценный пример и выложить. Наверное сегодня или завтра распишу всё подробненько и выложу все исходники
25 Апр 2010 в 9:04 дп
Спасибо, буду ждать)
09 Июл 2010 в 5:09 пп
Выложите пожалуйста исходники или (что еще лучше) скиньте на
SOV.develop.ua@mail.ru
09 Июл 2010 в 6:25 пп
Исходник выложен давным давно — тут http://www.webdelphi.ru/2010/04/isxodnik-xml2treeview/