{"id":846,"date":"2006-08-30T21:45:41","date_gmt":"2006-08-31T05:45:41","guid":{"rendered":"http:\/\/cephas.net\/blog\/2006\/08\/30\/xsl-css-processing-instructions-using-rome\/"},"modified":"2006-08-30T21:45:41","modified_gmt":"2006-08-31T05:45:41","slug":"xsl-css-processing-instructions-using-rome","status":"publish","type":"post","link":"https:\/\/cephas.net\/blog\/2006\/08\/30\/xsl-css-processing-instructions-using-rome\/","title":{"rendered":"XSL \/ CSS Processing Instructions using ROME"},"content":{"rendered":"<p>Have you seen the way that the smart guys at <a href=\"http:\/\/www.feedburner.com\/fb\/a\/home\">FeedBurner<\/a> display RSS feeds in a browser (<a href=\"http:\/\/feeds.feedburner.com\/BurnThisRSS2\">here&#8217;s a sample<\/a> if you haven&#8217;t)? If you&#8217;re like me, the first time you see a feed they manage, you&#8217;ll probably think that you&#8217;re viewing a page that contains a link to an RSS or ATOM feed, not the actual feed. In fact what you&#8217;re seeing is the feed transformed by your browser using XSL and CSS.  Take a peek at the source and you&#8217;ll see that the XSL and CSS transformations are produced by what are technically called <a href=\"http:\/\/www.w3.org\/TR\/xml-stylesheet\/\">processing instructions<\/a>. I won&#8217;t go into the work that they&#8217;ve done to create that look (but if you poke around the source it&#8217;s not trivial), but the inclusion of the processing instruction&#8230; now that&#8217;s something I can help you out with. I&#8217;ve used ROME on a couple different projects now because it is trivial to create RSS, RSS2 or ATOM feeds with only a couple lines of code.  There are a number of <a href=\"http:\/\/wiki.java.net\/bin\/view\/Javawsxml\/Rome05Tutorials\">tutorials up on the ROME site<\/a> that show you how to create a feed and then write to a <a href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/lang\/String.html\">String<\/a>, a <a href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/io\/File.html\">File<\/a> or a <a href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/io\/Writer.html\">Writer<\/a> which you should check out if you don&#8217;t have any experience with ROME.  Assuming that you do however and given that you have a feed (technically a <a href=\"https:\/\/rome.dev.java.net\/apidocs\/0_3\/com\/sun\/syndication\/feed\/synd\/SyndFeed.html\">SyndFeed<\/a> in ROME), you would write it out in a servlet like this:<\/p>\n<pre>\r\nSyndFeedOutput output = new SyndFeedOutput();\r\noutput.output(feed, response.getWriter());\r\n<\/pre>\n<p>ROME abstracts you from having to work directly with an XML document, which is handy most of the time. But if you want to add a processing instruction to style your feed, it takes a little fiddling with the source. If you peek at the source of <a href=\"https:\/\/rome.dev.java.net\/apidocs\/0_8\/com\/sun\/syndication\/io\/SyndFeedOutput.html\">SyndFeedOutput<\/a>, you&#8217;ll see that it wraps <a href=\"https:\/\/rome.dev.java.net\/apidocs\/0_8\/com\/sun\/syndication\/io\/WireFeedOutput.html\">WireFeedOutput<\/a>. WireFeedOutput uses a JDOM <a href=\"http:\/\/www.jdom.org\/docs\/apidocs\/org\/jdom\/Document.html\">Document<\/a> and the <a href=\"http:\/\/www.jdom.org\/docs\/apidocs\/org\/jdom\/output\/XMLOutputter.html\">XMLOutputter<\/a> class to create write the feed. Conveniently, the Document class has <a href=\"http:\/\/www.jdom.org\/docs\/apidocs\/org\/jdom\/Document.html#addContent(int,%20org.jdom.Content)\">methods for adding processing instructions<\/a>, in fact it has a <a href=\"http:\/\/www.jdom.org\/docs\/apidocs\/org\/jdom\/ProcessingInstruction.html\">ProcessingInstruction<\/a> class. Putting all these things together, you&#8217;d get this if you were creating the RSS feeds for FeedBurner using ROME:<\/p>\n<pre>\r\nWireFeedOutput feedOutput = new WireFeedOutput();\r\nDocument doc = feedOutput.outputJDom(feed.createWireFeed());\r\n\/\/ create the XSL processing instruction\r\nMap xsl = new HashMap();\r\nxsl.put(\"href\", \"http:\/\/feeds.feedburner.com\/~d\/styles\/rss2full.xsl\");\r\nxsl.put(\"type\", \"text\/xsl\");\r\nxsl.put(\"media\", \"screen\");\r\nProcessingInstruction pXsl = new ProcessingInstruction(\"xml-stylesheet\", xsl);\r\ndoc.addContent(0, pXsl);\r\n\/\/ create the CSS processing instruction\r\nMap css = new HashMap();\r\ncss.put(\"href\", \"http:\/\/feeds.feedburner.com\/~d\/styles\/itemcontent.css\");\r\ncss.put(\"type\", \"text\/css\");\r\ncss.put(\"media\", \"screen\");\r\nProcessingInstruction pCss = new ProcessingInstruction(\"xml-stylesheet\", css);\r\ndoc.addContent(1, pCss);\r\n\/\/ write the document to the servlet response\r\nXMLOutputter outputter = new XMLOutputter(format);\r\noutputter.output(doc,response.getWriter());\r\n<\/pre>\n<p>So now that I&#8217;ve made that easy for you, who&#8217;s going to show me the website that has a bunch of easy to use CSS and XSL templates for transforming RSS and ATOM feeds?  Better yet, when are browsers going to have this kind of logic baked in so that my mom doesn&#8217;t have to look at an RSS feed that looks like a bunch of gobbly gook XML?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Have you seen the way that the smart guys at FeedBurner display RSS feeds in a browser (here&#8217;s a sample if you haven&#8217;t)? If you&#8217;re like me, the first time you see a feed they manage, you&#8217;ll probably think that you&#8217;re viewing a page that contains a link to an RSS or ATOM feed, not &hellip; <a href=\"https:\/\/cephas.net\/blog\/2006\/08\/30\/xsl-css-processing-instructions-using-rome\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">XSL \/ CSS Processing Instructions using ROME<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[31,13,3,32,10],"tags":[],"_links":{"self":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts\/846"}],"collection":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/comments?post=846"}],"version-history":[{"count":0,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts\/846\/revisions"}],"wp:attachment":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/media?parent=846"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/categories?post=846"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/tags?post=846"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}