Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/TclHttpd+RSS+Processing?V=32
QUERY_STRINGV=32
CONTENT_TYPE
DOCUMENT_URI/revision/TclHttpd+RSS+Processing
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.131.151
REMOTE_PORT29438
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR3.145.52.86
HTTP_CF_RAY8769cd5c0e4a2d58-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
HTTP_CF_CONNECTING_IP3.145.52.86
HTTP_CDN_LOOPcloudflare
HTTP_CF_IPCOUNTRYUS

Body


Error

Unknow state transition: LINE -> END

-code

1

-level

0

-errorstack

INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit {TclHttpd RSS Processing} \[WJR\]\ -\ There\ was\ a\ discussion\ on\ the\ \[TclHttpd\]\ mailing\ list\ about\ processing\ \[RSS\].\ Here's\ a\ variant\ I\ came\ up\ with\ using\ \[tDOM\]\ and\ \[The\ Tcler's\ Wiki\]\ RSS\ feed\ (it\ should\ work\ with\ any\ RSS\ feed):\n======tcl\n\[Doc_Dynamic\]\n\ \n\[\npackage\ require\ http\npackage\ require\ tdom\n\ \nhtml::set\ token\ \[http::geturl\ http://wiki.tcl.tk/rss.xml\]\nhtml::set\ rss_xml\ \[http::data\ \$token\]\n\ \nhtml::set\ doc\ \[dom\ parse\ \$rss_xml\]\nhtml::set\ root\ \[\$doc\ documentElement\]\nhtml::set\ stories\ \[\$root\ selectNodes\ /rss/channel/item\]\n\]\n\ \n\[html::head\ \{RSS\ Example\}\]\n\ \n\ <style\ type=\"text/css\">\n\ \ \ \ \ body\ \{\n\ \ \ \ \ \ \ \ \ font-family:\ Arial,\ Helvetica,\ sans-serif\;\n\ \ \ \ \ \ \ \ \ font-size:\ 80%\;\n\ \ \ \ \ \}\n\ \ \ \ \ h1\ \{\n\ \ \ \ \ \ \ \ \ background:\ #f7f7f7\;\n\ \ \ \ \ \ \ \ \ padding:\ 4px\;\n\ \ \ \ \ \}\n\ \ \ \ \ dt\ \{\n\ \ \ \ \ \ \ \ \ font-size:\ 120%\;\n\ \ \ \ \ \ \ \ \ font-weight:\ bold\;\n\ \ \ \ \ \}\n\ \ \ \ \ dd\ \{\n\ \ \ \ \ \ \ \ \ margin:\ 10px\;\n\ \ \ \ \ \}\n\ \ \ \ \ #date\ \{\n\ \ \ \ \ \ \ \ \ color:\ #999999\;\n\ \ \ \ \ \}\n\ </style>\n\ \n\[html::bodyTag\]\n\ \n\[html::h1\ \{RSS\ Example\}\]\n\ \n\ <dl>\n\ \ \ \ \ \[html::foreach\ story\ \$stories\ \{\n\ \ \ \ \ \ \ \ \ <dt>\n\ \ \ \ \ \ \ \ \ \ \ \ \ <a\ href=\"\[\[\$story\ selectNodes\ link/text()\]\ nodeValue\]\">\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \[\[\$story\ selectNodes\ title/text()\]\ nodeValue\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ </a>\n\ \ \ \ \ \ \ \ \ \ \ \ \ <span\ class=\"date\">\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (\[\[\$story\ selectNodes\ pubDate/text()\]\ nodeValue\])\n\ \ \ \ \ \ \ \ \ \ \ \ \ </span>\n\ \ \ \ \ \ \ \ \ </dt>\n\ \ \ \ \ \ \ \ \ <dd>\[\[\$story\ selectNodes\ description/text()\]\ nodeValue\]</dd>\n\ \ \ \ \ \}\]\n\ </dl>\n\ \n\[html::end\]\n======\n\[tDOM\]\ and\ \[TclHttpd\]\ makes\ this\ pretty\ simple!\n\n----\n\n\[DG\]\ --\ That\ little\ starter\ script\ got\ me\ going.\ \ I\ was\ messing\ with\ \[TclXML\]\ at\ first,\ but\ \[tDOM\]\ is\ a\ whole\ lot\ easier\ to\ use.\ \ See\ it\ in\ action\ \[http://www.pobox.com/~davygrvy/news.tml\]\n======\n#\ tmlrss.tcl\ --\n#\n#\ \ \ \ Process\ RSS\ (0.91,\ 0.92,\ 0.93,\ 1.0,\ 2.0)\ newsfeeds\ into\n#\ \ \ \ 4.01\ HTML.\ \ For\ use\ in\ .tml\ templates\ with\ tclhttpd.\n#\n#\ \ \ \ http://www.xml.com/pub/a/2002/12/18/dive-into-xml.html\n#\ \ \ \ http://blogs.law.harvard.edu/tech/rss\n#\ \ \ \ http://www.tdom.org/\n#\ \ \ \ \n#\ \ \ \ Instructions:\n#\ \ \ \ \ \ \ \ 1)\ place\ this\ file\ in\ your\ tml\ library\ directory\ so\n#\ \ \ \ \ \ \ \ the\ server\ sources\ it\ automatically\ at\ startup.\n#\ \ \ \ \ \ \ \ 2)\ Call\ TmlRss_GenHTML\ with\ the\ url\ of\ the\ RSS\ feed\n#\ \ \ \ \ \ \ \ from\ your\ .tml\ file\ (set\ to\ dynamic\ generation).\n#\ \ \ \ \ \ \ \ This\ function\ returns\ the\ formatted\ HTML\ of\ the\ feed.\n#\n#\ \ \ \ By\ David\ Gravereaux\ <[email protected]>\n#\n\n\ package\ provide\ tmlrss\ 0.2\n\n\ package\ require\ httpd\n\ package\ require\ http\n\ package\ require\ html\n\ package\ require\ uri\n\ if\ \{\[catch\ \{package\ require\ tdom\}\ err\]\}\ \{\n\ \ \ \ eval\ \[subst\ \{proc\ TmlRss_GenHTML\ \{uri\ \{attr\ \{\}\}\}\ \{\n\ \ \ \ \ \ \ \ return\ \"<table\ class=\\\\\"newsfeed_table\\\\\"\ \\\$attr><tr><td>\[info\ script\]:\ \$err</td></tr></table>\"\}\n\ \ \ \ \}\]\n\ \ \ \ return\ -code\ error\ \$err\n\ \}\n\n\ namespace\ eval\ tmlrss\ \{\n\ \ \ \ variable\ rss_xml_cache\n\ \ \ \ array\ set\ rss_xml_cache\ \{\}\n\ \}\n\n\ #\ TmlRss_GenHTML\ --\n\ #\n\ #\ \ \ \ Generates\ 4.01\ HTML\ given\ a\ URI\ to\ an\ RSS\ feed\n\ #\n\ #\ \ \ \ \ \ \ \ \ uri\ -\ uri\ of\ rss\ feed\n\ #\ \ \ \ \ \ \ \ \ attr\ -\ additional\ attributes\ for\ the\ table\ (optional)\n\ #\n\ proc\ TmlRss_GenHTML\ \{uri\ \{attr\ \{\}\}\}\ \{\n\ \ \ \ append\ html\ \"<table\ class=\\\"newsfeed_table\\\"\ \$attr>\\n\"\n\ \ \ \ if\ \{\[catch\ \{\n\ \ \ \ \ \ \ \ set\ doc\ \[tmlrss::GetDOM\ \$uri\]\n\ \ \ \ \ \ \ \ append\ html\ \[tmlrss::genTitleBlock\ \$doc\]\n\ \ \ \ \ \ \ \ append\ html\ \[tmlrss::genContent\ \$doc\]\n\ \ \ \ \}\ err\]\}\ \{\n\ \ \ \ \ \ \ \ append\ html\ \"<tr><td>\$uri</td><td>\[tmlrss::encTxt\ \$err\]</td></tr>\"\n\ \ \ \ \}\n\ \ \ \ append\ html\ \"</table>\\n\"\n\ \ \ \ catch\ \{\$doc\ delete\}\n\ \ \ \ return\ \$html\n\ \}\n\n\ proc\ tmlrss::GetDOM\ \{uri\}\ \{\n\n\ \ \ \ #\ Is\ it\ cached\ locally?\n\ \ \ \ if\ \{\[isCachedXMLExpired\ \$uri\]\}\ \{\n\ \ \ \ \ \ \ \ set\ doc\ \[fetchXML\ \$uri\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ set\ doc\ \[dom\ parse\ -baseurl\ \[uriBase\ \$uri\]\ \$rss_xml_cache(\$uri)\]\n\ \ \ \ \}\n\n\ \ \ \ return\ \$doc\n\ \}\n\n\ #\ returns\ the\ DOM\ object\ of\ the\ RSS\ feed.\n\ proc\ tmlrss::fetchXML\ \{uri\}\ \{\n\ \ \ \ variable\ rss_xml_cache\n\n\ \ \ \ set\ token\ \[http::geturl\ \$uri\]\n\ \ \ \ if\ \{\[http::status\ \$token\]\ !=\ \"ok\"\ ||\ \[http::ncode\ \$token\]\ !=\ 200\}\ \{\n\ \ \ \ \ \ \ \ set\ err\ \[http::code\ \$token\]\n\ \ \ \ \ \ \ \ http::cleanup\ \$token\n\ \ \ \ \ \ \ \ return\ -code\ error\ \$err\n\ \ \ \ \}\n\ \ \ \ set\ xml\ \[http::data\ \$token\]\n\ \ \ \ upvar\ #0\ \$token\ state\n\ \ \ \ array\ set\ meta\ \$state(meta)\n\ \ \ \ http::cleanup\ \$token\n\ \ \ \ set\ doc\ \[dom\ parse\ -baseurl\ \[uriBase\ \$uri\]\ \$xml\]\n\n\ \ \ \ #\ Append\ a\ download\ time\ to\ the\ DOM\ as\ a\ comment.\n\ \ \ \ set\ comment\ \[\$doc\ createComment\ \\\n\ \ \ \ \ \ \ \ \"downloaded:\ \[clock\ format\ \[clock\ seconds\]\ -format\ \{%a,\ %e\ %b\ %Y\ %T\ GMT\}\ -gmt\ 1\]\"\]\n\ \ \ \ \[\$doc\ documentElement\]\ appendChild\ \$comment\n\n\ \ \ \ #\ Append\ when\ the\ server\ considers\ it\ expired\ to\ the\ DOM.\n\ \ \ \ catch\ \{\n\ \ \ \ \ \ \ \ set\ comment\ \[\$doc\ createComment\ \"expires:\ \$meta(Expires)\"\]\n\ \ \ \ \ \ \ \ \[\$doc\ documentElement\]\ appendChild\ \$comment\n\ \ \ \ \}\n\n\ \ \ \ #\ Save\ it\ in\ the\ cache.\n\ \ \ \ set\ rss_xml_cache(\$uri)\ \[\$doc\ asXML\ -indent\ 4\]\n\n\ \ \ \ return\ \$doc\n\ \}\n\n\ proc\ tmlrss::isCachedXMLExpired\ \{uri\}\ \{\n\ \ \ \ variable\ rss_xml_cache\n\n\ \ \ \ #TODO:\ make\ this\ work\n\n\ \ \ \ if\ \{\[info\ exist\ rss_xml_cache(\$uri)\]\}\ \{\n\ \ \ \ \ \ \ \ set\ xml\ \$rss_xml_cache(\$uri)\n\ \ \ \ \ \ \ \ set\ doc\ \[dom\ parse\ -baseurl\ \[uriBase\ \$uri\]\ \$xml\]\n\n\ \ \ \ \ \ \ \ #\ TODO:\ Is\ it\ past\ the\ TTL\ (if\ supported)?\n\ \ \ \ \ \ \ \ #\ \ \ \ \ \ \ just\ return\ yes,\ for\ now.\n\ \ \ \ \ \ \ \ if\ \{1\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \$doc\ delete\n\ \ \ \ \ \ \ \ \ \ \ \ unset\ rss_xml_cache(\$uri)\n\ \ \ \ \ \ \ \ \ \ \ \ return\ true\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ return\ false\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ return\ true\n\ \ \ \ \}\n\ \}\n\n\ proc\ tmlrss::uriBase\ \{uri\}\ \{\n\ \ \ \ array\ set\ info\ \[uri::split\ \$uri\]\n\ \ \ \ set\ info(path)\ \[file\ dirname\ \$info(path)\]\n\ \ \ \ return\ \[eval\ uri::join\ \[array\ get\ info\]\]\n\ \}\n\n\ proc\ tmlrss::getRSSVersion\ \{doc\}\ \{\n\ \ \ \ set\ root\ \[\$doc\ documentElement\]\n\ \ \ \ switch\ \[\$root\ nodeName\]\ \{\n\ \ \ \ \ \ \ \ rss\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[\$root\ hasAttribute\ version\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[\$root\ getAttribute\ version\]\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ #\ Best\ guess\ as\ most\ stuff\ is\ optional...\n\ \ \ \ \ \ \ \ \ \ \ \ return\ 0.92\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ rdf:RDF\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ return\ 1.0\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ return\ 0\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \}\n\n\ proc\ tmlrss::genTitleBlock\ \{doc\}\ \{\n\ \ \ \ set\ root\ \[\$doc\ documentElement\]\n\ \ \ \ append\ html\ \"<thead>\\n<tr>\\n\"\n\ \ \ \ switch\ \[getRSSVersion\ \$doc\]\ \{\n\ \ \ \ \ \ \ \ 0.91\ -\ 0.92\ -\ 0.93\ -\ 2.0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ titleXpath\ \ \ \ \ \ \ \ \{/rss/channel/title/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ linkXpath\ \ \ \ \ \ \ \ \{/rss/channel/link/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgNodeXpath\ \ \ \ \ \ \ \ \{/rss/channel/image/title\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgTitleXpath\ \ \ \ \ \ \ \ \{/rss/channel/image/title/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgLinkXpath\ \ \ \ \ \ \ \ \{/rss/channel/image/url/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgWidthXpath\ \ \ \ \ \ \ \ \{/rss/channel/image/width/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgHeightXpath\ \ \ \ \ \ \ \ \{/rss/channel/image/height/text()\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ 1.0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ titleXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='channel'\]/*\[local-name()='title'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ linkXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='channel'\]/*\[local-name()='link'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgNodeXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='image'\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgTitleXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='image'\]/*\[local-name()='title'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgLinkXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='image'\]/*\[local-name()='url'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgWidthXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='image'\]/*\[local-name()='width'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgHeightXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='image'\]/*\[local-name()='height'\]/text()\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ append\ html\ \"<th><a\ href=\\\"\[nodeUri\ \$root\ \$linkXpath\]\\\">\[nodeTxt\ \$root\ \$titleXpath\]</a></th>\\n\"\n\ \ \ \ if\ \{\[\$root\ selectNode\ \$imgNodeXpath\]\ !=\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ append\ html\ \"<th><a\ href=\\\"\[nodeUri\ \$root\ \$linkXpath\]\\\"><img\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ src=\\\"\[nodeUri\ \$root\ \$imgLinkXpath\]\\\"\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ alt=\\\"\[nodeTxt\ \$root\ \$imgTitleXpath\]\\\"\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \[expr\ \{\[nodeTxt\ \$root\ \$imgWidthXpath\]\ !=\ \"\"\ ?\ \"width=\\\"\[nodeTxt\ \$root\ \$imgWidthXpath\]\\\"\"\ :\ \"\"\}\]\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \[expr\ \{\[nodeTxt\ \$root\ \$imgHeightXpath\]\ !=\ \"\"\ ?\ \"height=\\\"\[nodeTxt\ \$root\ \$imgHeightXpath\]\\\"\"\ :\ \"\"\}\]></a></th>\\n\"\n\ \ \ \ \}\n\ \ \ \ append\ html\ \"</tr>\\n</thead>\\n\"\n\ \ \ \ return\ \$html\n\ \}\n\n\ proc\ tmlrss::genContent\ \{doc\}\ \{\n\ \ \ \ set\ root\ \[\$doc\ documentElement\]\n\ \ \ \ append\ html\ \"<tbody>\\n\"\n\ \ \ \ switch\ \[getRSSVersion\ \$doc\]\ \{\n\ \ \ \ \ \ \ \ 0.91\ -\ 0.92\ -\ 0.93\ -\ 2.0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ storiesXpath\ \ \ \ \ \ \ \ \{/rss/channel/item\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ titleXpath\ \ \ \ \ \ \ \ \{title/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ linkXpath\ \ \ \ \ \ \ \ \{link/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ pubDateXpath\ \ \ \ \ \ \ \ \{pubDate/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ descXpath\ \ \ \ \ \ \ \ \{description/text()\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ 1.0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ storiesXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='item'\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ titleXpath\ \ \ \ \ \ \ \ \{*\[local-name()='title'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ linkXpath\ \ \ \ \ \ \ \ \{*\[local-name()='link'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ pubDateXpath\ \ \ \ \ \ \ \ \{*\[local-name()='pubDate'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ descXpath\ \ \ \ \ \ \ \ \{*\[local-name()='description'\]/text()\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ set\ stories\ \[\$root\ selectNodes\ \$storiesXpath\]\n\ \ \ \ append\ html\ \[html::foreach\ story\ \$stories\ \{\n\ \ \ \ \ \ \ \ <tr><td\ colspan=2>\n\ \ \ \ \ \ \ \ \ \ \ \ <div\ class=\"headline\"><a\ href=\"\[nodeUri\ \$story\ \$linkXpath\]\">\[nodeTxt\ \$story\ \$titleXpath\]</a>\[expr\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{\[\$story\ selectNodes\ \$pubDateXpath\]\ !=\ \"\"\ ?\ \"\ <span\ class=\\\"headline_date\\\">(\[nodeTxt\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \$story\ \$pubDateXpath\])</span>\"\ :\ \"\"\}\]</div>\n\ \ \ \ \ \ \ \ \ \ \ \ <div\ class=\"headline_details\">\[nodeTxt\ \$story\ \$descXpath\]</div>\n\ \ \ \ \ \ \ \ </td></tr>\n\ \ \ \ \ \ \ \ \}\]\n\ \ \ \ append\ html\ \"</tbody>\\n\"\n\ \ \ \ return\ \$html\n\ \}\n\n\ proc\ tmlrss::encUri\ \{uri\}\ \{\n\ \ \ \ return\ \[string\ map\ \{\ &\ %26\ \}\ \$uri\]\n\ \}\n\n\ proc\ tmlrss::encTxt\ \{txt\}\ \{\n\ \ \ \ return\ \[string\ map\ \{\ &\ &amp\;\ <\ &lt\;\ >\ &gt\;\ \}\ \$txt\]\n\ \}\n\n\n\ proc\ tmlrss::nodeUri\ \{node\ xpath\}\ \{\n\ \ \ \ if\ \{\[\$node\ selectNode\ \$xpath\]\ !=\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ #\ Only\ if\ there\ is\ a\ lonely\ &,\ quote\ it\ back\ to\ an\ entity.\n\ \ \ \ \ \ \ \ return\ \[encUri\ \[\[\$node\ selectNode\ \$xpath\]\ nodeValue\]\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ return\ \"\"\n\ \ \ \ \}\n\ \}\n\n#\ TODO:\ there's\ a\ big\ problem\ here...\ \ Sometimes\ feeds\ include\ entities\ (ie.\ —\;)\n#\ that\ are\ outside\ the\ range\ of\ the\ claimed\ charset.\ \ Sometimes\ feeds\ include\n#\ URIs,\ but\ they\ aren't\ properly\ encoded..\n#\n#\ I\ tried\ ::htmlparse::mapEscapes,\ but\ for\ lonely\ ampersands\ that\ aren't\ encoded\n#\ to\ entities\ ('&'\ not\ '&amp\;'),\ ::htmlparse::mapEscapes\ mangles\ them\ and\ the\ four\n#\ chars\ that\ follow.\n#\n#\ TODO:\ possible\ solution\ would\ be\ to\ pre\ encode\ lonely\ ampersands,\ then\n#\ ::htmlparse::mapEscapes\ ???\ \ But\ how\ to\ fix\ the\ bad\ cp1252\ entities\ when\ the\n#\ charset\ is\ being\ claimed\ as\ iso8859-1\ in\ the\ XML\ header?\n#\ http://www.cs.tut.fi/~jkorpela/www/windows-chars.html#list\n#\n\ proc\ tmlrss::nodeTxt\ \{node\ xpath\}\ \{\n\ \ \ \ if\ \{\[\$node\ selectNode\ \$xpath\]\ !=\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ return\ \[\[\$node\ selectNode\ \$xpath\]\ nodeValue\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ return\ \"\"\n\ \ \ \ \}\n\ \}\n\n\ proc\ tmlrss::ShutDown\ \{\}\ \{\n\ \}\n\n\ Httpd_RegisterShutdown\ tmlrss::ShutDown\n======\nA\ .tml\ file\ to\ call\ it\ would\ look\ something\ like\ this:\n======\n<!DOCTYPE\ HTML\ PUBLIC\ \"-//W3C//DTD\ HTML\ 4.01\ Transitional//EN\"\ \"http://www.w3.org/TR/html4/strict.dtd\">\n\[Doc_Dynamic\]\n<html>\n<head>\n<title>SNews,\ you\ lose!</title>\n<meta\ http-equiv=\"Content-Type\"\ content=\"text/html\;\ charset=iso-8859-1\">\ \n<style\ type=\"text/css\">\n\ \ \ \ .newsfeed_table\ \{\n\ \ \ \ \ \ \ \ width:\ 80%\;\n\ \ \ \ \}\n\ \ \ \ .headline\ \{\n\ \ \ \ \}\n\ \ \ \ .headline_details\ \{\n\ \ \ \ \ \ \ \ padding-left:\ 2em\;\n\ \ \ \ \}\n\ \ \ \ .headline_date\ \{\n\ \ \ \ \ \ \ \ font-size:\ x-small\;\ font-style:\ italic\;\ color:\ #7F0000\;\n\ \ \ \ \}\n</style>\n<body>\n\n\[html::foreach\ rss_source\ \{\n\ \ \ \ \ \ \ \ http://www.npr.org/rss/rss.php?topicId=2\n\ \ \ \ \ \ \ \ http://rss.news.yahoo.com/rss/highestrated\n\ \ \ \ \ \ \ \ http://wiki.tcl.tk/rss.xml\n\ \ \ \ \ \ \ \ http://sourceforge.net/export/rss2_projsummary.php?group_id=10894\n\ \ \ \ \ \ \ \ http://dwlt.net/tapestry/dilbert.rdf\n\}\ \{\[TmlRss_GenHTML\ \$rss_source\ \"border=1\"\]<p/>\}\]\n\n<a\ href=\"http://validator.w3.org/check/referer\"\ ><img\ border=\"0\"\n\ \ \ \ \ \ \ \ \ \ src=\"http://www.w3.org/Icons/valid-html401\"\n\ \ \ \ \ \ \ \ \ \ alt=\"Valid\ HTML\ 4.01!\"\ height=\"31\"\ width=\"88\"></a>\n<a\ href=\"http://jigsaw.w3.org/css-validator/\">\n<img\ style=\"border:0\;width:88px\;height:31px\"\n\ \ \ \ \ \ \ src=\"http://jigsaw.w3.org/css-validator/images/vcss\"\ \n\ \ \ \ \ \ \ alt=\"Valid\ CSS!\">\n</a>\n\n</body>\n</html>\n======\n\[WJR\]\ -\ Nice,\ works\ great\ on\ my\ system!\ You\ should\ consider\ making\ this\ one\ of\ TclHttpd's\ sample\ apps\ (a\ number\ of\ apps\ come\ with\ the\ distribution\ in\ the\ sampleapp\ subdir).\n\n\[DG\]\ ''Thanks..''\ \ It's\ almost\ done.\ \ I\ had\ some\ problems\ with\ RSS\ v1.0,\ but\ just\ got\ them\ fixed.\ \ XML\ namespaces\ are\ no\ fun.\n\n\[Carsten\ Zerbst\]\ I\ have\ problems\ with\ encoding\ with\ some\ malformed\ files,\ e.g.\ by\ the\ main\ german\ tv\ magazin\ \ http://www.tagesschau.de/newsticker.rdf.\nI\ got\ rid\ off\ this\ changing\ the\ code\ a\ bit\n\n\n======\n\ \ \ \ #\ write\ to\ an\ temporary\ file\n\ \ \ \ set\ fd\ \[\ open\ tmp.xml\ w\]\n\ \ \ \ puts\ \$fd\ \[http::data\ \$token\]\n\ \ \ \ close\ \$fd\n\n\n\ \ \ \ upvar\ #0\ \$token\ state\n\ \ \ \ array\ set\ meta\ \$state(meta)\n\ \ \ \ http::cleanup\ \$token\n\n\ \ \ \ set\ doc\ \[\ dom\ parse\ \ -baseurl\ \[uriBase\ \$uri\]\ -channel\ \[tDOM::xmlOpenFile\ tmp.xml\]\ \]\n\ \ \ \ \n\ \ \ \ file\ delete\ tmp.xml\n=======\n\nIt\ works,\ but\ has\ the\ disadvantage\ of\ needing\ a\ temporary\ file.\ But\ it\ was\ too\ late\ to\ modify\ tDOM:xmlOpenFile\ to\ work\ on\ strings.\n\n\[DG\]\ --\ See\ \[XML/tDOM\ encoding\ issues\ with\ the\ http\ package\]\n\n----\n\[XO\]\ -\ As\ pointed\ out\ by\ \[Keith\ Vetter\]\ in\ \[Following\ Redirects\],\ \"One\ feature\ lacking\ \nin\ the\ http\ package\ is\ the\ ability\ to\ automatically\ handle\ redirects\".\ A\ '''geturl_followRedirects'''\ routine\ was\ used\ to\ solve\ the\ issue.\n\nAs\ of\ now\ (2006/03/04),\ the\ first\ (NPR)\ &\ the\ last\ (Dilbert)\ RSS\ feed\ in\ the\ above\ sample\ template\ have\ been\ redirected.\ Replacing\ '''''http::geturl\ \$uri'''''\ in\ line#4\ of\ tmlrss::fetchXML\ routine,\ by\ '''''geturl_followRedirects\ \$uri'''''\ will\ fix\ the\ problem.\n\nBTW,\ when\ I\ ran\ the\ script,\ I\ got\ an\ error\ on\ the\ second\ (Yahoo\ News)\ &\ the\ 4th\ (SourceForge)\ RSS\ feed,\ the\ error\ says\ something\ like\ ...\n======none\nerror\ \"syntax\ error\"\ at\ line\ 1\ character\ 0\ \"1\ <--Error--\ a7f\ <?xml\ version=\"1.0\"?>\ <!--\ RSS\ gene...\"\n======\n<<categories>>\ TclHttpd regexp2} CALL {my render {TclHttpd RSS Processing} \[WJR\]\ -\ There\ was\ a\ discussion\ on\ the\ \[TclHttpd\]\ mailing\ list\ about\ processing\ \[RSS\].\ Here's\ a\ variant\ I\ came\ up\ with\ using\ \[tDOM\]\ and\ \[The\ Tcler's\ Wiki\]\ RSS\ feed\ (it\ should\ work\ with\ any\ RSS\ feed):\n======tcl\n\[Doc_Dynamic\]\n\ \n\[\npackage\ require\ http\npackage\ require\ tdom\n\ \nhtml::set\ token\ \[http::geturl\ http://wiki.tcl.tk/rss.xml\]\nhtml::set\ rss_xml\ \[http::data\ \$token\]\n\ \nhtml::set\ doc\ \[dom\ parse\ \$rss_xml\]\nhtml::set\ root\ \[\$doc\ documentElement\]\nhtml::set\ stories\ \[\$root\ selectNodes\ /rss/channel/item\]\n\]\n\ \n\[html::head\ \{RSS\ Example\}\]\n\ \n\ <style\ type=\"text/css\">\n\ \ \ \ \ body\ \{\n\ \ \ \ \ \ \ \ \ font-family:\ Arial,\ Helvetica,\ sans-serif\;\n\ \ \ \ \ \ \ \ \ font-size:\ 80%\;\n\ \ \ \ \ \}\n\ \ \ \ \ h1\ \{\n\ \ \ \ \ \ \ \ \ background:\ #f7f7f7\;\n\ \ \ \ \ \ \ \ \ padding:\ 4px\;\n\ \ \ \ \ \}\n\ \ \ \ \ dt\ \{\n\ \ \ \ \ \ \ \ \ font-size:\ 120%\;\n\ \ \ \ \ \ \ \ \ font-weight:\ bold\;\n\ \ \ \ \ \}\n\ \ \ \ \ dd\ \{\n\ \ \ \ \ \ \ \ \ margin:\ 10px\;\n\ \ \ \ \ \}\n\ \ \ \ \ #date\ \{\n\ \ \ \ \ \ \ \ \ color:\ #999999\;\n\ \ \ \ \ \}\n\ </style>\n\ \n\[html::bodyTag\]\n\ \n\[html::h1\ \{RSS\ Example\}\]\n\ \n\ <dl>\n\ \ \ \ \ \[html::foreach\ story\ \$stories\ \{\n\ \ \ \ \ \ \ \ \ <dt>\n\ \ \ \ \ \ \ \ \ \ \ \ \ <a\ href=\"\[\[\$story\ selectNodes\ link/text()\]\ nodeValue\]\">\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \[\[\$story\ selectNodes\ title/text()\]\ nodeValue\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ </a>\n\ \ \ \ \ \ \ \ \ \ \ \ \ <span\ class=\"date\">\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (\[\[\$story\ selectNodes\ pubDate/text()\]\ nodeValue\])\n\ \ \ \ \ \ \ \ \ \ \ \ \ </span>\n\ \ \ \ \ \ \ \ \ </dt>\n\ \ \ \ \ \ \ \ \ <dd>\[\[\$story\ selectNodes\ description/text()\]\ nodeValue\]</dd>\n\ \ \ \ \ \}\]\n\ </dl>\n\ \n\[html::end\]\n======\n\[tDOM\]\ and\ \[TclHttpd\]\ makes\ this\ pretty\ simple!\n\n----\n\n\[DG\]\ --\ That\ little\ starter\ script\ got\ me\ going.\ \ I\ was\ messing\ with\ \[TclXML\]\ at\ first,\ but\ \[tDOM\]\ is\ a\ whole\ lot\ easier\ to\ use.\ \ See\ it\ in\ action\ \[http://www.pobox.com/~davygrvy/news.tml\]\n======\n#\ tmlrss.tcl\ --\n#\n#\ \ \ \ Process\ RSS\ (0.91,\ 0.92,\ 0.93,\ 1.0,\ 2.0)\ newsfeeds\ into\n#\ \ \ \ 4.01\ HTML.\ \ For\ use\ in\ .tml\ templates\ with\ tclhttpd.\n#\n#\ \ \ \ http://www.xml.com/pub/a/2002/12/18/dive-into-xml.html\n#\ \ \ \ http://blogs.law.harvard.edu/tech/rss\n#\ \ \ \ http://www.tdom.org/\n#\ \ \ \ \n#\ \ \ \ Instructions:\n#\ \ \ \ \ \ \ \ 1)\ place\ this\ file\ in\ your\ tml\ library\ directory\ so\n#\ \ \ \ \ \ \ \ the\ server\ sources\ it\ automatically\ at\ startup.\n#\ \ \ \ \ \ \ \ 2)\ Call\ TmlRss_GenHTML\ with\ the\ url\ of\ the\ RSS\ feed\n#\ \ \ \ \ \ \ \ from\ your\ .tml\ file\ (set\ to\ dynamic\ generation).\n#\ \ \ \ \ \ \ \ This\ function\ returns\ the\ formatted\ HTML\ of\ the\ feed.\n#\n#\ \ \ \ By\ David\ Gravereaux\ <[email protected]>\n#\n\n\ package\ provide\ tmlrss\ 0.2\n\n\ package\ require\ httpd\n\ package\ require\ http\n\ package\ require\ html\n\ package\ require\ uri\n\ if\ \{\[catch\ \{package\ require\ tdom\}\ err\]\}\ \{\n\ \ \ \ eval\ \[subst\ \{proc\ TmlRss_GenHTML\ \{uri\ \{attr\ \{\}\}\}\ \{\n\ \ \ \ \ \ \ \ return\ \"<table\ class=\\\\\"newsfeed_table\\\\\"\ \\\$attr><tr><td>\[info\ script\]:\ \$err</td></tr></table>\"\}\n\ \ \ \ \}\]\n\ \ \ \ return\ -code\ error\ \$err\n\ \}\n\n\ namespace\ eval\ tmlrss\ \{\n\ \ \ \ variable\ rss_xml_cache\n\ \ \ \ array\ set\ rss_xml_cache\ \{\}\n\ \}\n\n\ #\ TmlRss_GenHTML\ --\n\ #\n\ #\ \ \ \ Generates\ 4.01\ HTML\ given\ a\ URI\ to\ an\ RSS\ feed\n\ #\n\ #\ \ \ \ \ \ \ \ \ uri\ -\ uri\ of\ rss\ feed\n\ #\ \ \ \ \ \ \ \ \ attr\ -\ additional\ attributes\ for\ the\ table\ (optional)\n\ #\n\ proc\ TmlRss_GenHTML\ \{uri\ \{attr\ \{\}\}\}\ \{\n\ \ \ \ append\ html\ \"<table\ class=\\\"newsfeed_table\\\"\ \$attr>\\n\"\n\ \ \ \ if\ \{\[catch\ \{\n\ \ \ \ \ \ \ \ set\ doc\ \[tmlrss::GetDOM\ \$uri\]\n\ \ \ \ \ \ \ \ append\ html\ \[tmlrss::genTitleBlock\ \$doc\]\n\ \ \ \ \ \ \ \ append\ html\ \[tmlrss::genContent\ \$doc\]\n\ \ \ \ \}\ err\]\}\ \{\n\ \ \ \ \ \ \ \ append\ html\ \"<tr><td>\$uri</td><td>\[tmlrss::encTxt\ \$err\]</td></tr>\"\n\ \ \ \ \}\n\ \ \ \ append\ html\ \"</table>\\n\"\n\ \ \ \ catch\ \{\$doc\ delete\}\n\ \ \ \ return\ \$html\n\ \}\n\n\ proc\ tmlrss::GetDOM\ \{uri\}\ \{\n\n\ \ \ \ #\ Is\ it\ cached\ locally?\n\ \ \ \ if\ \{\[isCachedXMLExpired\ \$uri\]\}\ \{\n\ \ \ \ \ \ \ \ set\ doc\ \[fetchXML\ \$uri\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ set\ doc\ \[dom\ parse\ -baseurl\ \[uriBase\ \$uri\]\ \$rss_xml_cache(\$uri)\]\n\ \ \ \ \}\n\n\ \ \ \ return\ \$doc\n\ \}\n\n\ #\ returns\ the\ DOM\ object\ of\ the\ RSS\ feed.\n\ proc\ tmlrss::fetchXML\ \{uri\}\ \{\n\ \ \ \ variable\ rss_xml_cache\n\n\ \ \ \ set\ token\ \[http::geturl\ \$uri\]\n\ \ \ \ if\ \{\[http::status\ \$token\]\ !=\ \"ok\"\ ||\ \[http::ncode\ \$token\]\ !=\ 200\}\ \{\n\ \ \ \ \ \ \ \ set\ err\ \[http::code\ \$token\]\n\ \ \ \ \ \ \ \ http::cleanup\ \$token\n\ \ \ \ \ \ \ \ return\ -code\ error\ \$err\n\ \ \ \ \}\n\ \ \ \ set\ xml\ \[http::data\ \$token\]\n\ \ \ \ upvar\ #0\ \$token\ state\n\ \ \ \ array\ set\ meta\ \$state(meta)\n\ \ \ \ http::cleanup\ \$token\n\ \ \ \ set\ doc\ \[dom\ parse\ -baseurl\ \[uriBase\ \$uri\]\ \$xml\]\n\n\ \ \ \ #\ Append\ a\ download\ time\ to\ the\ DOM\ as\ a\ comment.\n\ \ \ \ set\ comment\ \[\$doc\ createComment\ \\\n\ \ \ \ \ \ \ \ \"downloaded:\ \[clock\ format\ \[clock\ seconds\]\ -format\ \{%a,\ %e\ %b\ %Y\ %T\ GMT\}\ -gmt\ 1\]\"\]\n\ \ \ \ \[\$doc\ documentElement\]\ appendChild\ \$comment\n\n\ \ \ \ #\ Append\ when\ the\ server\ considers\ it\ expired\ to\ the\ DOM.\n\ \ \ \ catch\ \{\n\ \ \ \ \ \ \ \ set\ comment\ \[\$doc\ createComment\ \"expires:\ \$meta(Expires)\"\]\n\ \ \ \ \ \ \ \ \[\$doc\ documentElement\]\ appendChild\ \$comment\n\ \ \ \ \}\n\n\ \ \ \ #\ Save\ it\ in\ the\ cache.\n\ \ \ \ set\ rss_xml_cache(\$uri)\ \[\$doc\ asXML\ -indent\ 4\]\n\n\ \ \ \ return\ \$doc\n\ \}\n\n\ proc\ tmlrss::isCachedXMLExpired\ \{uri\}\ \{\n\ \ \ \ variable\ rss_xml_cache\n\n\ \ \ \ #TODO:\ make\ this\ work\n\n\ \ \ \ if\ \{\[info\ exist\ rss_xml_cache(\$uri)\]\}\ \{\n\ \ \ \ \ \ \ \ set\ xml\ \$rss_xml_cache(\$uri)\n\ \ \ \ \ \ \ \ set\ doc\ \[dom\ parse\ -baseurl\ \[uriBase\ \$uri\]\ \$xml\]\n\n\ \ \ \ \ \ \ \ #\ TODO:\ Is\ it\ past\ the\ TTL\ (if\ supported)?\n\ \ \ \ \ \ \ \ #\ \ \ \ \ \ \ just\ return\ yes,\ for\ now.\n\ \ \ \ \ \ \ \ if\ \{1\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \$doc\ delete\n\ \ \ \ \ \ \ \ \ \ \ \ unset\ rss_xml_cache(\$uri)\n\ \ \ \ \ \ \ \ \ \ \ \ return\ true\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ return\ false\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ return\ true\n\ \ \ \ \}\n\ \}\n\n\ proc\ tmlrss::uriBase\ \{uri\}\ \{\n\ \ \ \ array\ set\ info\ \[uri::split\ \$uri\]\n\ \ \ \ set\ info(path)\ \[file\ dirname\ \$info(path)\]\n\ \ \ \ return\ \[eval\ uri::join\ \[array\ get\ info\]\]\n\ \}\n\n\ proc\ tmlrss::getRSSVersion\ \{doc\}\ \{\n\ \ \ \ set\ root\ \[\$doc\ documentElement\]\n\ \ \ \ switch\ \[\$root\ nodeName\]\ \{\n\ \ \ \ \ \ \ \ rss\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[\$root\ hasAttribute\ version\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[\$root\ getAttribute\ version\]\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ #\ Best\ guess\ as\ most\ stuff\ is\ optional...\n\ \ \ \ \ \ \ \ \ \ \ \ return\ 0.92\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ rdf:RDF\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ return\ 1.0\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ return\ 0\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \}\n\n\ proc\ tmlrss::genTitleBlock\ \{doc\}\ \{\n\ \ \ \ set\ root\ \[\$doc\ documentElement\]\n\ \ \ \ append\ html\ \"<thead>\\n<tr>\\n\"\n\ \ \ \ switch\ \[getRSSVersion\ \$doc\]\ \{\n\ \ \ \ \ \ \ \ 0.91\ -\ 0.92\ -\ 0.93\ -\ 2.0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ titleXpath\ \ \ \ \ \ \ \ \{/rss/channel/title/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ linkXpath\ \ \ \ \ \ \ \ \{/rss/channel/link/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgNodeXpath\ \ \ \ \ \ \ \ \{/rss/channel/image/title\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgTitleXpath\ \ \ \ \ \ \ \ \{/rss/channel/image/title/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgLinkXpath\ \ \ \ \ \ \ \ \{/rss/channel/image/url/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgWidthXpath\ \ \ \ \ \ \ \ \{/rss/channel/image/width/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgHeightXpath\ \ \ \ \ \ \ \ \{/rss/channel/image/height/text()\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ 1.0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ titleXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='channel'\]/*\[local-name()='title'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ linkXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='channel'\]/*\[local-name()='link'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgNodeXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='image'\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgTitleXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='image'\]/*\[local-name()='title'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgLinkXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='image'\]/*\[local-name()='url'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgWidthXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='image'\]/*\[local-name()='width'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ imgHeightXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='image'\]/*\[local-name()='height'\]/text()\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ append\ html\ \"<th><a\ href=\\\"\[nodeUri\ \$root\ \$linkXpath\]\\\">\[nodeTxt\ \$root\ \$titleXpath\]</a></th>\\n\"\n\ \ \ \ if\ \{\[\$root\ selectNode\ \$imgNodeXpath\]\ !=\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ append\ html\ \"<th><a\ href=\\\"\[nodeUri\ \$root\ \$linkXpath\]\\\"><img\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ src=\\\"\[nodeUri\ \$root\ \$imgLinkXpath\]\\\"\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ alt=\\\"\[nodeTxt\ \$root\ \$imgTitleXpath\]\\\"\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \[expr\ \{\[nodeTxt\ \$root\ \$imgWidthXpath\]\ !=\ \"\"\ ?\ \"width=\\\"\[nodeTxt\ \$root\ \$imgWidthXpath\]\\\"\"\ :\ \"\"\}\]\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \[expr\ \{\[nodeTxt\ \$root\ \$imgHeightXpath\]\ !=\ \"\"\ ?\ \"height=\\\"\[nodeTxt\ \$root\ \$imgHeightXpath\]\\\"\"\ :\ \"\"\}\]></a></th>\\n\"\n\ \ \ \ \}\n\ \ \ \ append\ html\ \"</tr>\\n</thead>\\n\"\n\ \ \ \ return\ \$html\n\ \}\n\n\ proc\ tmlrss::genContent\ \{doc\}\ \{\n\ \ \ \ set\ root\ \[\$doc\ documentElement\]\n\ \ \ \ append\ html\ \"<tbody>\\n\"\n\ \ \ \ switch\ \[getRSSVersion\ \$doc\]\ \{\n\ \ \ \ \ \ \ \ 0.91\ -\ 0.92\ -\ 0.93\ -\ 2.0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ storiesXpath\ \ \ \ \ \ \ \ \{/rss/channel/item\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ titleXpath\ \ \ \ \ \ \ \ \{title/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ linkXpath\ \ \ \ \ \ \ \ \{link/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ pubDateXpath\ \ \ \ \ \ \ \ \{pubDate/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ descXpath\ \ \ \ \ \ \ \ \{description/text()\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ 1.0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ storiesXpath\ \ \ \ \ \ \ \ \{/rdf:RDF/*\[local-name()='item'\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ titleXpath\ \ \ \ \ \ \ \ \{*\[local-name()='title'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ linkXpath\ \ \ \ \ \ \ \ \{*\[local-name()='link'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ pubDateXpath\ \ \ \ \ \ \ \ \{*\[local-name()='pubDate'\]/text()\}\n\ \ \ \ \ \ \ \ \ \ \ \ set\ descXpath\ \ \ \ \ \ \ \ \{*\[local-name()='description'\]/text()\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ set\ stories\ \[\$root\ selectNodes\ \$storiesXpath\]\n\ \ \ \ append\ html\ \[html::foreach\ story\ \$stories\ \{\n\ \ \ \ \ \ \ \ <tr><td\ colspan=2>\n\ \ \ \ \ \ \ \ \ \ \ \ <div\ class=\"headline\"><a\ href=\"\[nodeUri\ \$story\ \$linkXpath\]\">\[nodeTxt\ \$story\ \$titleXpath\]</a>\[expr\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \{\[\$story\ selectNodes\ \$pubDateXpath\]\ !=\ \"\"\ ?\ \"\ <span\ class=\\\"headline_date\\\">(\[nodeTxt\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \$story\ \$pubDateXpath\])</span>\"\ :\ \"\"\}\]</div>\n\ \ \ \ \ \ \ \ \ \ \ \ <div\ class=\"headline_details\">\[nodeTxt\ \$story\ \$descXpath\]</div>\n\ \ \ \ \ \ \ \ </td></tr>\n\ \ \ \ \ \ \ \ \}\]\n\ \ \ \ append\ html\ \"</tbody>\\n\"\n\ \ \ \ return\ \$html\n\ \}\n\n\ proc\ tmlrss::encUri\ \{uri\}\ \{\n\ \ \ \ return\ \[string\ map\ \{\ &\ %26\ \}\ \$uri\]\n\ \}\n\n\ proc\ tmlrss::encTxt\ \{txt\}\ \{\n\ \ \ \ return\ \[string\ map\ \{\ &\ &amp\;\ <\ &lt\;\ >\ &gt\;\ \}\ \$txt\]\n\ \}\n\n\n\ proc\ tmlrss::nodeUri\ \{node\ xpath\}\ \{\n\ \ \ \ if\ \{\[\$node\ selectNode\ \$xpath\]\ !=\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ #\ Only\ if\ there\ is\ a\ lonely\ &,\ quote\ it\ back\ to\ an\ entity.\n\ \ \ \ \ \ \ \ return\ \[encUri\ \[\[\$node\ selectNode\ \$xpath\]\ nodeValue\]\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ return\ \"\"\n\ \ \ \ \}\n\ \}\n\n#\ TODO:\ there's\ a\ big\ problem\ here...\ \ Sometimes\ feeds\ include\ entities\ (ie.\ —\;)\n#\ that\ are\ outside\ the\ range\ of\ the\ claimed\ charset.\ \ Sometimes\ feeds\ include\n#\ URIs,\ but\ they\ aren't\ properly\ encoded..\n#\n#\ I\ tried\ ::htmlparse::mapEscapes,\ but\ for\ lonely\ ampersands\ that\ aren't\ encoded\n#\ to\ entities\ ('&'\ not\ '&amp\;'),\ ::htmlparse::mapEscapes\ mangles\ them\ and\ the\ four\n#\ chars\ that\ follow.\n#\n#\ TODO:\ possible\ solution\ would\ be\ to\ pre\ encode\ lonely\ ampersands,\ then\n#\ ::htmlparse::mapEscapes\ ???\ \ But\ how\ to\ fix\ the\ bad\ cp1252\ entities\ when\ the\n#\ charset\ is\ being\ claimed\ as\ iso8859-1\ in\ the\ XML\ header?\n#\ http://www.cs.tut.fi/~jkorpela/www/windows-chars.html#list\n#\n\ proc\ tmlrss::nodeTxt\ \{node\ xpath\}\ \{\n\ \ \ \ if\ \{\[\$node\ selectNode\ \$xpath\]\ !=\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ return\ \[\[\$node\ selectNode\ \$xpath\]\ nodeValue\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ return\ \"\"\n\ \ \ \ \}\n\ \}\n\n\ proc\ tmlrss::ShutDown\ \{\}\ \{\n\ \}\n\n\ Httpd_RegisterShutdown\ tmlrss::ShutDown\n======\nA\ .tml\ file\ to\ call\ it\ would\ look\ something\ like\ this:\n======\n<!DOCTYPE\ HTML\ PUBLIC\ \"-//W3C//DTD\ HTML\ 4.01\ Transitional//EN\"\ \"http://www.w3.org/TR/html4/strict.dtd\">\n\[Doc_Dynamic\]\n<html>\n<head>\n<title>SNews,\ you\ lose!</title>\n<meta\ http-equiv=\"Content-Type\"\ content=\"text/html\;\ charset=iso-8859-1\">\ \n<style\ type=\"text/css\">\n\ \ \ \ .newsfeed_table\ \{\n\ \ \ \ \ \ \ \ width:\ 80%\;\n\ \ \ \ \}\n\ \ \ \ .headline\ \{\n\ \ \ \ \}\n\ \ \ \ .headline_details\ \{\n\ \ \ \ \ \ \ \ padding-left:\ 2em\;\n\ \ \ \ \}\n\ \ \ \ .headline_date\ \{\n\ \ \ \ \ \ \ \ font-size:\ x-small\;\ font-style:\ italic\;\ color:\ #7F0000\;\n\ \ \ \ \}\n</style>\n<body>\n\n\[html::foreach\ rss_source\ \{\n\ \ \ \ \ \ \ \ http://www.npr.org/rss/rss.php?topicId=2\n\ \ \ \ \ \ \ \ http://rss.news.yahoo.com/rss/highestrated\n\ \ \ \ \ \ \ \ http://wiki.tcl.tk/rss.xml\n\ \ \ \ \ \ \ \ http://sourceforge.net/export/rss2_projsummary.php?group_id=10894\n\ \ \ \ \ \ \ \ http://dwlt.net/tapestry/dilbert.rdf\n\}\ \{\[TmlRss_GenHTML\ \$rss_source\ \"border=1\"\]<p/>\}\]\n\n<a\ href=\"http://validator.w3.org/check/referer\"\ ><img\ border=\"0\"\n\ \ \ \ \ \ \ \ \ \ src=\"http://www.w3.org/Icons/valid-html401\"\n\ \ \ \ \ \ \ \ \ \ alt=\"Valid\ HTML\ 4.01!\"\ height=\"31\"\ width=\"88\"></a>\n<a\ href=\"http://jigsaw.w3.org/css-validator/\">\n<img\ style=\"border:0\;width:88px\;height:31px\"\n\ \ \ \ \ \ \ src=\"http://jigsaw.w3.org/css-validator/images/vcss\"\ \n\ \ \ \ \ \ \ alt=\"Valid\ CSS!\">\n</a>\n\n</body>\n</html>\n======\n\[WJR\]\ -\ Nice,\ works\ great\ on\ my\ system!\ You\ should\ consider\ making\ this\ one\ of\ TclHttpd's\ sample\ apps\ (a\ number\ of\ apps\ come\ with\ the\ distribution\ in\ the\ sampleapp\ subdir).\n\n\[DG\]\ ''Thanks..''\ \ It's\ almost\ done.\ \ I\ had\ some\ problems\ with\ RSS\ v1.0,\ but\ just\ got\ them\ fixed.\ \ XML\ namespaces\ are\ no\ fun.\n\n\[Carsten\ Zerbst\]\ I\ have\ problems\ with\ encoding\ with\ some\ malformed\ files,\ e.g.\ by\ the\ main\ german\ tv\ magazin\ \ http://www.tagesschau.de/newsticker.rdf.\nI\ got\ rid\ off\ this\ changing\ the\ code\ a\ bit\n\n\n======\n\ \ \ \ #\ write\ to\ an\ temporary\ file\n\ \ \ \ set\ fd\ \[\ open\ tmp.xml\ w\]\n\ \ \ \ puts\ \$fd\ \[http::data\ \$token\]\n\ \ \ \ close\ \$fd\n\n\n\ \ \ \ upvar\ #0\ \$token\ state\n\ \ \ \ array\ set\ meta\ \$state(meta)\n\ \ \ \ http::cleanup\ \$token\n\n\ \ \ \ set\ doc\ \[\ dom\ parse\ \ -baseurl\ \[uriBase\ \$uri\]\ -channel\ \[tDOM::xmlOpenFile\ tmp.xml\]\ \]\n\ \ \ \ \n\ \ \ \ file\ delete\ tmp.xml\n=======\n\nIt\ works,\ but\ has\ the\ disadvantage\ of\ needing\ a\ temporary\ file.\ But\ it\ was\ too\ late\ to\ modify\ tDOM:xmlOpenFile\ to\ work\ on\ strings.\n\n\[DG\]\ --\ See\ \[XML/tDOM\ encoding\ issues\ with\ the\ http\ package\]\n\n----\n\[XO\]\ -\ As\ pointed\ out\ by\ \[Keith\ Vetter\]\ in\ \[Following\ Redirects\],\ \"One\ feature\ lacking\ \nin\ the\ http\ package\ is\ the\ ability\ to\ automatically\ handle\ redirects\".\ A\ '''geturl_followRedirects'''\ routine\ was\ used\ to\ solve\ the\ issue.\n\nAs\ of\ now\ (2006/03/04),\ the\ first\ (NPR)\ &\ the\ last\ (Dilbert)\ RSS\ feed\ in\ the\ above\ sample\ template\ have\ been\ redirected.\ Replacing\ '''''http::geturl\ \$uri'''''\ in\ line#4\ of\ tmlrss::fetchXML\ routine,\ by\ '''''geturl_followRedirects\ \$uri'''''\ will\ fix\ the\ problem.\n\nBTW,\ when\ I\ ran\ the\ script,\ I\ got\ an\ error\ on\ the\ second\ (Yahoo\ News)\ &\ the\ 4th\ (SourceForge)\ RSS\ feed,\ the\ error\ says\ something\ like\ ...\n======none\nerror\ \"syntax\ error\"\ at\ line\ 1\ character\ 0\ \"1\ <--Error--\ a7f\ <?xml\ version=\"1.0\"?>\ <!--\ RSS\ gene...\"\n======\n<<categories>>\ TclHttpd} CALL {my revision {TclHttpd RSS Processing}} CALL {::oo::Obj3608354 process revision/TclHttpd+RSS+Processing} CALL {::oo::Obj3608352 process}

-errorcode

NONE

-errorinfo

Unknow state transition: LINE -> END
    while executing
"error $msg"
    (class "::Wiki" method "render_wikit" line 6)
    invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
    (class "::Wiki" method "render" line 8)
    invoked from within
"my render $name $C"
    (class "::Wiki" method "revision" line 31)
    invoked from within
"my revision $page"
    (class "::Wiki" method "process" line 56)
    invoked from within
"$server process [string trim $uri /]"

-errorline

4