Click here to Skip to main content
15,886,676 members
Articles / Web Development / ASP.NET

Podcast (RSS) to Playlist

Rate me:
Please Sign up or sign in to vote.
4.27/5 (6 votes)
1 Oct 2009CPOL5 min read 43.9K   300   18  
Convert podcast feeds into a variety of playlist formats on the fly by applying XSLT on RSS XML
<%@ Page Language="C#" %>
<%@ OutputCache Duration="240" VaryByParam="*" %>
<%@ Import Namespace="System.IO"%>
<%@ Import Namespace="System.Linq"%>
<%@ Import Namespace="System.Xml.Linq"%>
<script language="C#" runat="server">
      	
        void Page_Load(object sender, EventArgs e)
        {
            string sAsxFileName;
            string sRssUrl;
            //set the default xslt flename extension/type
            string sXslFileType = "ASX";
            //prepend the full path of the current directory
            string sXslFile = Path.GetDirectoryName(Request.PhysicalPath) + Path.DirectorySeparatorChar;

            //if they provided the OutType QueryString param, lets use this transform file
            if (Request.QueryString["OutType"] != null)
            {
                sXslFileType = Request.QueryString["OutType"];
            }

            //format the xslt filename to use based on the out type
            sXslFile += String.Format("RssTo{0}.xslt", sXslFileType);
            
            //check to make sure they provided the RssUrl QueryString param
            if (Request.QueryString["RssUrl"] != null)
            {
                sRssUrl = Request.QueryString["RssUrl"];
                
                //we'll try to use a formatted title of the feed for the asx filename
                sAsxFileName = FormatFileName(GetRssTitle(sRssUrl)) + "." + sXslFileType;
            }
            else
            {
                throw new ApplicationException("No RSS Feed URL (RssUrl) QueryString parameter provided.");
            }
         
            Response.Buffer = true;
            Response.ClearContent();
            Response.ClearHeaders();
            Response.Clear();
            Response.ContentEncoding = Encoding.UTF8;

            //if they provided the "inline" QueryString param, use it to determine how to send the asx file
            //inline sends the asx xml to the browser, attachment prompts the user to download the file
            //attachment is the defalut
            if ((Request.QueryString["Inline"] != null) && (Request.QueryString["Inline"].ToLower() == "true"))
            {
                //set Response.ContentType based on output method in xsl (this lets us switch between xml or text)
                Response.ContentType = GetXslOutputMethod(sXslFile);
                Response.AppendHeader("content-disposition", "inline;filename=" + sAsxFileName);
            }
            else
            {
                //we just use "text/x-unknown-content-type" because if we set to "text/plain" or "text/xml"
                //some browsers sometimes change the file extension to .txt or .xml respectively.
                Response.ContentType = "text/x-unknown-content-type";
                Response.AppendHeader("content-disposition", "attachment;filename=" + sAsxFileName);
            }

            //send transformed xml
            Response.Write(TransformXML(sRssUrl, sXslFile));
            Response.End();
        }
        

        /// <summary>
        /// removed unwanted characters from filename
        /// </summary>
        /// <param name="fileName">unformated filename</param>
        /// <returns>formated filename</returns>
        private string FormatFileName(string fileName)
        {
            string sReturn = fileName;

            sReturn = sReturn.Replace(" ", "");
            sReturn = sReturn.Replace(":", "");
            sReturn = sReturn.Replace("\\", "");
            sReturn = sReturn.Replace("/", "");
            sReturn = sReturn.Replace("@", "");
            sReturn = sReturn.Replace("$", "");
            sReturn = sReturn.Replace("+", "");
            sReturn = sReturn.Replace("%", "");
            sReturn = sReturn.Replace(">", "");
            sReturn = sReturn.Replace("<", "");
            sReturn = sReturn.Replace("?", "");
            sReturn = sReturn.Replace("\"", "");
            sReturn = sReturn.Replace("'", "");
            sReturn = sReturn.Replace(",", "");
            sReturn = sReturn.Replace("`", "");

            return sReturn;
        }


        /// <summary>
        /// Transforms xml from url using an xslt file.
        /// In this case, it will take a rss feed url and return the the playlist file
        /// </summary>
        /// <param name="xmlUrl">rss feed url</param>
        /// <param name="xslUrl">xslt filename</param>
        /// <returns>asx xml</returns>
        private string TransformXML(string xmlUrl, string xslUrl)
        {
            MemoryStream ms = new MemoryStream();
            string sOutput;
            try
            {
                System.Xml.XPath.XPathDocument oXPath = new System.Xml.XPath.XPathDocument(xmlUrl);
                System.Xml.Xsl.XslTransform oXSLT = new System.Xml.Xsl.XslTransform();
                oXSLT.Load(xslUrl);
                oXSLT.Transform(oXPath, null, ms);
                ms.Position = 0;
                StreamReader sr = new StreamReader(ms, Encoding.UTF8);
                sOutput = sr.ReadToEnd().ToString();
            }
            catch (Exception ex)
            {
                //Put in custom error handler here...
                sOutput = ex.ToString();
            }

            return sOutput;
        }

    
        /// <summary>
        /// Gets the title from an rss feed url
        /// </summary>
        /// <param name="xmlUrl">rss feed url</param>
        /// <returns>return the title from an rss feed url</returns>
        private string GetRssTitle(string xmlUrl)
        {
            string sReturn;

            try
            {
                XDocument xmlDoc = XDocument.Load(xmlUrl);

                var qry = from r in xmlDoc.Descendants("channel")
                          select (string)r.Element("title");

                sReturn = qry.First();
            }
            catch (Exception ex)
            {
                // there was a problem trying to get the title
                // we'll just use "rss"
                sReturn = "rss";
            }
            
            return sReturn;
        }
    

        /// <summary>
        /// Gets the output method (xsl:output method="xml" ...) from the given xsl file
        /// </summary>
        /// <param name="xslUrl">xsl url/filename</param>
        /// <returns>returns "text/xml" or "text/plain"</returns>
        private string GetXslOutputMethod(string xslUrl)
        {
            string sReturn = "xml";  //default to xml

            try
            {
                XNamespace xsl = "http://www.w3.org/1999/XSL/Transform";
                XDocument xmlDoc = XDocument.Load(xslUrl);

                var qry = from r in xmlDoc.Descendants(xsl + "stylesheet")
                          select r.Element(xsl + "output");
                
                XElement xslOutput = qry.First();
                if (xslOutput != null) { sReturn = xslOutput.Attribute("method").Value; }
            }
            catch (Exception ex)
            {
                // there was a problem trying to get the output method
                // we'll just use "xml"
            }

            sReturn = sReturn == "text" ? "text/plain" : "text/xml";
            return sReturn;
        }
    
</script>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader Kendle
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions