Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 6 211

/ вопрос закрыт /

Здравствуйте, уважаемые эксперты!

Каким образом осуществляется поиск по xml документу?
использую ECXMLParser.
заранее не знаю структуру всего документа

вот например документ в котором мне надо найти пароли всех пользователей ну или имена всех групп пользователей....

Приложение:
  1. <?xml version="1.0" encoding="cp1251"?>
  2. <dbBuilder>
  3. <measures>
  4. <measure id="11" name="A" />
  5.  
  6.  
  7. </measures>
  8.  
  9. <structure>
  10. <users>
  11.  
  12. tcallowed="1" blockallowed="1" />
  13. </users>
  14.  
  15. <usergroups>
  16.  
  17.  
  18. </usergroups>
  19.  
  20. <Districts>
  21.  
  22. </Districts>
  23.  
  24. <IPAddresses>
  25. <IPAddress ID="11" DAServerID="11" EthID="1" IPAddr="192.168.3.127" />
  26. </IPAddresses>
  27. </structure>
  28. </dbBuilder>


yuta_86 Вопрос закрыт (ответы не принимаются, мини-форум закрыт)

Вопрос задал: yuta_86 (статус: Посетитель)
Вопрос отправлен: 26 июня 2012, 15:24
Состояние вопроса: закрыт, ответов: 1.

Ответ #1. Отвечает эксперт: min@y™

// Процедура рекурсивного поиска всех XML-подузлов внутри узла AParentItem,
// имеющих имя AName. Найденные подузлы помещаются в список AResults,
// который перед вызовом процедуры надо очистить.
procedure FindItems(AParentItem: TXMLItem; const AName: string; AResults: TList);
var
  Index: Integer;
begin
  for Index:= 0 to AParentItem.Count - 1 do
    begin
      if AParentItem[Index].Name = AName // проверка имени
        then AResults.Add(AParentItem[Index]); // добавление в список
      if AParentItem[Index].Count <> 0 // если есть подузлы, то...
        then FindItems(AParentItem[Index], AName, AResults); // поиск в подузлах (рекурсия)
    end;
end;
 
// Пример вызова:
var
  Items: TList;
  Index: Integer;
  Item: TXMLItem;
begin
  Items:= TList.Create();
  try
    FindItems(Parser.Root, 'user', Items); // поиск
 
    for Index:= 0 to Items.Count - 1 do
      begin
        Item:= TXMLItem(Items[Index]);
        // <--- тут - требуемая работа с найденными подузлами
      end;
  finally
    Items.Free();
  end;
end;
 
// Ахтунг! Код не отлаживал, писал на заборе! :)

По аналогии с этой процедурой можно сделать поиск по именам и/или значениям параметров узлов.

Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 26 июня 2012, 15:56


Мини-форум вопроса

Всего сообщений: 11; последнее сообщение — 27 июня 2012, 13:15; участников в обсуждении: 2.

26 июня 2012, 16:01: Вопрос перемещён из тематического раздела Delphi » Прочее в раздел Delphi » Работа с компонентами и библиотеками модератором DNK

yuta_86

yuta_86 (статус: Посетитель), 26 июня 2012, 16:37 [#1]:

а вытаскивать значение параметра так?

Item.Params[0] ? если ищем user то будет значение id=11 а как получить значение 11

можно ли как-то сделать типа

edit1.text:=Item.params['id'].value ))
min@y™

