Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> XML-парсер. Помогите прочитать тег, находящий в другом теге? 
:(
    Опции темы
navodri
Дата 28.5.2010, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 173
Регистрация: 26.10.2007

Репутация: нет
Всего: -1



Есть XML-файл примерно следующего характера

Код

<weather ver="2.0">
 <dayf>
  <day d="0" t="Friday" dt="May 28">

   <part p="d">
     <icon>12</icon>
   </part>

   <part p="n">
    <icon>16</icon>
   </part>

  </day>
 </dayf>
</weather>


Для его парсинга использую следующую структуру: 

Код

 for i:=1 to GetNodesCountByName(['//weather','//dayf'],'day') do 
  begin
   Label1.Caption := День - ' + GetNodeItemTextFromID(['//weather','//dayf'], i, 't')) + ', ' +  GetNodeItemTextFromID(['//weather','//dayf'], i, 'dt'));

 end;


Всё бы хорошо, если бы небыло тега part, в котором мне надо прочитать номер значка (icon). 
Подскажите, как это сделать?


Ниже представляю код парсера, которым пользуюсь:

Код

unit XMLParser;

interface

uses
  ComObj;

var
 XML: Variant;  //главный объект XML: загружает/сохраняет XML и т.п.

function CreateXML: boolean;
procedure LoadXML(XML_:string); //XML_ - строка_XML или имя_файла или URL
procedure SaveXML(FileName: string);
function GetNodeText(Path: array of string): string;
function GetNodeItemText(Path: array of string; Item:string): string;
function GetNodeItemTextFromID(Path: array of string; ID:integer; Item:string): string;
function GetNodeItemTextByNameFromID(Path: array of string; NodeName:string; ID:integer; Item:string): string;
function GetNodesCount(Path: array of string): integer;//кол-во всех элементов у последнего "нода" в Path
function GetNodesCountByName(Path: array of string;NodeName:string): integer; //кол-во элементов с именем NodeName у последнего "нода" в Path
function GetNodeTextFromID(Path: array of string; ID:integer): string;
function GetNodeTextByNameFromID(Path: array of string; NodeName:string; ID:integer):string;

implementation

function CreateXML: boolean;
begin
 XML := CreateOleObject('Microsoft.XMLDOM');
 XML.async := false; //если true то вроде динамически будет подгружать XML
  Result := (XML.parseError.reason = '');
end;

procedure LoadXML(XML_:string);
begin
 XML.load(XML_);
end;

procedure SaveXML(FileName:string);
begin
 XML.save(FileName);
end;

function GetNodeText(Path:array of string):string;
var
 Node: variant;
 i:integer;
begin
 Node:=XML.documentElement;
 for i:=0 to High(Path) do Node := XML.SelectSingleNode(Path[i]);
 if VarIsEmpty(Node)
  then Result := ''
  else Result := Node.Text;
end;

function GetNodeItemText(Path:array of string;Item:string): string;
var
 Node: variant;
 i: integer;
begin
 Node := XML.documentElement;
 for i:=0 to High(Path) do Node := XML.SelectSingleNode(Path[i]);
 if VarIsEmpty(Node)
  then Result := ''
  else Result := Node.attributes.getNamedItem(Item).text;
end;

function GetNodeItemTextFromID(Path:array of string;ID:integer;Item:string):string;
var
 Node: variant;
 i:integer;
begin
 Node:=XML.documentElement;
 for i:=0 to High(Path) do Node:=XML.SelectSingleNode(Path[i]);
 if VarIsEmpty(Node)
  then Result := ''
  else Result := Node.childNodes.item[ID].attributes.getNamedItem(Item).Text;
end;

function GetNodeItemTextByNameFromID(Path:array of string; NodeName:string; ID:integer; Item:string):string;
var
 Node: variant;
 i:integer;
begin
 Node:=XML.documentElement;
 for i:=0 to High(Path) do Node:=Node.SelectSingleNode(Path[i]);
 if VarIsEmpty(Node)
  then Result := ''
  else Result := Node.SelectNodes(NodeName).item[ID].attributes.getNamedItem(Item).text;
end;

function GetNodesCount(Path:array of string):integer;
var
 Node: variant;
 i:integer;
begin
 Node:=XML.documentElement;
 for i:=0 to High(Path) do Node:=Node.SelectSingleNode(Path[i]);
 if VarIsEmpty(Node)
  then Result := 0
  else Result := Node.childNodes.length;
end;

function GetNodesCountByName(Path:array of string;NodeName:string):integer;
var
 Node: variant;
 i:integer;
begin
 Node:=XML.documentElement;
 for i:=0 to High(Path) do Node:=XML.SelectSingleNode(Path[i]);
 if VarIsEmpty(Node)
  then Result := 0
  else Result:=Node.SelectNodes(NodeName).length;
end;

function GetNodeTextFromID(Path:array of string;ID:integer):string;
var
 Node: variant;
 i:integer;
begin
 Node:=XML.documentElement;
 for i:=0 to High(Path) do Node:=XML.SelectSingleNode(Path[i]);
 if VarIsEmpty(Node)
  then Result := ''
  else Result := Node.childNodes.item[ID].Text;
end;

function GetNodeTextByNameFromID(Path: array of string; NodeName: string; ID: integer): string;
var
 Node: variant;
 i:integer;
begin
 Node:=XML.documentElement;
 for i:=0 to High(Path) do Node:=XML.SelectSingleNode(Path[i]);
  if VarIsEmpty(Node)
  then Result := ''
  else begin
   Node := Node.childNodes.item[ID];
   Result := Node.SelectSingleNode(NodeName).text;
  end;
end;

end.


Это сообщение отредактировал(а) navodri - 28.5.2010, 18:19
PM MAIL WWW   Вверх
navodri
Дата 29.5.2010, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 173
Регистрация: 26.10.2007

Репутация: нет
Всего: -1



Ну, хотя бы намекните, в какую сторону копать?
PM MAIL WWW   Вверх
kuzyara
Дата 29.5.2010, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 215
Регистрация: 13.11.2006

Репутация: нет
Всего: 1



так вам что надо то? 
найти что внутри тега icon находится?

если так, то проще юзать RegExp!
Код

uses RegExpr;
...
with TRegExpr.Create do try
   Expression := '<icon>(.*?)</icon>';
   if Exec (Memo1.Text) then
    REPEAT
      Memo2.Lines.Add(Match [1])
    UNTIL not ExecNext;
  finally Free;
end;
...


--------------------
подпись
PM MAIL   Вверх
navodri
Дата 30.5.2010, 09:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 173
Регистрация: 26.10.2007

Репутация: нет
Всего: -1



Цитата

так вам что надо то? 
найти что внутри тега icon находится?


Именно! Но я не хочу использовать RegExp. Для меня это еще более запутанней. Думаю, модуль XMLParser, представленный выше, может вполне справится с моей задачей. Но моих знаний не хватает. Плиз, помогите!
PM MAIL WWW   Вверх
pseud
Дата 31.5.2010, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 10
Всего: 40



Цитата(navodri @  30.5.2010,  09:35 Найти цитируемый пост)
Думаю, модуль XMLParser, представленный выше, может вполне справится с моей задачей.

Твой парсер с этой задачей не справиться.
Код

iDayCount := GetNodesCountByName(['//weather','//dayf'],'day');
for i := 0 to iDayCount - 1 do 
begin
  Label1.Caption := 'День - ' + GetNodeItemTextFromID(['//weather','//dayf'], i, 't')) + ', ' +  GetNodeItemTextFromID(['//weather','//dayf'], i, 'dt'));
  // здесь необходимо организовать цикл по нодам <part> внутри дня (их несколько, если ты заметил).
  // глядя на код твоего парсера, ясно, что он "вполне" с этим НЕ СПРАВИТСЯ.
