AWS認証制限に対応しました。本文中はそのままですが、デモには非公開キーを使用してアクセスするCGIに変更しています。
時代は便利になった物です。
MOONGIFT: » XMLをJSONにするXSLT「xml2json.xslt」:オープンソースを毎日紹介javascriptとXSLTを使うならば、AWSサーバから見えるサーバを用意しないといけないのですがYahoo! YQLを使えばそれも要りません。xml2json.xsltを見ていたらma.la氏のAmazon最速検索を思い出した。あちらはAmazon AWS専用になるだろうが、xml2json.xsltはそれをもっと汎用的なものにしたと考えられるだろう。
http://www.moongift.jp/2009/04/xml2json-xslt/
YQLといえばPipesに毛の生えた様な物だと思う方もいらっしゃるかもしれませんが、解析した結果をXMLやJSONで返す事ができJSONならばDOMツリーをJSONで表現してくれます。
例えばgithubで自分が公開したりforkしたりしているプロジェクトの一覧を作る場合、何を使って作りますか?Pipes?CGI?YQLならば簡単です。
select * from html where url = 'http://github.com/mattn' and xpath = '//li[@class="project"]'
実行結果これだけ。ちなみに私のgithubのページではプロジェクト一覧が表示されています。適当にパクって遊んでみて下さい。 さて話を戻してYQLですが
select * from html where url = 'http://www.example.com/'
のhtmlをxmlに変えればxmlもパース出来ます。つまりAWSのレスポンスをJSON(JSONP)で受け取れるのです。
select * from xml where url = 'http://xml-jp.amznxslt.com/onca/xml?Service=AWSECommerceService&SubscriptionId=XXX&AssociateTag=YYY&Operation=ItemSearch&SearchIndex=Books&ResponseGroup=Medium,Offers,Reviews&Version=2005-10-05&Keywords=ZZZ'
jQueryならば
var Keywords = 'ZZZ';
var SubscriptionId = 'XXX';
var AssociateTag = 'YYY';
var ResponseGroup = 'Medium,Offers,Reviews';
$.ajaxSettings.cache = true;
$.getJSON('http://query.yahooapis.com/v1/public/yql?callback=?', {
'q' : 'select * from xml where url = \'http://xml-jp.amznxslt.com/onca/xml?Service=AWSECommerceService&SubscriptionId=' + encodeURIComponent(SubscriptionId) + '&AssociateTag=' + encodeURIComponent(AssociateTag) + '&Operation=ItemSearch&SearchIndex=Books&ResponseGroup=' + encodeURIComponent(ResponseGroup) + '&Version=2005-10-05&Keywords=' + encodeURIComponent(Keywords) + '\'',
'format' : 'json'
}, function(data) {
こんな感じに書けます。これを使えば以前書いた「XSLとjQuery/HTMLだけで作る、amazon最速検索」ももっと簡単になるのです。さくっと以下の様に書いてみました。
$(function() {
var unsanitize = function(text) { return (text||'').replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<'); }
var quote = function(str) { return encodeURIComponent(str) };
$('#aws-word').keydown(function(e) { if (e.keyCode == 13) $('#aws-search').click() });
$('#aws-search').click(function() {
if (!$('#aws-word').val()) { $('#aws').html(''); return; }
$('#aws').html('<img src="http://mattn.kaoriya.net/images/ajax-loader.gif"/>');
var Keywords = $('#aws-word').val();
var SubscriptionId = '1GXPBVS13GJVA58PKVG2';
var AssociateTag = 'bigsky-22';
var ResponseGroup = 'Medium,Offers,Reviews';
$.ajaxSettings.cache = true;
$.getJSON('http://query.yahooapis.com/v1/public/yql?callback=?', {
'q' : 'select * from xml where url = \'http://xml-jp.amznxslt.com/onca/xml?Service=AWSECommerceService&SubscriptionId=' + encodeURIComponent(SubscriptionId) + '&AssociateTag=' + encodeURIComponent(AssociateTag) + '&Operation=ItemSearch&SearchIndex=Books&ResponseGroup=' + encodeURIComponent(ResponseGroup) + '&Version=2005-10-05&Keywords=' + encodeURIComponent(Keywords) + '\'',
'format' : 'json'
}, function(data) {
$('#aws').html('');
$.each(data.query.results.ItemSearchResponse.Items.Item, function(index, item) {
$('<div>')
.css('border', '1px dotted black')
.css('background-color', '#eeeeee')
.css('padding', '0.5em')
.css('margin', '0.5em')
.attr('id', 'aws' + index)
.hide()
.appendTo('#aws');
var c = $('#aws' + index);
$('<a/>')
.appendTo(c)
.attr('href', item.DetailPageURL)
.text(unsanitize(item.ItemAttributes.Title))
.appendTo(c);
var a = $('a', c);
if (item.MediumImage) {
$('<img/>')
.css('vertical-align', 'top')
.css('padding', '0.5em')
.css('border', '0px')
.css('float', 'left')
.attr('title', item.ItemAttributes.Title)
.attr('src', item.MediumImage.URL)
.prependTo(a);
}
a.after('<br />');
if (typeof (item.ItemAttributes.Author||'') == 'string') item.ItemAttributes.Author = [item.ItemAttributes.Author||''];
$.each(item.ItemAttributes.Author, function(index, item) {
$('<b>')
.text(item)
.appendTo(c)
.after('<br />');
});
$('#aws' + index)
.append('<span>ASIN: ' + item.ASIN + '</span>')
.append('<br />')
.append('<br />')
.append(item.ItemAttributes.Publisher + '/' + (item.ItemAttributes.ListPrice ? item.ItemAttributes.ListPrice.FormattedPrice : '') + ' (' + item.ItemAttributes.PublicationDate + ')')
.append('<br />')
.append((item.Offers && (item.Offers.Offer||'')) ? item.Offers.Offer.OfferListing.Availability : '');
$(c).append('<br clear="all" /><br />');
if (item.CustomerReviews) {
if (typeof item.CustomerReviews.Review.Summary == 'string') item.CustomerReviews.Review = [item.CustomerReviews.Review];
$('<a href="#">review comments</a>')
.css('font-size', 'small')
.css('color', 'blue')
.appendTo(c)
.click(function() { $('.reviews', c).toggle('slow'); return false; });
$('<div>')
.attr('class', 'reviews')
.css('display', 'none')
.css('font-size', 'small')
.appendTo(c);
$.each(item.CustomerReviews.Review, function(index, item) {
$('.reviews', c)
.append('<span class="name"><strong>' + item.Summary + '</strong></span><br />')
.append('<div class="comment">' + unsanitize(item.Content) + '</div>')
.append('<br />');
$('.comment', c)
.css('border', '1px dotted gray')
.css('background-color', 'white')
.css('padding', '0.5em')
});
}
});
$('div', '#aws').fadeIn('slow', function() {
$('.reviews').hide();
});
});
});
});
以下実行例簡単ですね。これでWebサーバを持たなくてもAmazon最速検索が出来上がります。