Due to memory limitations of
SecondLife with its first implementations of requesting data over
HTTP on the internet, the
RSS format can become too large to parse any data that is needed. The Second Simple Syndication format was created on the
protocol exchange as an attempt to work around this problem. A
SSS feed is in
XML format. Any valid RSS feed can be converted to SSS using
XSL Transformations. The SSS feed is made public as an open format so that others may adapt it easily without the need to depend on only one service for future products. XML can be transformed and served from just about any web server out there.
This document explains the format of SSS feeds.
When designing SSS feeds, only the bare minimum information was identified. This is to keep the data transferred within the 2048 character limit imposed with the first implementations of the
llHTTPRequest method. The following elements are found within an
<sss> root element:
<feed>
This is the identification of the podcast, blog, or information source.
Attribute | Description |
title | represents the name of the information source |
link | represents the web page url to the homepage of the information source. (see llLoadURL) |
<item>
This is the identification of an individual post, item, or entry within the information source.
Here is an example of an SSS feed:
<sss>
<feed title="My Podcast" link="http://www.mydomain.com/"/>
<item title="July 16, 2006" link="http://www.mydomain.com/20060716.html" enclosure="http://www.mydomain.com/20060716.mp3"/>
<item title="July 15, 2006" link="http://www.mydomain.com/20060715.html" enclosure="http://www.mydomain.com/20060715.mp3"/>
<item title="July 14, 2006" link="http://www.mydomain.com/20060714.html" enclosure="http://www.mydomain.com/20060714.mp3"/>
<item title="July 13, 2006" link="http://www.mydomain.com/20060713.html" enclosure="http://www.mydomain.com/20060713.mp3"/>
<item title="July 12, 2006" link="http://www.mydomain.com/20060712.html" enclosure="http://www.mydomain.com/20060712.mp3"/>
<item title="July 11, 2006" link="http://www.mydomain.com/20060711.html" enclosure="http://www.mydomain.com/20060711.mp3"/>
<item title="July 10, 2006" link="http://www.mydomain.com/20060710.html" enclosure="http://www.mydomain.com/20060710.mp3"/>
<item title="July 9, 2006" link="http://www.mydomain.com/20060709.html" enclosure="http://www.mydomain.com/20060709.mp3"/>
<item title="July 8, 2006" link="http://www.mydomain.com/20060708.html" enclosure="http://www.mydomain.com/20060708.mp3"/>
<item title="July 7, 2006" link="http://www.mydomain.com/20060707.html" enclosure="http://www.mydomain.com/20060707.mp3"/>
</sss>
Here is an exmple of an XSL file to transform existing RSS 2.0 feeds
<?xml version="1.0" ?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:rss="http://purl.org/rss/2.0/"
exclude-result-prefixes="rss"
>
<xsl:output indent="yes" method="xml" encoding="UTF-8" />
<xsl:template match="channel">
<sss>
<xsl:element name="feed">
<xsl:attribute name="title">
<xsl:value-of select="title" />
</xsl:attribute>
<xsl:attribute name="link">
<xsl:value-of select="link"/>
</xsl:attribute>
</xsl:element>
<xsl:call-template name="items"/>
</sss>
</xsl:template>
<xsl:template name="items">
<xsl:for-each select="item">
<xsl:element name="item">
<xsl:attribute name="title">
<xsl:value-of select="title"/>
</xsl:attribute>
<xsl:attribute name="link">
<xsl:value-of select="link"/>
</xsl:attribute>
<xsl:attribute name="enclosure">
<xsl:value-of select="enclosure/@url"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Here is an example of how to transform an RSS feed into an SSS feed, using
PHP with an XSL Transformation.
$xsl_file = 'rss2sss.xsl';
$xml_file = $_GET['feed'];
header('Content-Type: text/xml; charset=UTF-8');
$xml = domxml_open_file ($xml_file);
$xsl = domxml_xslt_stylesheet_file ($xsl_file);
$out = $xsl->process ($xml, array ());
echo $xsl->result_dump_mem ($out);
Here is an example of how to read an SSS feed using
LSL
integer LOAD_FEED = 100001;
string feedTitle;
string feedLink;
list itemTitles;
list itemLinks;
list itemEnclosures;
parseElement(string line)
{
/// sss element - new feed
if(line == "sss")
{
feedTitle = "";
feedLink = "";
itemTitles = [];
itemLinks = [];
itemEnclosures = [];
return;
}
// determine type of element
string element = llGetSubString(line, 0, llSubStringIndex(line, " ") - 1);
element = llToLower(element);
// parse known elements
if(element == "item")
parseItemElement(llGetSubString(line, llStringLength(element) + 1, -1));
else if(element == "feed")
parseFeedElement(llGetSubString(line, llStringLength(element) + 1, -1));
}
parseFeedElement(string line)
{
// parse attribute name/value pairs
list parts = llParseString2List(line, ["=\"", "\" "], []);
integer n = llGetListLength(parts);
integer i;
// loop through name/value pairs
for(i = 0; i < n; i += 2)
{
// read name/value pair
string name = llList2String(parts, i);
name = llToLower(name);
string value = llList2String(parts, i + 1);
// assign known values
if(name == "title") feedTitle = value;
if(name == "link") feedLink = value;
}
}
parseItemElement(string line)
{
// parse attribute name/value pairs
list parts = llParseString2List(line, ["=\"", "\" ", "\""], []);
integer n = llGetListLength(parts);
integer i;
// set default values
string title = "";
string link = "";
string enclosure = "";
// loop through name/value pairs
for(i = 0; i < n; i += 2)
{
// read name/value pair
string name = llList2String(parts, i);
name = llToLower(name);
string value = llList2String(parts, i + 1);
// assign known values
if(name == "title") title = value;
if(name == "link") link = value;
if(name == "enclosure") enclosure = value;
}
// add new item
itemTitles += [title];
itemLinks += [link];
itemEnclosures += [enclosure];
}
default
{
http_response(key request_id, integer status, list metadata, string body)
{
llWhisper(0, "Parsing feed.");
// parse out xml elements
list lines = llParseString2List(body, ["/>","<", ">", "\n"], []);
// loop through elements
integer n = llGetListLength(lines);
integer i;
for(i = 0; i < n; i++)
parseElement(llList2String(lines, i));
// notify results
llWhisper(0, "Done reading feed for " + feedTitle + " with " + (string)llGetListLength(itemTitles) + " items.");
}
link_message(integer sender_num, integer num, string str, key id)
{
if(num == LOAD_FEED)
{
llWhisper(0, "Requesting feed.");
llHTTPRequest(str, [], "");
}
}
}