end;


Добавлено через 3 минуты и 24 секунды
В Дельфи (в частности, Delphi 6) есть прекрасный парсер TXMLDocument (страница Internet), который точно справится. 
Он инкапсулирует ДомДокумент. 
Ну или можешь в лоб с ДомДокументом работать.


--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
navodri
Дата 1.6.2010, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 173
Регистрация: 26.10.2007

Репутация: нет
Всего: -1



Пишу без визуала, поэтому TXMLDocument не подходит.
А кроме, GetNodeItemTextFromID, в модуле присутствуют и другие функцие.

Цитата

// здесь необходимо организовать цикл по нодам <part> внутри дня (их несколько, если ты заметил).


можно хотя бы ориентировочный пример?
PM MAIL WWW   Вверх
Dom
Дата 1.6.2010, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 7.8.2005

Репутация: 1
Всего: 4



TXMLDocument это не визуальный компонент.
А кроме того есть и бесплатные парсеры - NativeXML например. Весьма шустрый.

Это сообщение отредактировал(а) Dom - 1.6.2010, 16:20
PM MAIL   Вверх
pseud
Дата 1.6.2010, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 10
Всего: 40



Цитата(navodri @  1.6.2010,  15:43 Найти цитируемый пост)
Пишу без визуала, поэтому TXMLDocument не подходит.

