以前、GoogleAppsScript (以降、GAS) にてXMLを扱ったことがありました*1。
そんな中、先日GASのリリースノートが更新され、今までのXMLがDeprecatedとなり、今後はXML Serviceというものを使うことになりました。また、公式Blogにも記事がアップされています。
- Release Notes - Google Apps Script — Google Developers
- XML changes in Apps Script - Google Apps Developer Blog
そこで新しいXML Serviceを使って何か作ろうと考えたところ、RSSフィードもXMLの一つということを思い出し、GASでRSSフィードを作成・出力してみることにしました。
なお、XML Serviceの基本的な使い方については公式ブログに記載があったため、そちらを参考に作りました。
■悩んだところなど
pubDateをRFC2822形式で設定する方法
GASのUtilitiesクラスにformatDate()メソッドがあり、扱いやすそうだったため、それを利用しました。
デフォルトパラメータの設定
pubDateのタイムゾーンについて、基本的には「JST」でいいけれど他のタイムゾーンも使えるようにしようと考えました。
JavaScriptのデフォルトパラメータについて調べたところ、ES6から実装されるとのことでした。
では、GASはどのJavaScriptをベースにしているのかを調べたところ、JavaScript1.8ということで残念ながら使えないようでした。
- Built-in Google Services - Google Apps Script — Google Developers
- Which Edition of ECMA-262 Does Google Apps Script Support? - Stack Overflow
そのため、以下を参考にデフォルトパラメータを設定しました。
if (typeof timezone === 'undefined') timezone = "JST" ;
エラーチェックについて
簡単に作ったためエラーチェックについては、ほとんどしていません。
以下を参考にして、pubDateがDate型かどうかをチェックしているくらいです。
if (!(pubDate instanceof Date)) throw 'pubDateは日付型';
ファイルの分離について
WebからのGETにレスポンスを返す「example.gs」と、RSS2.0フィードを作成するライブラリの「rss20feed.gs」に分けました。
「rss20feed.gs」はいわゆるモジュールパターンで作りましたが、JavaScriptのライブラリはどんな感じで作るのが一番良いのかは、まだよくわかっていません...
他の言語のフィード出力
参考までに、以下がありました。
■ソース
以下のとおりですが、一応feedlyにも取り込めましたので、問題ないかと思います。
JavaScriptに慣れていないので、書き方などで問題があれば、ご指摘ください。
example.gs
function doGet() { var rss = makeRss(); rss.addTitle('RSS 2.0 test'); rss.addLink('http://example.com'); rss.addDescription('RSS 2.0のテスト'); rss.addLanguage('ja'); for (var i = 1; i < 3; i++){ rss.addItem('ページ:' + i, 'http://example.com/' + i, i + 'つ目のページ', new Date() ) } return ContentService.createTextOutput(rss.toString()) .setMimeType(ContentService.MimeType.RSS); }
rss20feed.gs
var makeRss = function(){ var channel = XmlService.createElement('channel'); var root = XmlService.createElement('rss') .setAttribute('version', "2.0") .addContent(channel); var createElement = function(element, text){ return XmlService.createElement(element).setText(text); }; return { addTitle: function(title){ channel.addContent(createElement('title', title)); }, addLink: function(link){ channel.addContent(createElement('link', link)); }, addDescription: function(description){ channel.addContent(createElement('description', description)); }, addLanguage: function(language){ channel.addContent(createElement('language', language)); }, addItem: function(title, link, description, pubDate, timezone){ if (typeof timezone === 'undefined') timezone = "JST" ; if (!(pubDate instanceof Date)) throw 'pubDateは日付型'; var item = XmlService.createElement('item'); item.addContent(createElement('title', title)); item.addContent(createElement('link', link)); item.addContent(createElement('description', description)); var dateRfc2822 = Utilities.formatDate(pubDate, timezone, "EEE, dd MMM yyyy HH:mm:ss Z"); item.addContent(createElement('pubDate', dateRfc2822)); channel.addContent(item); }, toString: function(){ var document = XmlService.createDocument(root); var xml = XmlService.getPrettyFormat().format(document); return xml; } }; };
また、gistにも上げました(使う時は、.jsを.gsに変えます)。
*1:現在エラーで正しく動作していませんが、そのうち直さないと...