RSS p°φmo z webu pomocφ .NET t°φdy SgmlReader
RSS kanßl je standardnφm dopl≥kem dneÜnφch webzin∙. P°esto mezi nimi existujφ ΦernΘ ovce, kterΘ tuto technologii zarputile ignorujφ, nebo dokonce odmφtajφ. Vytvo°me pro n∞ tedy parazitnφ RSS kanßl v prost°edφ Visual Studio .NET.
V tomto Φlßnku budou popsßny techniky, kterΘ lze vyu₧φt nejen na vytvß°enφ RSS kanßl∙, ale obecn∞ pro jakΘkoli sbφrßnφ dat z www strßnek. Myslφm si, ₧e Φtenß°i Intervalu jsou na ·rovni a nebudou tyto dovednosti zneu₧φvat proti v∙li autor∙ web∙. Jß jsem si jako testovacφ web vybral magazφn Interval.cz, a to i p°esto, ₧e ji₧ mß sv∙j vlastnφ RSS kanßl.
Princip
V²sledkem prßce bude webovß aplikace, kterou m∙₧ete umφstit nap°φklad na svΘm poΦφtaΦi, nebo kdekoli na svΘm serveru. Jejφm prvnφm ·kolem je sta₧enφ obsahu vybranΘ (nejspφÜe titulnφ) strßnky webzinu, kterß (pokud mo₧no) obsahuje seznam Φlßnk∙ Φi spot∙ vΦetn∞ n∞jak²ch p°φpadn²ch dopl≥kov²ch informacφ (perex, jmΘno autora Φi datum vydßnφ). Z obsahu strßnky je pomocφ knihovny SgmlReader zφskßn XmlDocument, z n∞ho₧ ji₧ XML transformacφ vytßhneme po₧adovanΘ data a zpracujeme do RSS kanßlu. To je vÜe. Tak₧e jdeme na to!
Sta₧enφ dat a SgmlReader
Zalo₧φme nov² projekt typu ASP.NET Web Application a v n∞m vytvo°φme strßnku rss.aspx. Jejφ HTML k≤d bude velmi jednoduch², bude obsahovat pouze komponentu Xml, do kterΘ ho se budou naΦφtat vstupnφ data pro kanßl, a kterß bude nad t∞mito daty provßd∞t transformaci. Proto vytvo°φme transformaΦnφ stylesheet data.xslt, kter² prozatφm ponechßme prßzdn², a na°φdφme komponent∞, aby jej pou₧φvala pomocφ atributu TransformSource. Musφme takΘ nastavit v²stupnφ MIME typ strßnky na text/xml, abychom sv∞tu sd∞lili, ₧e naÜe strßnka generuje data ve formßtu XML.
ContentType="text/xml" Inherits="interval.rss" %>
<asp:Xml id="data" TransformSource="data.xslt"
runat="server"></asp:Xml>
N∞kolikrßt zde byla zmφn∞na knihovna SgmlReader. O co krßΦφ? Jak vφme, .NET Framework poskytuje sadu t°φd pro zpracovßnφ XML dokument∙. Celß °ada web∙ je vÜak psßna ve starΘm (a Φasto nevalidnφm) HTML, a mß dost daleko do XHTML (co₧ je vlastn∞ implementace XML). Obsah t∞chto web∙ tedy nelze t∞mito t°φdami p°φmo zpracovat. SgmlReader je t°φda, kterß d∞dφ z XmlReader, tak₧e poskytuje standardnφ rozhranφ pro Φtenφ Xml dokument∙, avÜak spokojφ se i s pom∞rn∞ "sprasen²m k≤dem". Voliteln∞ lze zapnout logovßnφ nalezen²ch chyb, ovÜem ty mohou b²t ignorovßny, resp. vhodn²m zp∙sobem kompenzovßny. SGML je standard, ze kterΘho vychßzφ HTML i XML a je to pom∞rn∞ star² a velmi tolerantnφ znaΦkovacφ jazyk. SgmlReader je jeÜt∞ tolerantn∞jÜφ. Nejd°φve si tedy tuto knihovnu stßhn∞te, rozbalte, a projekt SgmlReaderDll.csproj ze slo₧ky SgmlReader\SgmlReaderDll p°idejte do naÜφ aplikace (solution). Nezapome≥te tento projekt takΘ p°idat mezi reference naÜeho ASP.NET projektu.
T°φda SgmlReader jako sv∙j vstup oΦekßvß TextReader, tak₧e budeme muset data z HTTP odpov∞di dek≤dovat n∞jak²m k≤dovßnφm, abychom zφskali z binßrnφch dat jejich textovou reprezentaci. Jak zjistφme, v jakΘm k≤dovßnφ je HTML strßnka zapsßna? To je docela oÜemetnß zßle₧itost, proto₧e tato informace se m∙₧e ukr²vat bu∩ v XHTML hlaviΦce, nebo ve znßmΘm META elementu. Programov∞ tyto informace zφskat nenφ prßv∞ hraΦka. Jsme v bezradnΘ situaci. Abychom mohli data p°edat SgmlReaderu, pot°ebujeme v nich najφt specifikaci k≤dovßnφ, tak₧e musφme nejd°φve strßnku analyzovat, a k tomu nejlΘpe slou₧φ prßv∞ SgmlReader. Je to vlastn∞ bludn² kruh.
NaÜt∞stφ tento ·kol je °eÜiteln², a °eÜenφ je ukryto op∞t v tΘto nesmφrn∞ u₧iteΦnΘ knihovn∞. Zapßtrßme-li d∙kladn∞ji ve jmennΘm prostoru Sgml, mo₧nß zavadφme pohledem o t°φdu HtmlStream. Ten nßzev znφ velmi slibn∞, nemyslφte? Tato t°φda d∞dφ z TextReaderu (vzpome≥te si, jde o vy₧adovan² vstupnφ formßt pro SgmlReader), a jejφ konstruktor mß dva parametry: jeden typu Stream (lze p°φmo napojit v²stup z WebResponse), a druh² se naz²vß defaultEncoding a jde o k≤dovßnφ znak∙, kterΘ je pou₧ito implicitn∞, pokud nenφ nalezena explicitnφ definice ve strßnce. Celß t°φda mß podstatnou nev²hodu: je deklarovßna jako internφ, tak₧e ji nelze pou₧φt v naÜem projektu. ZdrojovΘ k≤dy mßme (SgmlParser.cs), nenφ tedy nic snazÜφho, ne₧ p°epsat v hlaviΦce deklarace tΘto t°φdy klφΦovΘ slovo internal na public. Pak projekt SgmlReaderu zkompilujte.
Nynφ tedy znßme zp∙sob, jak z k≤du libovolnΘ strßnky m∙₧eme zφskat XmlReader. NapiÜme si tedy funkci, kterß nßm stßhne XmlDocument z URL adresy p°edanΘ parametrem jako °et∞zec. Takovou funkce bude jist∞ znovupou₧itelnß v ·pln∞ jin²ch projektech. P°ejd∞me do k≤du strßnky a nadeklarujme pot°ebnΘ jmennΘ prostory:
using System.Net;
using System.IO;
using System.Xml;
using System.Text;
A nynφ ji₧ slφbenß metoda:
{
// http po₧adavek
WebRequest request = WebRequest.Create(url);
WebResponse response = request.GetResponse();
TextReader stream = new HtmlStream(
response.GetResponseStream(),
Encoding.GetEncoding("iso-8859-2"));
// zpracovßnφ SgmlReaderem do stringu
SgmlReader reader = new SgmlReader();
reader.InputStream = stream;
reader.DocType = "HTML";
StringWriter str = new StringWriter();
XmlTextWriter xml = new XmlTextWriter(str);
reader.Read();
while(!reader.EOF)
{
xml.WriteNode(reader,true);
}
xml.Flush();
xml.Close();
response.Close();
stream.Close();
// naΦtenφ stringu do XmlDocumentu
XmlDocument data = new XmlDocument();
data.LoadXml(str.ToString());
return data;
}
Mo₧nß vßs p°ekvapilo, ₧e data z XmlReaderu do XmlDocumentu cestujφ pon∞kud krkolomn∞ uzel po uzlu p°es XmlWriter do stringu, a ten je pak cel² naΦten do DOM struktury. ProΦ to, kdy₧ by jist∞ bylo mnohem jednoduÜÜφ a takΘ v²konn∞jÜφ vyu₧φt p°etφ₧enou metodu XmlDocumentu Load, jejφ₧ jedna varianta p°φmo Φte z XmlReaderu? Tedy jednoduÜe takto:
Je to proto, ₧e XmlDocument nenφ z mi neznßmΘho d∙vodu se SgmlReaderem zcela kompatibilnφ. Zkuste a uvidφte. XmlDocument z°ejm∞ neuznß posloupnost naΦten²ch XML uzl∙ za sprßvnou. Mo₧nß jsem n∞co p°ehlΘdl, a problΘm lze vy°eÜit jinak, ovÜem spolehliv∞ mi fungoval pouze dotyΦn² obchvat p°es string.
Nynφ naÜi metodu pou₧ijeme k naΦtenφ strßnky z Intervalu a jejφmu p°edßnφ do Xml komponenty data. Tuto akci provedeme v t∞le oblφbenΘ metody Page_Load.
{
data.Document = GetPage("http://interval.cz/");
}
Transformace
KoneΦn∞ jsme v poslednφ etap∞ projektu. Strßnku mßme ve snadno zpracovatelnΘm tvaru, napsßnφ XSL transformace je ji₧ trivialita. Webovß strßnka je nynφ vydßna na milost (Φi nemilost) vaÜim XPath v²raz∙m. Je jen na Vßs, kolik informacφ z nφ zvlßdnete vydolovat. Nßsledujφcφ p°φklad generuje jen pßr zßkladnφch RSS element∙, ovÜem vy samoz°ejm∞ m∙₧ete jφt dßle a vytvo°it pro svou RSS ΦteΦku pon∞kud komplexn∞jÜφ stravu.
<xsl:stylesheet version="1.0"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="xsl html">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<rss version="2.0">
<channel>
<title>
<xsl:value-of select="//html:title" />
</title>
<xsl:for-each
select="//html:div[@class='anotation']">
<item>
<title>
<xsl:value-of
select=".//html:h2" />
</title>
<link>
<xsl:text>http://interval.cz/</xsl:text>
<xsl:value-of
select=".//html:h2/html:a/@href" />
</link>
<description>
<xsl:value-of
select=".//html:p" />
</description>
</item>
</xsl:for-each>
</channel>
</rss>
</xsl:template>
</xsl:stylesheet>
K dispozici jsou vßm kompletnφ zdrojovΘ k≤dy aplikace.
Odkazy a zdroje
- Kompletnφ pr∙vodce XSLT (Interval.cz)
- Transformace XSL ASP.NET ve struΦnosti - Radek Jφcha (Interval.cz, 5. 8. 2004)
- XML v ASP.NET - naΦφtßnφ dat v C# - Radek Jφcha (Interval.cz, 8. 8. 2004)
Syndikace obsahu - formßty, techniky, v²voj
Syndikace obsahu je modernφ metodou sdφlenφ velk²ch objem∙ rychle se m∞nφcφch informacφ na internetu. Soubor naÜich text∙ popisuje specifikace jednotliv²ch formßt∙ a nßstroje pro prßci s daty v nich p°edßvan²mi. Tato sΘrie Φlßnk∙ ji₧ byla uzav°ena, aΦkoli dalÜφ pokraΦovßnφ nelze vylouΦit.
- RSS p°φmo z webu pomocφ .NET t°φdy SgmlReader (prßv∞ Φtete)
- Atom 0.3
- RSS 2.0
- Tvorba RSS v PHP
- P°ehled Φlßnk∙ z RSS ve strßnce ASP
- Generujeme RSS pomocφ Repeateru v ASP.NET
- P°ehled Φlßnk∙ z RSS ve strßnce ASP.NET
- RSS? RSS!