Несмотря на то, что тема работы с XML в Delphi довольно широко обсуждалась в Интернете, вопросы на эту тему довольно часто возникают на всевозможных форумах.
Я тоже уже писал по этому поводу, но хотел бы вернуться к реальному случаю быстрого разбора XML файла и извлечения данных, который я сегодня проделал на работе. Получение необходимых данных у меня заняло не более 5 минут времени.
Предыстория. Сегодня понадобилось обработать данные об установленных программах на компьютерах пользователей (да, да, пиратов выявляем :)). Технический отдел предоставил мне такую информацию содраную с ничего не подозревающих пользователей по сети с использованием WMI. Программа, которой они пользовались выдает отчеты в формате XML. Соответственно - мне притащили гору XML файлов с довольно сложной структурой из которых мне необходимо было вытащить только название установленных программных продуктов.
Обработка. Просмотрев пару файлов вручную, понял что так и состариться не долго, и решил написать небольшой конвертер. Запустив Delphi - выбрал в репозитарии объект XML DataBinding и скормил ему один из файлов. Все настройки и параметры я оставил по умолчанию и в результате у меня сформировался модуль с большим количеством классов и интерфейсов для доступа к элементам этого XML файла. Я не стал долго разбираться со структурой классов, сразу же перешел к написанию конвертера.
В новом консольном приложении написал довольно простой код:
program XML2TXT;
uses
Forms,
Classes, SysUtils,
SoftwareXML in 'SoftwareXML.pas';
procedure CovertXML2Text;
var
softbase : IXMLSTDSoftwareType;
i: integer;
sr: TSearchRec;
CurDir: string;
ExportFile: TStringList;
begin
CurDir := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName));
if FindFirst(CurDir+'*.xml', faAnyFile, sr) = 0 then
repeat
ExportFile := TStringList.Create;
softbase := LoadSTDSoftware(Pchar(CurDir+sr.Name));
for i := 0 to softbase.InstalledSoftware.source.software.Count - 1 do
ExportFile.Add(softbase.InstalledSoftware.source.software[i].DisplayName);
ExportFile.Sort;
ExportFile.SaveToFile(CurDir + softbase.InstalledSoftware.Source.servername+'.txt');
ExportFile.Free;
until FindNext(sr) <> 0;
end;
begin
Application.Initialize;
CovertXML2Text;
end.
В результате которого у меня образовался по одному текстовичку на каждый компьютер в сетке, содержащий список установленного ПО.
Чувствую что данный код потребует пояснений. Например, зачем я в консольном приложении использовал модуль Forms и вызывал процедуру Application.Initialize;?
На самом деле все просто - это небольшой хак, позволяющий использовать XML Data Binding в консольном приложении. Потому как в нем упорно отказывался инициализироваться класс для работы с XML. В истинных причинах пока не разбирался - сегодня было важно время, я и так 4 из 5 минут потратил на борьбу с этой ошибкой. :) Думаю позже разобраться с этой проблемой и написать в чем истинная причина.
Странный класс softbase был создан на основе XML файла - так назывался корневой элемент, а softbase.InstalledSoftware.source.software[i].DisplayName - просто навигация по вложенным элементам до нужного и получение его значения.
Вот собственно так выглядит один из самых быстрых способов работы с XML в Delphi.
"...хотел бы вернуться к реальному случаю быстрого разбора XML файла и извлечения данных, который я сегодня проделал на работе. Получение необходимых данных у меня заняло не более 5 минут времени..."
ОтветитьУдалитьЕсть БД в XML. Размер около 30 мб. Нужно разобрать по запчастям. Насколько быстрым будет процесс? Час, два,.. десять?.. А оно вообще вывезет такой объем?
Если отдавать парсеру этот файл полностью - то есть шанс, что этот процесс будет вечным :)
ОтветитьУдалитьМожно поступить так: вычленить из файла структуру документа, и уже этот файл со структурой анализировать - получится в разы быстрее и эффективнее. Тем более что эта функция в первую очередь предназначена для генерации иерархии классов из схемы документа, а остальное - так, дополнительная возможность.
Перед использованием любой функции СОМ необходимо инициализоровать библиотеку СОМ. Модуль Form неявно делает вызов этих методов из метода Application.Initialize. В консольных программах это нужно делать самому:
ОтветитьУдалитьinitialization
CoInitialize(nil);
finalization
CoUnInitialize;
А где функция "LoadSTDSoftware"? Самое интересное то в ней! У меня она не генериться сама и я не могу загрузить данные :(
ОтветитьУдалить[cite]Kozer пишет:
ОтветитьУдалить13 ноября 2009 г. 21:53
Перед использованием любой функции СОМ необходимо инициализоровать библиотеку СОМ. Модуль Form неявно делает вызов этих методов из метода Application.Initialize. В консольных программах это нужно делать самому:
initialization
CoInitialize(nil);
finalization
CoUnInitialize;[/cite]
Можно и проще сделать.
в uses добавляем вот этот модуль OleAuto
а в папку с программой вот эти три файлика:
Ole2.pas
OleAuto.pas
OleCtl.pas
По идее файлы наверное и сами найдутся если Делфи одна на компе, просто у меня две версии и при компиляции берутся dcu от другой версии :)
А да OleAuto, вроде как должен быть объявлен первым в списке. :)
Все. OLE грузится автоматом.