не вижу связи
Цитата(navodri @  1.6.2010,  15:43 Найти цитируемый пост)
А кроме, GetNodeItemTextFromID, в модуле присутствуют и другие функцие.

я изучил представленный тобой модуль, потому и написал.
Цитата(pseud @  31.5.2010,  17:56 Найти цитируемый пост)
// глядя на код твоего парсера, ясно, что он "вполне" с этим НЕ СПРАВИТСЯ.

может ты его представил не целиком.
Цитата(navodri @  1.6.2010,  15:43 Найти цитируемый пост)
можно хотя бы ориентировочный пример? 

на базе твоего парсера? не хватает функционала.


--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
navodri
Дата 1.6.2010, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 173
Регистрация: 26.10.2007

Репутация: нет
Всего: -1



ладно. понял. тогда на базе любого функционала можете представить код, который прочитает значение <icon> в  <part p="d"> и в <part p="n"> ?
PM MAIL WWW   Вверх
pseud
Дата 1.6.2010, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 10
Всего: 40



вот пример разбора твоего xml компонентом TXMLDocument.
модуль целиком рабочий (Delphi 6).
Код

unit Unit2;

interface

uses
  Classes;

procedure DoExample(AOwner: TComponent);

implementation

uses
  XMLDoc, XMLIntf;

procedure DoExample(AOwner: TComponent);
var
  i: Integer;
  doc: TXMLDocument;
  nodeRoot: IXMLNode;
  nodeDay: IXMLNode;
  nodePart: IXMLNode;
  iDay: Integer;
  iDayCount: Integer;
  iPart: Integer;
  iPartCount: Integer;
  iIcon: Integer;
  s: string;
begin
  doc := TXMLDocument.Create(AOwner);
  try
    with doc.XML do
    begin
      Add('<weather ver="2.0">');
      Add(' <dayf>');
      Add('  <day d="0" t="Friday" dt="May 28">');
      Add('   <part p="d">');
      Add('    <icon>12</icon>');
      Add('   </part>');
      Add('   <part p="n">');
      Add('    <icon>16</icon>');
      Add('   </part>');
      Add('  </day>');
      Add(' </dayf>');
      Add('</weather>');
    end;
    doc.Active := True;

    nodeRoot := doc.DocumentElement.ChildNodes.Nodes['dayf'];

    iDayCount := nodeRoot.ChildNodes.Count;
    for iDay := 0 to iDayCount - 1 do
    begin
      // действия с днем
      nodeDay := nodeRoot.ChildNodes.Nodes[iDay];
      iPartCount := nodeDay.ChildNodes.Count;
      for iPart := 0 to iPartCount - 1 do
      begin
        // действия с временем суток
        nodePart := nodeDay.ChildNodes.Nodes[iPart];
        iIcon := nodePart.ChildNodes.Nodes['icon'].NodeValue;
        // действия с номером иконки
      end;
    end;

    doc.Active := False;
  finally
    doc.Free;
  end;
end;

end.



--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
navodri
Дата 2.6.2010, 07:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 173
Регистрация: 26.10.2007

Репутация: нет
Всего: -1



Спасибо. Буду разбиратся.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0524 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.