Про структуру RSS я уже писала. Задача сводится к малому: пройтись по всем записям, разобрать их элементы и представить в виде дерева "Адрес RSS — Записи".
Для достижения своих целей будем оперировать данными типов IXMLNode и IXMLNodeList.
nd : IXMLNode;
firstTier : IXMLNodeList;
DocumentElement — возвращает корневой объект документа.
childNodes — возвращает список прямых потомков вершины. Далее с дочерними узлами можно работать просто как с элементами списка. Например, узнать имя узла, можно будет firstTier[i].NodeName.
Итак, исследуем код RSS-фида, который генерируется feedburner-ом. Видим, что самый простой способ получить все записи, — это из списка узлов первого уровня выбрать узлы с именем entry, а потом каждый из этих узлов обработать (выделить нужные нам дочерние узлы content, published (дата публикации) и link (у узла link нам понадобится значение атрибута href)).
XMLDocument1.FileName := 'MyRSSFeed.xml';
XMLDocument1.Active := true;
nd := XMLDocument1.DocumentElement;
TreeView1.Items.AddChild(nil,edtRSSURL.Text);
firstTier := nd.childNodes;
for i := 0 to firstTier.Count-1 do
begin
if firstTier[i].NodeName = 'entry' then
begin
nd := firstTier[i];
ProcessItem();
end;
end;
Что касается обработки записей. Все просто со значениями узлов с именами content и published, так как такие узлы встречаются один раз. А вот узлов с именем link встречается несколько.
<link rel="replies" type="application/atom xml" href="http://mama-karlo.blogspot.com/feeds/6599339245902184370/comments/default" title="..." />
<link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=29395559131211965&postID=6599339245902184370" title="..." />
<link rel="edit" type="application/atom xml" href="http://www.blogger.com/feeds/29395559131211965/posts/default/6599339245902184370?v=2" />
<link rel="self" type="application/atom xml" href="http://www.blogger.com/feeds/29395559131211965/posts/default/6599339245902184370?v=2" />
<link rel="alternate" type="text/html" href="http://mama-karlo.blogspot.com/2008/12/blog-post_16.html" title="..." />
Нам нужно выбрать только тот узел, у которого значение атрибута rel равно alternate. В итоге получаем код:
type
PRSSFeedData = ^TRSSFeedData;
TRSSFeedData = record
URL : string;
Description : string;
Date : string;
end;
procedure ProcessItem();
var
rssFeedData : PRSSFeedData;
tn : TTreeNode;
title : string;
j : integer;
begin
New(rssFeedData);
title := nd.ChildNodes.FindNode('title').Text;
with nd.ChildNodes do
begin
rssFeedData.Description := FindNode('content').Text;
rssFeedData.Date := FindNode('published').Text;
end;
for j := 0 to nd.ChildNodes.Count-1 do
if (nd.ChildNodes[j].NodeName = 'link') and (nd.ChildNodes[j].GetAttribute('rel') = 'alternate') then
begin
rssFeedData.URL := nd.ChildNodes[j].GetAttribute('href');
break;
end;
tn := TreeView1.Items.AddChild(TreeView1.Items.GetFirstNode, title);
tn.Data := rssFeedData;
end;
Вот небольшое приложение, на примере которого можно поразбираться, как все работает.
Исходники можно скачать здесь.
P.S. Спасибо благодарным читателям, которые шлют на пиво! %D
Не универсальным дерево получилось-то...оказывается фидбёрнер фидбернеру рознь. Сейчас смотрю XML-схему для feed2 от Гугля - там получается, что узел с описанием статьи находится на уровень ниже, чем в этом примере узел entry. Получается, что теперь так с ходу к нужному узлу и не попасть? Только перебирать все узлы в поисках нужного, а потом с ним работать?
ОтветитьУдалитьПривет! Да, код не универсальный, об универсальности я и не говорила. Я просто привела пример конкретно для фида, генерируемого фидбернером. Некоторые сайты генерируют фиды по-своему. Фидбернер их более-менее приводил к одному виду. С переносом фида на гугль - надо брать фид и изучать. К сожалению, мне сейчас этим заняться некогда, но я уверена, что данные там систематизированы не хуже ;)
ОтветитьУдалить