min@y™ (статус: Доктор наук), 26 июня 2012, 16:51 [#2]:

Цитата (yuta_86):

а вытаскивать значение параметра так?

Вот тебе мой самодельный модуль. Там всё для этого есть.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
yuta_86

yuta_86 (статус: Посетитель), 26 июня 2012, 17:04 [#3]:

модуль очень полезен..... меня удивляет как вы до этого дошли ведь описания TECXMLParser вообще нет ведь....
yuta_86

yuta_86 (статус: Посетитель), 26 июня 2012, 17:04 [#4]:

СПАСИБО
min@y™

min@y™ (статус: Доктор наук), 26 июня 2012, 21:00 [#5]:

Цитата (yuta_86):

меня удивляет как вы до этого дошли ведь описания TECXMLParser вообще нет ведь.

А нахрена мне описание, когда исходники и демо-примеры есть? К тому же имена свойств и методов несут хорошую смысловую нагрузку.

Цитата (yuta_86):

СПАСИБО

Пива достаточно.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
yuta_86

yuta_86 (статус: Посетитель), 27 июня 2012, 10:50 [#6]:

вот я нашёл элемент это всё гуд. а как теперь заменить в нём значение параметра?
например
поменять Диспетчеры на что-то другое?
min@y™

min@y™ (статус: Доктор наук), 27 июня 2012, 11:16 [#7]:

Допустим, что ты нашёл элемент и записал его адрес в переменную Item: TXMLItem.
Параметры хранятся в свойстве TXMLItem.Params: TStrings в формате имя_параметра="значение". Для изменения значения воспользуйся свойством TStrings.Values[const Name: string]: string;

Цитата (yuta_86):

например поменять Диспетчеры на что-то другое?

Для твоего примера:
Item.Params.Values['name']:= 'Уборщицы';
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
yuta_86

yuta_86 (статус: Посетитель), 27 июня 2012, 11:27 [#8]:

да это понятно но дело в том что если я хочу сохранить результаты в тот же файл.
min@y™

min@y™ (статус: Доктор наук), 27 июня 2012, 11:48 [#9]:

Цитата (yuta_86):

да это понятно но дело в том что если я хочу сохранить результаты в тот же файл.

И что? Загрузил файл, изменил что нужно, сохранил файл. Какие тут могут быть проблемы?
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
yuta_86

yuta_86 (статус: Посетитель), 27 июня 2012, 12:05 [#10]:

да верно.... правильно сделал так

Parser := TECXMLParser.Create(Self);
Parser.Clear;
Parser.LoadFromFile('1.xml');
Items:= TList.Create();
try
Form1.FindItems(Parser.Root, 'usergroup', Items); // поиск
Item:=TXMLItem(Items[0]);
Item.Params.Values['name']:= 'Уборщицы';
Item.Params.Values['id']:= '123';
finally
Items.Free();
end;
Parser.SaveToFile('1.xml');

в данном случае для первой записи. так должно быть? замечания или предложения есть?
min@y™

min@y™ (статус: Доктор наук), 27 июня 2012, 13:15 [#11]:

Цитата (yuta_86):

замечания или предложения есть?

Есть:
Parser := TECXMLParser.Create(Self); // заменить Self на nil
Parser.Clear;                        // убрать эту строку
Parser.LoadFromFile('1.xml');
Items:= TList.Create();
try
  Form1.FindItems(Parser.Root, 'usergroup', Items); // поиск
  Item:=TXMLItem(Items[0]); // здесь получишь Access Violation, если ничего не найдено
  Item.Params.Values['name']:= 'Уборщицы';
  Item.Params.Values['id']:= '123';
finally
  Items.Free();
end;
 
Parser.SaveToFile('1.xml');
 
// добавить убиение парсера, а то утечка памяти будет.

Я бы сделал примерно вот в таком духе:
function TForm1.ChangeParam: Boolean;
var
  Parser: TECXMLParser;
begin
  Parser:= TECXMLParser.Create(nil);
  Items:= TList.Create();
  Result:= True;
  try
    try
      Parser.LoadFromFile('1.xml');
    except
      Result:= False;
    end;
 
    if not Result
      then Exit;
 
    FindItems(Parser.Root, 'usergroup', Items); // поиск
 
    if Items.Count <> 0
      then with TXMLItem(Items[0]).Params do
             begin
               Values['name']:= 'Уборщицы';
               Values['id']:= '123';
             end;
 
    try
      Parser.SaveToFile('1.xml');
    except
      Result:= False;
    end;
  finally
    Items.Free();
    Parser.Free();
  end;
end;

Цитата (yuta_86):

в данном случае для первой записи.


А что делать, если найдено несколько записей - решай сам.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!

30 июля 2012, 12:30: Вопрос закрыт (решение принял DNK): на первый взгляд вопрос исчерпан

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:37
Выполнено за 0.03 сек.