<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>0xDECAFBAD - Tag: hacks</title>
    <link href="http://decafbad.com/blog/atom.xml" rel="self"/>
    <link href="http://decafbad.com/blog"/>
    <updated>2011-11-16T16:29:50+00:00</updated>
    <id></id>
    <author>
        <name></name>
        <email>l.m.orchard@pobox.com</email>
    </author>
    

    <entry>
        <title>Social Media Cyborg</title>
        <link href="http://decafbad.com/blog/2011/11/04/social-media-cyborg"/>
        <updated>2011-11-04T21:12:34+00:00</updated>
        <id>http://decafbad.com/blog/2011/11/04/social-media-cyborg</id>
        <content type="html">&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: &lt;em&gt;Since Google Reader lost it's sharing, I've decided to
revisit my &quot;social media strategy&quot;. I'm plugging lots of things into
other things. I feel like maybe I should write about this stuff.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.lucidchart.com/documents/view#4eb47331-8950-4a92-8b55-6c6e0a7aa298?branch=9c737269-0e32-4248-8525-54b73b1424a5&quot; style=&quot;display: block; float: right; text-decoration: none; border: none; margin: 0 0 1em 1em; width: 310px;&quot;&gt;&lt;img src=&quot;{{ site.baseurl }}/images/2011/11/social-media-cyborg.png&quot; style=&quot;width: 275px; border: 2px solid #ddd; padding: 1em; background: #fff;&quot; /&gt;&lt;br/&gt;&lt;small&gt;Started diagramming all my social media flows on LucidChart.&lt;/small&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;This is what I do for fun&lt;/h2&gt;

&lt;p&gt;Since I've mentioned in a few places that I'm a weirdo, I thought I
might spend some time explaining exactly what I mean by that. You see,
one of my hobbies is turning myself into a human content filter for
friends on the web.&lt;/p&gt;

&lt;p&gt;And, honestly, having my sharing habits shaken up by the
&lt;a href=&quot;http://decafbad.com/blog/2011/11/01/readerpocalypse&quot;&gt;Readerpocalypse&lt;/a&gt; makes it fun again.&lt;/p&gt;

&lt;p&gt;The image over to the right is an attempt I made to diagram some of my
social media flow. It's incomplete, though: I'm a cheapsake and ran
out of free objects in my diagram. So, I had to leave out at least a
half-dozen more services and a dozen additional connections.
(&lt;a href=&quot;http://www.lucidchart.com/&quot;&gt;LucidChart&lt;/a&gt; is very nice, by the way.)&lt;/p&gt;

&lt;h2&gt;In other words, ifttt.com is awesome&lt;/h2&gt;

&lt;p&gt;In particular, I've finally spent some time with &lt;a href=&quot;http://ifttt.com&quot;&gt;ifttt.com&lt;/a&gt;. It's
like &lt;a href=&quot;http://en.wikipedia.org/wiki/Automator_%28software%29&quot;&gt;Automator&lt;/a&gt; for the social web. It lets you &lt;a href=&quot;http://ifttt.com/people/lmorchard&quot;&gt;define event
triggers from one site that cause actions on another site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, I've gone crazy and created a bunch of tasks that make things like
the following possible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://pinboard.in/u:deusx&quot;&gt;Pinboard&lt;/a&gt; bookmarks based on favorites from
&lt;a href=&quot;https://twitter.com/lmorchard/favorites&quot;&gt;Twitter&lt;/a&gt;, &lt;a href=&quot;http://identi.ca/lmorchard/favorites&quot;&gt;identi.ca&lt;/a&gt;, &lt;a href=&quot;http://www.youtube.com/user/lmorchard&quot;&gt;YouTube&lt;/a&gt;,
&lt;a href=&quot;http://www.last.fm/user/deusx/library/loved&quot;&gt;Last.fm&lt;/a&gt;, and my &lt;a href=&quot;https://kindle.amazon.com/profile/Leslie-Michael-Orchard/1056858&quot;&gt;Kindle&lt;/a&gt; highlights. I'm turning my
&lt;a href=&quot;http://pinboard.in/u:deusx&quot;&gt;Pinboard&lt;/a&gt; account into both my personal social media archive and
a Google Reader sharing replacement, and I don't even have to beg
for new features at &lt;a href=&quot;http://pinboard.in/u:deusx&quot;&gt;Pinboard&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://lmorchard.tumblr.com/&quot;&gt;Tumblr&lt;/a&gt; photo posts based on &lt;a href=&quot;http://pipes.yahoo.com/pipes/pipe.run?_id=6f374b46f1b9a132972b262f2d85b7db&amp;amp;_render=rss&quot;&gt;Reddit up-votes&lt;/a&gt;, &lt;a href=&quot;http://www.flickr.com/photos/deusx/favorites/&quot;&gt;Flickr
favorites&lt;/a&gt;, and &lt;a href=&quot;http://pinboard.in/u:deusx&quot;&gt;Pinboard&lt;/a&gt; bookmarks tagged &quot;&lt;a href=&quot;http://pinboard.in/u:deusx/t:to:tumblr&quot;&gt;to:tumblr&lt;/a&gt;&quot;.
Since creating it, I've left my &lt;a href=&quot;http://lmorchard.tumblr.com/&quot;&gt;Tumblr&lt;/a&gt; almost entirely
neglected—but now with &lt;a href=&quot;http://ifttt.com&quot;&gt;ifttt.com&lt;/a&gt;, I can route almost every nifty
image I find over to that thing. It's the right side of my outboard
brain to the &lt;a href=&quot;http://pinboard.in/u:deusx&quot;&gt;Pinboard&lt;/a&gt; left.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Published items from from my private installation of &lt;a href=&quot;http://tt-rss.org/&quot;&gt;Tiny Tiny RSS&lt;/a&gt;
end up shared on &lt;a href=&quot;http://pinboard.in/u:deusx&quot;&gt;Pinboard&lt;/a&gt;. This pretty much scratches my itch
for feed reader sharing, since &lt;a href=&quot;http://decafbad.com/blog/2011/11/01/readerpocalypse&quot;&gt;Google nixed those features from
Reader&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Starred items from &lt;a href=&quot;http://tt-rss.org/&quot;&gt;tt-rss&lt;/a&gt; get sent to
&lt;a href=&quot;http://www.instapaper.com/&quot;&gt;Instapaper&lt;/a&gt;, so I can read them on my &lt;a href=&quot;https://kindle.amazon.com/profile/Leslie-Michael-Orchard/1056858&quot;&gt;Kindle&lt;/a&gt; later. If &lt;a href=&quot;https://twitter.com/lmorchard/status/132482782709555200&quot;&gt;email
delivery of documents start working&lt;/a&gt;, then I'll have a
personal long-attention span newspaper delivered regularly to that
gadget.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Posts from &lt;a href=&quot;https://plus.google.com/114487965928288927815/posts&quot;&gt;Google+&lt;/a&gt; get copied over to &lt;a href=&quot;http://www.facebook.com/lmorchard&quot;&gt;Facebook&lt;/a&gt;, because I
don't want to pick sides.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In fact, almost everything I do everywhere eventually ends up posted
to &lt;a href=&quot;http://www.facebook.com/lmorchard&quot;&gt;Facebook&lt;/a&gt;, because I almost never post anything in person over
there. I do have friends and family over there and respond to
comments, though.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;What's the point?&lt;/h2&gt;

&lt;p&gt;The important principle here is that I'm lazy. If there's a single
button to click somewhere that expresses my happiness about a thing,
I'd like to click it and have that happiness shared and archived
elsewhere without me doing much (or anything) more. The scheme I have
now feels pretty good for that, and &lt;a href=&quot;http://ifttt.com&quot;&gt;ifttt.com&lt;/a&gt; does a huge amount
to help.&lt;/p&gt;

&lt;p&gt;The other important thing is that &lt;strong&gt;I am at the center of these
connections&lt;/strong&gt;. I don't live entirely on any single service, and
anything I care about is archived where I can easily grab it for
backups or mashups. Should any particular service node in this web
fail, I can probably do without, find an alternative, or build one
myself.&lt;/p&gt;

&lt;p&gt;My goal is to eventually replace as many of these nodes as possible
with self-hosted or at least Open Source derived services. (Though, of
course, I'm also lazy and my friends are where they are. So, that goal
will take awhile.)&lt;/p&gt;

&lt;h2&gt;One more thing...&lt;/h2&gt;

&lt;p&gt;I've got &lt;a href=&quot;https://github.com/lmorchard/tinkering-with-activity-streams&quot;&gt;an idea for my next book simmering&lt;/a&gt;. And, since I've
so far managed to write books about the major things I've done for
fun, I feel I'd be remiss if I skipped this stuff. I mean, I sort of
covered the same ground all in &lt;a href=&quot;http://www.amazon.com/gp/product/0764597582?ie=UTF8&amp;amp;tag=0xdecafbad01-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;c%0D%0Areative=9325&amp;amp;creativeASIN=0764597582&quot;&gt;my first&lt;/a&gt; and &lt;a href=&quot;http://www.amazon.com/gp/product/0470037857?ie=UTF8&amp;amp;tag=0xdecafbad01-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;%0D%0Acreative=9325&amp;amp;creativeASIN=0470037857&quot;&gt;second&lt;/a&gt; books, but
things have progressed since then.&lt;/p&gt;

&lt;p&gt;What this means is that all the above feels like a warm up for the
coding and prosing I'll need to do. I just need to get my shit
together and carve out the time to make it happen.&lt;/p&gt;

&lt;!-- vim: set wrap wm=5 syntax=mkd textwidth=70: --&gt;

</content>
    </entry>
    
    

    <entry>
        <title>Ficlets enhanced author feed, an XSL scraper hack</title>
        <link href="http://decafbad.com/blog/2007/04/05/ficlets-enhanced-author-feed-an-xsl-scraper-hack"/>
        <updated>2007-04-05T05:37:00+00:00</updated>
        <id>http://decafbad.com/blog/2007/04/05/ficlets-enhanced-author-feed-an-xsl-scraper-hack</id>
        <content type="html">&lt;p&gt;I've been trying to get myself serious about writing and even set up a &lt;a href=&quot;http://decafbad.com/skein/&quot;&gt;personal slush pile for my output&lt;/a&gt;.  Then, I found &lt;a href=&quot;http://ficlets.com/authors/l_m_orchard&quot;&gt;Ficlets&lt;/a&gt;, and spewed a few quick starter stories there.  And then... I stopped.  I'm hoping to pick it up again very soon, but I guess that's the nature of my &lt;a href=&quot;http://decafbad.com/blog/2006/05/26/confessions-of-a-serial-enthusiast&quot;&gt;serial enthusiasm&lt;/a&gt;—it doesn't just apply to hacking.&lt;/p&gt;

&lt;p&gt;So, here's something ironic:  I just spent a few hours tonight throwing together a hack for &lt;a href=&quot;http://ficlets.com/authors/l_m_orchard&quot;&gt;Ficlets&lt;/a&gt;.  See, &lt;a href=&quot;http://ficlets.com/authors/l_m_orchard&quot;&gt;Ficlets&lt;/a&gt; runs on original stories, comments, ratings, and sequels and prequels to stories.  You can get an Atom feed of an author's stories and a feed of comments—but it seems like there's no way to get notified of prequels and sequels, which are a very gratifying part of the whole shebang.&lt;/p&gt;

&lt;p&gt;With that in mind, check out this RSS feed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href=&quot;http://decafbad.com/2005/12/FeedMagick/www-bin/ficlets.php?author=l_m_orchard&quot;&gt;&lt;code&gt;http://decafbad.com/2005/12/FeedMagick/www-bin/ficlets.php?author=l_m_orchard&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;That's a blend of all my stories, comments on my stories, as well as prequels and sequels found for my stories.  Subscribing to that feed will give me updates whenever there's anything new in all the above.  It's thrown together using a semi-crazy mix of my &lt;a href=&quot;http://decafbad.com/trac/wiki/FeedMagick&quot;&gt;FeedMagick&lt;/a&gt; package for caching, and some XSL for scraping.  If you'd like a feed like this of your own, just replace &lt;code&gt;l_m_orchard&lt;/code&gt; for your own author name in the &lt;code&gt;author&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Please note, however, that this little service is hosted on my site and may go away at any time for any reason.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In case you're interested in what's under the hood, here's the quick and dirty XSL that's behind it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href=&quot;http://decafbad.com/2007/04/ficlets.xsl&quot;&gt;&lt;code&gt;http://decafbad.com/2007/04/ficlets.xsl&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This thing's made possible because the &lt;a href=&quot;http://ficlets.com/authors/l_m_orchard&quot;&gt;Ficlets&lt;/a&gt; feeds are XML, &lt;strong&gt;and so are the XHTML pages happily infested with microformats&lt;/strong&gt;.  If they ever go invalid, this scraper breaks.  But, that's the nature of scrapers, and it works for now.  Oh, and although they provide Atom, this feed is RSS 2.0.  Why?  Because it was easier that way.  I might put some more effort into an Atom feed, but my itch has so far been scratched.&lt;/p&gt;

&lt;div id=&quot;comments&quot; class=&quot;comments archived-comments&quot;&gt;
            &lt;h3&gt;Archived Comments&lt;/h3&gt;
            
        &lt;ul class=&quot;comments&quot;&gt;
            
        &lt;li class=&quot;comment&quot; id=&quot;comment-221084356&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://rss-central.net/megalar&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=1869681b309d36e59764f51c7f210406&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://rss-central.net/megalar&quot;&gt;megalar&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221084356&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2007-04-05T09:31:48&quot;&gt;2007-04-05T09:31:48&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;I had already decided I was gonna grab your FeedMagick source and try to do something with it but this just gives me more incentive as a Ficlets lover. I recently read your thoughts on pipes and feel much the same way =&amp;gt; meh to GUI, especially a buggy one. It seems much more satisfying to just tell php what I want done and watch it go rather than spend 20 minutes fiddling with a silly applet.&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221084357&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=2377f34a68801b861c3e54e1301f0dce&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;l.m.orchard&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221084357&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2007-04-05T14:04:06&quot;&gt;2007-04-05T14:04:06&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;@meglar: Well, just to warn ya - FeedMagick needs a &lt;em&gt;lot&lt;/em&gt; of work.  :)  I've got ideas for it, but have yet to get back around to it.&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221084360&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://lawver.net&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=368732c30e3525fab12f9cd0664b4ba0&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://lawver.net&quot;&gt;Kevin Lawver&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221084360&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2007-04-05T14:59:37&quot;&gt;2007-04-05T14:59:37&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;That may be the coolest thing ever.  Good job!&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221084362&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=2377f34a68801b861c3e54e1301f0dce&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;l.m.orchard&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221084362&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2007-04-05T15:14:00&quot;&gt;2007-04-05T15:14:00&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;@Kevin: One thing that &lt;em&gt;might&lt;/em&gt; not be cool is that this XSL hits Ficlets.com once for each story in the feed to pick up the additional info, but I try to cache the feed on my end for about 20 minutes per author...  so hopefully it doesn't put any more stress on your site than I might have done manually in opening all my stories in tabs to check for comments and prequels/sequels.  :)&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221084364&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://lawver.net&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=368732c30e3525fab12f9cd0664b4ba0&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://lawver.net&quot;&gt;Kevin Lawver&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221084364&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2007-04-05T15:44:25&quot;&gt;2007-04-05T15:44:25&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;That's fine.  I think we can handle it.  We'll get prequels/sequels added to either the author feed or their own feed in the near future.&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221084365&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=2377f34a68801b861c3e54e1301f0dce&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;l.m.orchard&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221084365&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2007-04-05T21:05:26&quot;&gt;2007-04-05T21:05:26&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;@Kevin: Yeah, I think the bare author feed is a good thing to leave alone.  But, a personal author feed with comments and prequels/sequels and possibly notes would be excellent!  You know, basically, notifications of significant events that'd bring me back to the site.&lt;/p&gt;

&lt;p&gt;I'm also thinking it might be neat to gently spider through prequels and sequels on stories to map them out and track progress, but that's just a future hackery idea.&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221084368&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=e5d9a8832bed84d8d713ab0ef953d1af&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;&quot;&gt;Roger Costello&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221084368&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2007-04-06T13:54:55&quot;&gt;2007-04-06T13:54:55&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;Is there any way for me to view the documents you are mashing up to generate the resulting RSS document?  I am particularly interested in seeing how Microformats are being mashed up.  Thanks!&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221084369&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=2377f34a68801b861c3e54e1301f0dce&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;l.m.orchard&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221084369&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2007-04-06T14:25:44&quot;&gt;2007-04-06T14:25:44&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;Roger: Sure...  Really, the only things I'm mashing up are the author Atom feed, like mine here:&lt;/p&gt;

&lt;p&gt;http://ficlets.com/feeds/author/l&lt;em&gt;m&lt;/em&gt;orchard&lt;/p&gt;

&lt;p&gt;And then, I chase down each story in the feed, like this one:&lt;/p&gt;

&lt;p&gt;http://ficlets.com/stories/1763&lt;/p&gt;

&lt;p&gt;You can view source on a story page and see all the information sprinkled in there - look for 'abbr' tags and class names like 'pubdate' and 'hentry'.  The pages are also valid XML, so they can be manipulated right in XSL.&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221084370&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.blurbtree.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=fa30e56b9a686d32cdae390345019928&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.blurbtree.com&quot;&gt;Bill&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221084370&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2009-01-28T00:36:02&quot;&gt;2009-01-28T00:36:02&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;I'm sure that many Ficlets fans are sad that Ficlets.com is no more. We are in the process of constructing &lt;a href=&quot;http://www.blurbtree.com&quot; rel=&quot;nofollow&quot;&gt;Blurbtree.com&lt;/a&gt; a site that might be helpful for them. It's not a replacement for Ficlets, but it's a clean start and we'll build the site based on the feedback we get from the online community. Please give it a try and let us know what we can do to make it fit your needs. 
You can also get more information at our &lt;a href=&quot;http://www.blurbtree.com/faqs.php&quot; rel=&quot;nofollow&quot;&gt;Blurbtree FAQ&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;/ul&gt;
    
        &lt;/div&gt;



</content>
    </entry>
    
    

    <entry>
        <title>i'm in the nintendo ds homebrew club now</title>
        <link href="http://decafbad.com/blog/2006/09/19/im-in-the-nintendo-ds-homebrew-club-now"/>
        <updated>2006-09-19T16:16:12+00:00</updated>
        <id>http://decafbad.com/blog/2006/09/19/im-in-the-nintendo-ds-homebrew-club-now</id>
        <content type="html">&lt;blockquote cite=&quot;http://www.divineo.com/cgi-bin/div-us/dd-ds-pssc&quot;&gt;Passscard is the perfect flash card boot-up solution for DS LITE &amp; NDS .
It is compatible with most types of flash cards including M3, Neo, SC &amp; G6 etc. &lt;/blockquote&gt;


&lt;div class=&quot;quotesource&quot;&gt;Source: &lt;a href=&quot;http://www.divineo.com/cgi-bin/div-us/dd-ds-pssc&quot;&gt;Divineo.com - Product Information&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;I've just received a &lt;a href=&quot;http://www.divineo.com/cgi-bin/div-us/dd-ds-pssc&quot;&gt;Passcard 3&lt;/a&gt; in the mail.  Nintendo DS homebrew, here I come!  I'm particularly excited about &lt;a href=&quot;http://nitrotracker.tobw.net/index.php&quot;&gt;NitroTracker&lt;/a&gt; and &lt;a href=&quot;http://scummvm.drunkencoders.com/&quot;&gt;ScummVM&lt;/a&gt;.  Though I've only got a &lt;a href=&quot;http://movieadvance.com/&quot;&gt;GBA Movie Player&lt;/a&gt; and a 128MB CF flash card from a camera, that seems enough to run most of this stuff so far.  Unfortunately, it just sticks out from the Nintendo DS Lite by an inch or so - almost half the depth of the handheld itself!  I think one of my next purchases may be a more compact and capable &lt;a href=&quot;http://www.divineo.com/cgi-bin/div-us/dd-ds-suplite.html&quot;&gt;SuperCard MicroSD&lt;/a&gt;, which fits flush in the Nintendo DS Lite and accepts MicroSD expansion cards.&lt;/p&gt;

&lt;div id=&quot;comments&quot; class=&quot;comments archived-comments&quot;&gt;
            &lt;h3&gt;Archived Comments&lt;/h3&gt;
            
        &lt;ul class=&quot;comments&quot;&gt;
            
        &lt;li class=&quot;comment&quot; id=&quot;comment-221082362&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://foosel.net&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=bc9bc547d634817fe7ca6348119b0eaf&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://foosel.net&quot;&gt;foosel&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221082362&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2006-09-24T22:43:08&quot;&gt;2006-09-24T22:43:08&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;Congratulations on the Passcard ;) I got one myself a couple of months ago, including a M3 CF, and playing Monkey Island on the DS rocks ;) I have to warn you though concerning SD based units, there were a couple of issues not so long ago with several homebrew apps (including Scumm), and write-support for SD is afaik still rather new in the standard fat-lib used by homebrew devs. So you might want to make sure that your most beloved or interesting apps will actually work like expected prior to spending loads of money.&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221082363&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://twitter.com/adammokan&quot;&gt;&lt;img src=&quot;http://disqus.com/api/users/avatars/amokan.jpg&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://twitter.com/adammokan&quot;&gt;Adam Mokan&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221082363&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2006-09-28T04:21:30&quot;&gt;2006-09-28T04:21:30&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;How does the Passcard 3 fit in the DS? I've heard that its a real tight fit and you really have to force it to &quot;click&quot;.&lt;/p&gt;

&lt;p&gt;I'm getting ready to break down and buy some homebrew stuff for mine.&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;/ul&gt;
    
        &lt;/div&gt;



</content>
    </entry>
    
    

    <entry>
        <title>Ajaxitagging</title>
        <link href="http://decafbad.com/blog/2006/08/16/ajaxitagging"/>
        <updated>2006-08-16T13:12:07+00:00</updated>
        <id>http://decafbad.com/blog/2006/08/16/ajaxitagging</id>
        <content type="html">&lt;blockquote cite=&quot;http://adactio.com/journal/1162&quot;&gt;Ever since I switched over to a new CMS back in February, I’ve been tagging all my journal entries. Until now, I haven’t been doing anything with those tags apart from exposing them in category elements in my RSS feed. Now that I’ve got a good head of steam going with my tags, I’ve decided to play around with them a bit.&lt;/blockquote&gt;


&lt;div class=&quot;quotesource&quot;&gt;Source: &lt;a href=&quot;http://adactio.com/journal/1162&quot;&gt;Adactio: Journal - Ajaxitagging&lt;/a&gt;&lt;/div&gt;


&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0470037857/0xdecafbad01-20/104-2713105-4524705?%5Fencoding=UTF8&amp;amp;camp=1789&amp;amp;link%5Fcode=xm2&quot;&gt;Book&lt;/a&gt; pimping time:  In &lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0470037857/0xdecafbad01-20/104-2713105-4524705?%5Fencoding=UTF8&amp;amp;camp=1789&amp;amp;link%5Fcode=xm2&quot;&gt;Hacking del.icio.us&lt;/a&gt;, I've got something not entirely unlike the above-linked hack.  (Which, by the way, is good work!)  Mine is much more basic, though - with less microformat, progress bar, and yellow fadey goodness.  And, instead of AJAX, my hack uses &lt;a href=&quot;http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/&quot;&gt;JSONP&lt;/a&gt;.  The Related Links hack in Chapter 9 of &lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0470037857/0xdecafbad01-20/104-2713105-4524705?%5Fencoding=UTF8&amp;amp;camp=1789&amp;amp;link%5Fcode=xm2&quot;&gt;the book&lt;/a&gt; shows you how to include lists of the last few bookmarks you've posted under each tag / category / keyword used in a blog post.&lt;/p&gt;
</content>
    </entry>
    
    

    <entry>
        <title>Stupid fun with fax machines</title>
        <link href="http://decafbad.com/blog/2005/12/15/stupid-fun-with-fax-machines"/>
        <updated>2005-12-15T21:55:58+00:00</updated>
        <id>http://decafbad.com/blog/2005/12/15/stupid-fun-with-fax-machines</id>
        <content type="html">&lt;blockquote cite=&quot;http://faxtoy.net/&quot;&gt;Random Stuff Sent From Your Fax Machine&lt;br /&gt;Fax something interesting to 1-510-545-0990&lt;/blockquote&gt;


&lt;p&gt;&lt;small style=&quot;text-align:right; display:block&quot;&gt;Source: &lt;a href=&quot;http://faxtoy.net/&quot;&gt;Fax Toy - Random Stuff You Fax To Us&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;It's fun to fax anonymously!  And it's fun to have &lt;a href=&quot;http://faxtoy.net/page/fax-iBwDqh&quot;&gt;yet another opportunity for meta&lt;/a&gt;.  First person to fax their ass from the Christmas party loses.&lt;/p&gt;

&lt;!-- tags: fax fun nifty hacks --&gt;



</content>
    </entry>
    
    

    <entry>
        <title>Yahoo for stalking iPods in the hands of couriers</title>
        <link href="http://decafbad.com/blog/2005/11/03/yahoo-for-stalking-ipods-in-the-hands-of-couriers"/>
        <updated>2005-11-03T18:29:12+00:00</updated>
        <id>http://decafbad.com/blog/2005/11/03/yahoo-for-stalking-ipods-in-the-hands-of-couriers</id>
        <content type="html">&lt;p&gt;If the new &lt;a href=&quot;http://maps.yahoo.com/beta/&quot;&gt;Yahoo! Maps&lt;/a&gt; were &lt;em&gt;really&lt;/em&gt; cool, they'd've already done a mashup with &lt;a href=&quot;http://track.dhl-usa.com/&quot;&gt;DHL&lt;/a&gt; to let me obsessively stalk the courier in whose truck my returning iPod repair currently rests.&lt;/p&gt;

&lt;p&gt;Come on, get with the program!  When we've got &lt;a href=&quot;http://www.garmin.com/products/forerunner201/&quot;&gt;GPS watches&lt;/a&gt;, &quot;&lt;code&gt;Status: With delivery courier / Location: (blank)&lt;/code&gt;&quot; is no way to track a package!  In the meantime, my &lt;a href=&quot;http://www.randsinrepose.com/archives/2005/11/02/repetitive_information_injury.html&quot;&gt;repetitive information injury&lt;/a&gt; is flaring up as I refresh, refresh, refresh, refresh...&lt;/p&gt;

&lt;!-- tags: yahoo hacks programming maps ipod --&gt;

</content>
    </entry>
    
    

    <entry>
        <title>Could an iPod and AV cable fit in a DVD case?</title>
        <link href="http://decafbad.com/blog/2005/10/21/could-an-ipod-and-av-cable-fit-in-a-dvd-case"/>
        <updated>2005-10-21T18:05:54+00:00</updated>
        <id>http://decafbad.com/blog/2005/10/21/could-an-ipod-and-av-cable-fit-in-a-dvd-case</id>
        <content type="html">&lt;blockquote cite=&quot;http://www.russellbeattie.com/notebook/1008657.html&quot;&gt;Being able to listen to audio while in the “natural” places you listen to audio (in the car, while walking/running, on the couch, etc.) is what accelerated audio Podcasts to the phenomenon it is today.  Now that there is a way to view video the same way ... that’s going to accelerate that new type of user generated content as well. I’m positive. It’s a no brainer.&lt;/blockquote&gt;


&lt;p&gt;&lt;small style=&quot;text-align:right; display:block&quot;&gt;Source: &lt;a href=&quot;http://www.russellbeattie.com/notebook/1008657.html&quot;&gt;Russell Beattie Notebook » My New iPod: Video Podcasting Is Going to Be BIG&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;I've been gradually easing into subscribing to vidcast feeds, starting to find some early greats out there like &lt;a href=&quot;http://www.rocketboom.com/vlog/&quot;&gt;RocketBoom&lt;/a&gt;, &lt;a href=&quot;http://www.commandn.net/&quot;&gt;Command-N&lt;/a&gt;, and &lt;a href=&quot;http://openalpha.tv&quot;&gt;OpenAlpha&lt;/a&gt;.  I've also started hacking together feeds for &lt;a href=&quot;http://decafbad.com/blog/2005/10/13/internet-tv-wheres-the-feed&quot;&gt;great online video shows which lack feeds&lt;/a&gt;.  And then, there's the occasional private hack I've done to record shows with a capture card or help catch up on TV shows I find on Usenet.&lt;/p&gt;

&lt;p&gt;To watch all of these things in the living room, I use &lt;a href=&quot;http://www.xboxmediacenter.com/&quot;&gt;Xbox Media Center&lt;/a&gt; on my modded Xbox, networked to a file server in the basement.  However, there are probably very few other people on the planet who'd bother setting up a rig like mine.  So the combination of iTunes loading feed-delivered video enclosures onto an iPod equipped with an AV cable and a remote sounds like a genius combination for really jump starting the next phase of the vidcasting rise.&lt;/p&gt;

&lt;!-- tags: apple ipod video syndication rss atom podcasting vidcasting hacks xbox --&gt;




&lt;div id=&quot;comments&quot; class=&quot;comments archived-comments&quot;&gt;
            &lt;h3&gt;Archived Comments&lt;/h3&gt;
            
        &lt;ul class=&quot;comments&quot;&gt;
            
        &lt;li class=&quot;comment&quot; id=&quot;comment-221086753&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://rasterweb.net/raster/&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=db0fab74bcb564ebb09295498b892fb6&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://rasterweb.net/raster/&quot;&gt;Pete Prodoehl&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221086753&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-10-21T19:27:21&quot;&gt;2005-10-21T19:27:21&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;I really wish I had a enough spare parts of bucks lying around to build a MythTV box, because I could create quite a freaking videoblog aggregating machine out of it, and view it all on the big screen TV... Someday... Someday...&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221086754&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=2377f34a68801b861c3e54e1301f0dce&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;l.m.orchard&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221086754&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-10-21T20:29:08&quot;&gt;2005-10-21T20:29:08&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;Pete, well, I'm not doing all that bad with just an NSLU2, a 160 GB drive, and an Xbox.  :)&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221086755&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.slackorama.com/&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=15b474c86cd73c2d12c1d77af11c1d8a&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.slackorama.com/&quot;&gt;Seth Mason&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221086755&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-10-21T20:59:13&quot;&gt;2005-10-21T20:59:13&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;Thanks for the tip about Xbox Media Center.  I'll have to check that out.&lt;/p&gt;

&lt;p&gt;How did you mod your Xbox?  Or did I miss a post about it?&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221086756&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=2377f34a68801b861c3e54e1301f0dce&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;l.m.orchard&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221086756&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-10-22T01:43:09&quot;&gt;2005-10-22T01:43:09&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;Seth: Oh, I just went over to &lt;a href=&quot;http://www.modchipman.com&quot; rel=&quot;nofollow&quot;&gt;ModChipMan.com&lt;/a&gt; and picked up a &lt;a href=&quot;http://www.modchipman.com/xecuter-26-ce-p-120.html&quot; rel=&quot;nofollow&quot;&gt;Xecuter 2.6&lt;/a&gt; and soldered it in myself.  I upgraded the internal HD with one from a junker PC.  Very cool to dump all my games onto the drive and leave them squirreled away in their cases.  And then there's all the homebrew stuff like XBMC...&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221086758&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.slackorama.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=15b474c86cd73c2d12c1d77af11c1d8a&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.slackorama.com&quot;&gt;Seth Mason&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221086758&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-10-23T03:59:13&quot;&gt;2005-10-23T03:59:13&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;Thanks for the lowdown.&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221086759&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://stephanierose.hondaelement.org/&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=209e3adbef289391174f1a3a08af7c8a&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://stephanierose.hondaelement.org/&quot;&gt;Steph_B&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221086759&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-10-25T18:48:47&quot;&gt;2005-10-25T18:48:47&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;I wanna thanks for the tip about Xbox Media Center too. It's very useful information for me because I'm going to create videoblog instead of my homepage.&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;/ul&gt;
    
        &lt;/div&gt;



</content>
    </entry>
    
    

    <entry>
        <title>RedHanded » Announcing the MouseHole Proxy</title>
        <link href="http://decafbad.com/blog/2005/10/05/redhanded-%25c2%25bb-announcing-the-mousehole-proxy"/>
        <updated>2005-10-05T11:14:25+00:00</updated>
        <id>http://decafbad.com/blog/2005/10/05/redhanded-%c2%bb-announcing-the-mousehole-proxy</id>
        <content type="html">&lt;blockquote cite=&quot;http://redhanded.hobix.com/inspect/theMouseholeProxy.html&quot;&gt;MouseHole is a scriptable proxy. Like Greasemonkey, but scripts are in Ruby.&lt;/blockquote&gt;


&lt;p&gt;&lt;small style=&quot;text-align:right; display:block&quot;&gt;Source: &lt;a href=&quot;http://redhanded.hobix.com/inspect/theMouseholeProxy.html&quot;&gt;RedHanded » Announcing the MouseHole Proxy&lt;/a&gt;&lt;/small&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;MouseHole looks pretty freakin' sweet.  It's doing one of the things I never got around to making &lt;a href=&quot;http://decafbad.com/trac/wiki/AgentFrank&quot;&gt;AgentFrank&lt;/a&gt; do.  Every now and then I get an itch to revisit that project (or, more likely, its &lt;a href=&quot;http://decafbad.com/trac/wiki/DbProxy&quot;&gt;Pythonic sibling&lt;/a&gt;).&lt;/p&gt;

&lt;div id=&quot;comments&quot; class=&quot;comments archived-comments&quot;&gt;
            &lt;h3&gt;Archived Comments&lt;/h3&gt;
            
        &lt;ul class=&quot;comments&quot;&gt;
            
        &lt;li class=&quot;comment&quot; id=&quot;comment-221086801&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.screwtheman.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=52c00253a2327f7d1d351fdd259405c1&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.screwtheman.com&quot;&gt;Paul&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221086801&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-10-05T13:49:56&quot;&gt;2005-10-05T13:49:56&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;Hey Mr. Hacking RSS ,&lt;/p&gt;

&lt;p&gt;You may want to change the relative &amp;lt;href=&quot;af&quot;&amp;gt; because it doesn't resolve very well from inside an RSS reader (like Bloglines).&lt;/p&gt;

&lt;p&gt;;oD&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221086802&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=2377f34a68801b861c3e54e1301f0dce&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com&quot;&gt;l.m.orchard&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221086802&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-10-05T14:13:20&quot;&gt;2005-10-05T14:13:20&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;@Paul: D'oht.  That wasn't supposed to be an &lt;code&gt;&amp;lt;a href=&quot;af&quot;&amp;gt;&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Looks like I mixed up my &lt;code&gt;()&lt;/code&gt;'s with my &lt;code&gt;[]&lt;/code&gt;'s in Markdown when making the link reference.  Should be fixed now!&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;/ul&gt;
    
        &lt;/div&gt;



</content>
    </entry>
    
    

    <entry>
        <title>Building an Address Book as a Modern Web App</title>
        <link href="http://decafbad.com/blog/2004/12/23/abook1"/>
        <updated>2004-12-23T05:58:41+00:00</updated>
        <id>http://decafbad.com/blog/2004/12/23/abook1</id>
        <content type="html">&lt;p&gt;&lt;img src=&quot;http://www.decafbad.com/2004/12/abook-architecture.jpg&quot; align=&quot;right&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So, in the spirit of &lt;a href=&quot;http://www.decafbad.com/blog/2004/11/30/picoprojects_and_trepanation&quot;&gt;pico-projects&lt;/a&gt;, I've started building &lt;a href=&quot;http://www.decafbad.com/blog/2004/11/30/nextgenwebapps&quot;&gt;that address book application&lt;/a&gt; I mentioned awhile ago and I want to start writing about it as I go.&lt;/p&gt;

&lt;p&gt;First off, hopefully you'll notice the quick diagram I threw together in OmniGraffle.  This is a sort of rough sketch of the loosely-joined architecture I want to explore with this thing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Data&lt;/em&gt;: This is where address book entries live.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Model&lt;/em&gt;: A set of objects encapsulating the data, this is how address book entries will be accessed.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;REST API&lt;/em&gt;: Model objects exposed as resources identified by URI, serialized and deserialized as XML, and manipulated by GET / PUT / POST / DELETE methods.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;XSLT Filter&lt;/em&gt;: XML data produced by REST API calls can be first passed through XSL at a given URL before being served up as a response.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;HTML, CSS, JavaScript&lt;/em&gt;: Thanks to the XSLT filter layer, the XML vocabulary used to describe address book entries can be transformed into user interface presentation.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;HTTP&lt;/em&gt;: Everything happens via HTTP...&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Web Browser Client&lt;/em&gt;: ...and everything is viewed in a web browser.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Now, I call this a loosely-joined architecture because I want to stress that you should be able to swap out just about any part of this whenever you want.&lt;/p&gt;

&lt;p&gt;Want the &lt;em&gt;Data&lt;/em&gt; to be in MySQL?  Fine.  Want it to be in flat files?  Fine.  Just make sure the &lt;em&gt;Model&lt;/em&gt; can cope while maintaining a consistent interface for the &lt;em&gt;REST API&lt;/em&gt;.  Want to change the user interface in the browser?  Great-- ideally, all you have to do is change some XSLT files.  I'm writing everything from the &lt;em&gt;XSLT Filter&lt;/em&gt; down to the &lt;em&gt;Model&lt;/em&gt; in Python.  Don't like that?  Fine.  Rewrite it all in Perl, and hopefully everything from the XSLT up to the browser will still be useful to you.&lt;/p&gt;

&lt;p&gt;At some point, you might even want to ditch the browser for a native desktop client.  Fabulous! Just ignore everything past the &lt;em&gt;REST API&lt;/em&gt; and &lt;em&gt;HTTP&lt;/em&gt;, don't use any XSLT in the &lt;em&gt;Filter&lt;/em&gt;, and use the API and XML directly.&lt;/p&gt;

&lt;p&gt;I don't think any of this is particularly revolutionary-- although I thought it was when I first saw Amazon Web Services doing some of this, and I hope to throw a little GMail in as well.  I hope that this will all be useful as I muddle through explaining what I'm doing.  In the meantime, you can see me getting the stage set as I start checking things into my Subversion repository over here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.decafbad.com/svn/trunk/hacks/abook/&quot;&gt;http://www.decafbad.com/svn/trunk/hacks/abook/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;!--more--&gt;


&lt;p&gt;shortname=abook1&lt;/p&gt;

&lt;div id=&quot;comments&quot; class=&quot;comments archived-comments&quot;&gt;
            &lt;h3&gt;Archived Comments&lt;/h3&gt;
            
        &lt;ul class=&quot;comments&quot;&gt;
            
        &lt;li class=&quot;comment&quot; id=&quot;comment-221085892&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://trikuare.cx/&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=7d3d1e46aae8ca19855a6026d404b91d&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://trikuare.cx/&quot;&gt;fluffy&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221085892&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2004-12-23T07:35:40&quot;&gt;2004-12-23T07:35:40&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;Don't forget that with XSLT you could also rewrite it to SyncML and vCard and so on, so you could also sync it with external devices and iSync (assuming Apple finally opens up a third-party conduit system in Tiger, preferably one which doesn't require .Mac to function).&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221085894&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://eliot.landrum.cx&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=8b8f5370253bd0e0030154baa15785ed&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://eliot.landrum.cx&quot;&gt;eliot&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221085894&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2004-12-23T09:12:34&quot;&gt;2004-12-23T09:12:34&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;I'm looking forward to what becomes of this little app. Address book apps seem to all be severely lacking (with the possible exception of OS X's app) and need some fresh thinking. Making the components flexible could be a great way for some change to come about. 

Keep us posted!&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221085895&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com/&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=2377f34a68801b861c3e54e1301f0dce&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.decafbad.com/&quot;&gt;l.m.orchard&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221085895&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2004-12-23T12:41:13&quot;&gt;2004-12-23T12:41:13&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;Well, hopefully it's not too disappointing, but this address book app will be pretty anemic in terms of use as a serious app.  Implementing an address book is just an excuse to run through the various technologies involved.

However, there's nothing stopping anyone (including me) from enhancing the thing when I'm done and making it into a serious offering with vCard support and such.&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221085896&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://webseitz.fluxent.com/wiki&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=8157a5907b244071cda98ba5aa7a9635&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://webseitz.fluxent.com/wiki&quot;&gt;Bill Seitz&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221085896&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2004-12-27T12:23:46&quot;&gt;2004-12-27T12:23:46&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;(Hmm, posted last week but it never showed up...)

What are you thinking in terms of having this data store actually used by, say, your email client?

Make it look like an LDAP server, maybe?&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221085898&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.chuckknows.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=6cede7ba6ff803837ba2da9cc6e466b6&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.chuckknows.com&quot;&gt;Chuck Conway&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221085898&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-01-02T20:37:00&quot;&gt;2005-01-02T20:37:00&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;How Funny! I've been thinking about doing the same thing.

The only difference is I was thinking about doing address book, bookmarks and my RSS feeds. 

Those are the things I miss the most when I am away.&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221085900&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.worldwide-sources.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=73de6d1640f8cae902843f4a753bcaee&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.worldwide-sources.com&quot;&gt;William&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221085900&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-03-05T05:16:08&quot;&gt;2005-03-05T05:16:08&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;I'm curious to see where this little app is going its still needs more work&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221085903&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://webseitz.fluxent.com/wiki&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=8157a5907b244071cda98ba5aa7a9635&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://webseitz.fluxent.com/wiki&quot;&gt;Bill Seitz&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221085903&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2006-08-26T13:37:35&quot;&gt;2006-08-26T13:37:35&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;I see you working with Tarawa in there. Did you like it? Is it being worked on at all?&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;/ul&gt;
    
        &lt;/div&gt;



</content>
    </entry>
    
    

    <entry>
        <title>XPath based Python dictionaries, on loan</title>
        <link href="http://decafbad.com/blog/2004/09/01/xpath-based-python-dictionaries-on-loan"/>
        <updated>2004-09-01T10:47:41+00:00</updated>
        <id>http://decafbad.com/blog/2004/09/01/xpath-based-python-dictionaries-on-loan</id>
        <content type="html">&lt;p&gt;So &lt;a href=&quot;http://www.xmldatabases.org/WK/blog&quot;&gt;Kimbro Staken&lt;/a&gt; posted this nifty idea to build &lt;a href=&quot;http://www.xmldatabases.org/WK/blog/1964_XPath_based_Python_Dictionaries.item&quot;&gt;XPath based Python dictionaries&lt;/a&gt; to access XML data as a part of his incredibly nifty &lt;a href=&quot;http://www.syncato.org/&quot;&gt;Syncato&lt;/a&gt; microcontent management system.  Eventually, I've really got to break down and get that thing built and running on my server and my laptop-- it really seems like I'm reinventing so many wheels by not basing &lt;a href=&quot;http://www.decafbad.com/cvs/dbagg3/&quot;&gt;&lt;code&gt;dbagg3&lt;/code&gt;&lt;/a&gt; on it.&lt;/p&gt;

&lt;p&gt;But, while I'm in the process of wheel reinvention, how about I borrow Kimbro's idea?  I just threw together &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/dbagg3/lib/dbagg3/xmlutils.py&quot;&gt;a quick class called XPathDict&lt;/a&gt;, based on &lt;a href=&quot;http://www.xmlsoft.org/&quot;&gt;libxml2&lt;/a&gt;.  It works a little something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;feed_xd = XPathDict(file=&quot;sample-atom.xml&quot;)
for entry_node in feed_xd.nodes(&quot;//atom:entry&quot;):
    entry = XPathDict(doc=entry_node.doc, node=entry_node)
    print &quot;Title: &quot; % entry['atom:title']
    if 'atom:author' in entry:
        print &quot;Author: &quot; % entry['atom:author/atom:name']

xml = &quot;&quot;&quot;
   &amp;lt;dbagg3:user xmlns=&quot;http://purl.org/atom/ns#&quot; 
            xmlns:dbagg3=&quot;http://decafbad.com/2004/07/dbagg3/&quot;&amp;gt;
        &amp;lt;name&amp;gt;deusx&amp;lt;/name&amp;gt;
        &amp;lt;email&amp;gt;deus_x@pobox.com&amp;lt;/email&amp;gt;
        &amp;lt;url&amp;gt;http://www.decafbad.com/&amp;lt;/url&amp;gt;
        &amp;lt;dbagg3:prefs&amp;gt;
            &amp;lt;dbagg3:pref name=&quot;foo&quot;&amp;gt;bar&amp;lt;/dbagg3:pref&amp;gt;
        &amp;lt;/dbagg3:prefs&amp;gt;
   &amp;lt;/dbagg3:author&amp;gt;
&quot;&quot;&quot;

map = (
    ('userName',  'a:name'),
    ('userEmail', 'a:email'),
    ('fooPref',   &quot;dbagg3:prefs/dbagg3:pref[@name='foo']&quot;)
)

xd = XPathDict(xml=xml)
xd.cd(&quot;/dbagg3:user&quot;)
print xd.extract(map)

#    {'userName'  : 'deusx', 
#     'userEmail' : 'deus_x@pobox.com', 
#     'fooPref'   : 'bar'}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There isn't any spectacular code behind all this, and the idea &lt;em&gt;was&lt;/em&gt; Kimbro's, but it's working.  It's also incredibly convenient, especially with the little XML-to-dict extraction map method I whipped up.  This would take a bit more work to pry it out of its current context, such as turning the hardcoded namespaces into an option, among other things.  But, &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/dbagg3/lib/dbagg3/xmlutils.py&quot;&gt;here's the code&lt;/a&gt; for you to peruse.&lt;/p&gt;

&lt;p&gt;(I got hooked early on subverting in-built language constructs from perl's &lt;code&gt;tie&lt;/code&gt; facilities, and C++'s operator overloading.  Now I'm loving Python's &lt;a href=&quot;http://diveintopython.org/object_oriented_framework/special_class_methods2.html&quot;&gt;special class methods&lt;/a&gt;.  Someday, maybe, I'll actually get down to doing some work in LISP and wrap my head around some &lt;em&gt;real&lt;/em&gt; language subversion.)&lt;/p&gt;

&lt;p&gt;Anyway, while this is neither quite &lt;a href=&quot;http://dev2dev.bea.com/products/wlworkshop/articles/JSchneider_XML.jsp&quot;&gt;Native XML Scripting&lt;/a&gt; nor XML as &lt;a href=&quot;http://www.xmldatabases.org/WK/blog/663?t=item&quot;&gt;a native language construct&lt;/a&gt;, it's getting there.&lt;/p&gt;

&lt;div id=&quot;comments&quot; class=&quot;comments archived-comments&quot;&gt;
            &lt;h3&gt;Archived Comments&lt;/h3&gt;
            
        &lt;ul class=&quot;comments&quot;&gt;
            
        &lt;li class=&quot;comment&quot; id=&quot;comment-221090556&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://naeblis.cx&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=abfc88b96ae18c85ba7aac3bded2ec5e&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://naeblis.cx&quot;&gt;Ryan Tomayko&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221090556&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2004-09-01T17:29:27&quot;&gt;2004-09-01T17:29:27&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;Funny that. I also have one that has survived a couple of failed apps. I have a hard time dropping it to be honest and just keep lugging it around to each new project. 

http://naeblis.cx/cvs/percolator/xb/lib/xpdm.py?rev=HEAD&amp;content-type=text/vnd.viewcvs-markup

It has some pretty big issues. Among other things, creating nodes with namespace support is a little.. ermmm.. not there. But it does a lot of things well like garbage collecting xmlDoc instances (freeDoc), copying nodesets between documents, encoding things when they need to be, etc.
 
Anyway, I wonder if maybe we all might benefit by teaming up on this and try to define what a complete xpathish wrapper atop libxml2 should look like. And really, why limit it to libxml2? I'm of the opinion that the value here is an interface that embraces xpath. The fact that it's running on top of the blazingly fast libxml2 is nice but coding against the XMLTRAMP like interface is the value for me.

So let me see if I can get some time together to whip up a quick comparison of the three implementations. I'll shoot that over to you and Kimbro and we can go from there. If these seem to work best as backyard APIs we like to keep close to us, we'll drop it. However, I think there's a good chance that we can all benefit by combining our efforts.&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;/ul&gt;
    
        &lt;/div&gt;



</content>
    </entry>
    
    

    <entry>
        <title>Making progress on dbagg3</title>
        <link href="http://decafbad.com/blog/2004/08/31/dbagg3-makingprogress"/>
        <updated>2004-08-31T01:37:42+00:00</updated>
        <id>http://decafbad.com/blog/2004/08/31/dbagg3-makingprogress</id>
        <content type="html">&lt;p&gt;Work has been insanely busy lately, but I have made some more progress with &lt;a href=&quot;http://www.decafbad.com/cvs/dbagg3/&quot;&gt;&lt;code&gt;dbagg3&lt;/code&gt;&lt;/a&gt;.  The code is all in CVS, so feel free to take a gander-- I don't have a ton of time for a proper write up, but I do want to spew a little bit.&lt;/p&gt;

&lt;p&gt;As per my &lt;a href=&quot;http://www.decafbad.com/blog/2004/08/23/slicing_and_dicing_to_make_atom_soup_in_dbagg3&quot;&gt;previous musings on XML in a SQL database&lt;/a&gt;, I revamped the database.  Now things are sliced up by feed and entry tables, rows in each containing a few metadata columns and then one big column for an XML dump.  This lets me index on  date and parent feed and such, meanwhile punting on the issue of dicing things like authors or content up further.  And, as extension elements start to show up, this handling is dumb enough to simply store things it doesn't know about without mangling them.  This is a very good thing and one of my big goals for this beast.&lt;/p&gt;

&lt;p&gt;The other thing that I'm getting excited about is the REST API built atop the Atom store.  Rather than spend time on proper documentation, here's a quick dump from the &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/dbagg3/lib/dbagg3/rest.py&quot;&gt;appropriate module&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;URL: GET /feeds/
URL: GET /feeds/{id}.xml
URL: GET /feeds/{id}/{yyyy}/{mm}/{dd}/{hstart}-{hend}.xml
URL: GET /feeds/{id}/{yyyy}/{mm}/{dd}/{hh}.xml
URL: GET /feeds/{id}/{yyyy}/{mm}/{dd}.xml
URL: GET /feeds/{id}/{yyyy}/{mm}.xml
URL: GET /feeds/{id}/now-{nowoff}.xml
URL: GET /feeds/{fid}/entries/{eid}.xml
URL: GET /users/
URL: GET /users/{uname}.xml
URL: POST /users/
URL: DELETE /users/{uname}.xml
URL: PUT /users/{uname}.xml
URL: GET /users/{uname}/prefs.xml
URL: GET /users/{uname}/prefs/
URL: POST /users/{uname}/prefs/{pname}.{type}
URL: PUT /users/{uname}/prefs/{pname}.{type}
URL: GET /users/{uname}/prefs/{pname}.{type}
URL: DELETE /users/{uname}/prefs/{pname}.{type}
URL: GET /users/{uname}/subscriptions.{type}
URL: GET /users/{uname}/subscriptions/
URL: POST /users/{uname}/subscriptions/
URL: DELETE /users/{uname}/subscriptions/{id}.xml
URL: GET /users/{uname}/subscriptions/{sid}/{yyyy}/{mm}/{dd}/{hstart}-{hend}.xml
URL: GET /users/{uname}/subscriptions/{sid}/{yyyy}/{mm}/{dd}/{hh}.xml
URL: GET /users/{uname}/subscriptions/{sid}/{yyyy}/{mm}/{dd}.xml
URL: GET /users/{uname}/subscriptions/{sid}/{yyyy}/{mm}.xml
URL: GET /users/{uname}/subscriptions/{sid}/now-{hours}.xml
URL: GET /users/{uname}/subscriptions/{sid}/now.xml
URL: GET /users/{uname}/subscriptions/{yyyy}/{mm}/{dd}/{hstart}-{hend}.xml
URL: GET /users/{uname}/subscriptions/{yyyy}/{mm}/{dd}/{hh}.xml
URL: GET /users/{uname}/subscriptions/{yyyy}/{mm}/{dd}.xml
URL: GET /users/{uname}/subscriptions/{yyyy}/{mm}.xml
URL: GET /users/{uname}/subscriptions/now-{hours}.xml
URL: GET /users/{uname}/subscriptions/now.xml
URL: GET /users/{uname}/subscriptions/{sid}/entries/{eid}.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hopefully, the structure of these URL patterns make a little bit of sense.  The too-clever thing about these is that they're both documentation in the module's docstrings, and parsed out to register methods with automagically-generated regexes applied to incoming URL requests.  (I may eventually realize just how stupid an idea this is, but not yet.)&lt;/p&gt;

&lt;p&gt;This list is nowhere near complete or final or even all that well thought out yet.  But, it seems to be working out pretty well so far, and it's so easy to tinker with the API to sketch out ideas in working code.  Eating my own dogfood, my first browser window of the day tends to open on this URL:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://localhost/~deusx/dbagg3.5/api/users/default/subscriptions/
now-12.xml?xsl=xsl/full.xsl&amp;amp;#38;content-type=text/html
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This grabs the last 12 hours' worth of items from &lt;code&gt;default&lt;/code&gt;'s subscriptions, passing them through the XSL at &lt;code&gt;xsl/full.xsl&lt;/code&gt; on the way to my browser with a content type of &lt;code&gt;text/html&lt;/code&gt;.  This tends to produce about 1000-1500 entries in about 15 seconds on my PowerBook, which is better than I'd expected.&lt;/p&gt;

&lt;p&gt;Pretty soon, I'll be implementing the ability to post metadata onto feed entries under subscriptions.  Then, I can mark items as seen, attach categories, tags, and notes.  From there, I can exclude seen items from queries, produce new aggregate feeds based on my tagging or notes, among a few other ideas I've got stewing.&lt;/p&gt;

&lt;p&gt;A little more work, and I think I'll be able to throw together the beginnings of a &lt;a href=&quot;http://www.bloglines.com&quot;&gt;Bloglines&lt;/a&gt;-style three-pane browser interface, as well as improving the functionality of my own outliner-style display with &lt;a href=&quot;http://developer.apple.com/internet/webcontent/xmlhttpreq.html&quot;&gt;XmlHTTPRequest&lt;/a&gt;-based calls to the API to enable refresh-free interaction.  From there, I have some ideas for desktop apps and maybe even some &lt;a href=&quot;http://www.decafbad.com/blog/2003/06/19/flash_agg&quot;&gt;tinkering in Flash&lt;/a&gt;.  (Wow... has it really been over a year since I was writing about Flash &amp;#38; REST?)&lt;/p&gt;

&lt;p&gt;And &lt;em&gt;then&lt;/em&gt;, I want to implement the Atom API and allow users to create feeds to which they can post their own items and share read-only with others (or share writing with a group).  From there, this thing can turn into a read/write Atom storage tank, serving both as an aggregator and a blog publishing engine, given the appropriate XSL work.&lt;/p&gt;

&lt;p&gt;Lots of ideas stewing.  Now I just have to get the time and possibly a new web server, since I'd like to eventually open up an installation of this to fellow tinkerers, but this poor little box can barely take what it's tasked with at present...&lt;/p&gt;

&lt;p&gt;Oh yeah, and one other thing:  I've been thinking about names better than &lt;code&gt;dbagg3&lt;/code&gt;.  The one that's sticking around in my head so far is &lt;strong&gt;feedReactor&lt;/strong&gt;.  What do you think?&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;shortname=dbagg3_makingprogress&lt;/p&gt;

&lt;div id=&quot;comments&quot; class=&quot;comments archived-comments&quot;&gt;
            &lt;h3&gt;Archived Comments&lt;/h3&gt;
            
        &lt;ul class=&quot;comments&quot;&gt;
            
        &lt;li class=&quot;comment&quot; id=&quot;comment-221086277&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=26343060da04d2f84c3fbd726c1158b6&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;&quot;&gt;Alan&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221086277&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2004-09-01T03:39:10&quot;&gt;2004-09-01T03:39:10&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;I prefer the dbagg title to feed_anything_. There's feedster, feedburner, feedreader and I'm sure there will be a whole slew more. This needs an original name. It seems similiar to Urchin, which you earlier posted a link to, how about Starfish or maybe Seahorse. ;)&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;/ul&gt;
    
        &lt;/div&gt;



</content>
    </entry>
    
    

    <entry>
        <title>mysql and XML output</title>
        <link href="http://decafbad.com/blog/2004/08/23/mysql-and-xml-output"/>
        <updated>2004-08-23T05:09:51+00:00</updated>
        <id>http://decafbad.com/blog/2004/08/23/mysql-and-xml-output</id>
        <content type="html">&lt;p&gt;So...  How many of you have ever used &lt;code&gt;mysql -X&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;I just discovered it today, while screwing around with dumping database queries into Atom.  While I'm not entirely sure it's what I need to use, this is pretty nifty:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ mysql -Xp -udbagg3 dbagg3 -e '
&amp;gt; select id, title, modified 
&amp;gt; from feed
&amp;gt; order by modified 
&amp;gt; limit 4' 
Enter password:

&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;

&amp;lt;resultset statement=&quot;select id, title, modified 
        from feed order by modified limit 4&quot;&amp;gt;
  &amp;lt;row&amp;gt;
    &amp;lt;id&amp;gt;527&amp;lt;/id&amp;gt;
    &amp;lt;title&amp;gt;Channel Dean&amp;lt;/title&amp;gt;
    &amp;lt;modified&amp;gt;2004-03-04 15:56:54&amp;lt;/modified&amp;gt;
  &amp;lt;/row&amp;gt;

  &amp;lt;row&amp;gt;
    &amp;lt;id&amp;gt;31&amp;lt;/id&amp;gt;
    &amp;lt;title&amp;gt;chocolate and vodka&amp;lt;/title&amp;gt;
    &amp;lt;modified&amp;gt;2004-07-21 21:30:08&amp;lt;/modified&amp;gt;
  &amp;lt;/row&amp;gt;

  &amp;lt;row&amp;gt;
    &amp;lt;id&amp;gt;183&amp;lt;/id&amp;gt;
    &amp;lt;title&amp;gt;floating atoll&amp;lt;/title&amp;gt;
    &amp;lt;modified&amp;gt;2004-07-31 14:09:27&amp;lt;/modified&amp;gt;
  &amp;lt;/row&amp;gt;

  &amp;lt;row&amp;gt;
    &amp;lt;id&amp;gt;24&amp;lt;/id&amp;gt;
    &amp;lt;title&amp;gt;What's Your Brand Mantra?&amp;lt;/title&amp;gt;
    &amp;lt;modified&amp;gt;2004-08-02 03:15:03&amp;lt;/modified&amp;gt;
  &amp;lt;/row&amp;gt;
&amp;lt;/resultset&amp;gt;    
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, while I don't think that using this for &lt;code&gt;dbagg3&lt;/code&gt; is all that great an idea, it's something I need to remember for future shell and XSLT hacks...&lt;/p&gt;

&lt;div id=&quot;comments&quot; class=&quot;comments archived-comments&quot;&gt;
            &lt;h3&gt;Archived Comments&lt;/h3&gt;
            
        &lt;ul class=&quot;comments&quot;&gt;
            
        &lt;li class=&quot;comment&quot; id=&quot;comment-221087588&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=365087c6a73a2ee5fa90760c2f9d9ca8&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;&quot;&gt;iamsure&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221087588&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2004-08-23T03:47:12&quot;&gt;2004-08-23T03:47:12&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;Is there a way to do so without the commandline option, ie, via a select call, etc?&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221087591&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=34b6089110a6bfc86b6351ba400ae8fa&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;&quot;&gt;bosshoff&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221087591&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-04-20T12:22:15&quot;&gt;2005-04-20T12:22:15&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;There is a better way, using mysqldump, explained here: http://insight.zdnet.co.uk/software/developer/0,39020469,2112200,00.htm&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221087595&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=4c32c5992ac6744d2f14712d280e3834&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;&quot;&gt;Rededog027&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221087595&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2007-07-19T23:51:15&quot;&gt;2007-07-19T23:51:15&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;&lt;p&gt;That is awesome I haven't used it before but it is extreamly useful for  creating changelogs from svn and bugzilla :)&lt;/p&gt;&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;/ul&gt;
    
        &lt;/div&gt;



</content>
    </entry>
    
    

    <entry>
        <title>Wish-of-the-Month Club, Part 3 of 3</title>
        <link href="http://decafbad.com/blog/2004/07/06/wishofthemonthclub3"/>
        <updated>2004-07-06T21:05:45+00:00</updated>
        <id>http://decafbad.com/blog/2004/07/06/wishofthemonthclub3</id>
        <content type="html">&lt;p&gt;&lt;i&gt;This is the exciting conclusion of the Wish-of-the-Month Club.  Before continuing on, you may want to catch up with parts &lt;a href=&quot;http://www.decafbad.com/blog/2004/06/16/wishofthemonthclub1&quot;&gt;one&lt;/a&gt; and &lt;a href=&quot;http://www.decafbad.com/blog/2004/06/27/wishofthemonthclub2&quot;&gt;two&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;

&lt;h3&gt;Presenting the Results&lt;/h3&gt;

&lt;p&gt;Some ready-made files are available for this section:
* &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/hacks/wishes/wishes-ex5.xsl&quot;&gt;&lt;code&gt;wishes-ex5.xsl&lt;/code&gt;&lt;/a&gt;: The fifth iteration of the stylesheet in development.
* &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/hacks/wishes/wishes.html&quot;&gt;&lt;code&gt;wishes.html&lt;/code&gt;&lt;/a&gt;: Sample output in HTML&lt;/p&gt;

&lt;p&gt;We've finally gotten together all the bits of information we need--wishlists have been queried; random items have been selected; and a shopping cart has been prepared.  Now we just have to present the selections and a link to check out with the shopping cart.&lt;/p&gt;

&lt;p&gt;First, locate the following line toward the end of the stylesheet as we left it in the last section:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;xsl:copy-of select=&quot;$shopping_cart&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Delete this, and let's replace it by building some HTML:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;xsl:variable name=&quot;shopping_cart_purchase_url&quot; 
                  select=&quot;exsl:node-set($shopping_cart)//PurchaseUrl&quot; /&amp;gt;

    &amp;lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&amp;gt;
      &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Wishlist Shopping Cart&amp;lt;/title&amp;gt;\&amp;lt;/head&amp;gt;
      &amp;lt;body&amp;gt;
        &amp;lt;p class=&quot;title&quot;&amp;gt;
          Here are your wishlist items
          &amp;lt;a href=&quot;{$shopping_cart_purchase_url}&quot;&amp;gt;
            &amp;lt;img src=&quot;http://g-images.amazon.com/images/G/01/detail/shoppingcart-header-02.gif&quot; /&amp;gt;
          &amp;lt;/a&amp;gt; 
          items:
        &amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We're using the &lt;code&gt;exsl:note-set&lt;/code&gt; function again to access the contents of &lt;code&gt;$shopping_cart&lt;/code&gt; with an XPath expression.  We pluck out the value of the &lt;code&gt;PurchaseUrl&lt;/code&gt; in the shopping cart and place it in the variable &lt;code&gt;shopping_cart_purchase_url&lt;/code&gt;.  Then, after a bit of HTML preamble, we borrow a shopping cart icon from Amazon itself to construct a link to which we can browse later to purchase the selected items.  This HTML is very simple so far; it's likely too simple, so eventually you may like to toss some CSS in here to improve the looks of things.  But, I'll leave that as an exercise for the reader.&lt;/p&gt;

&lt;p&gt;Next, let's build a display of the items selected by iterating first through the wishlists:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        &amp;lt;xsl:for-each select=&quot;exsl:node-set($random_products)/wishes:wishitem&quot;&amp;gt;
          &amp;lt;div class=&quot;Detail&quot;&amp;gt;

            &amp;lt;p class=&quot;wishlistLabel&quot;&amp;gt;
              &amp;lt;xsl:value-of select=&quot;wishes:wishlist/@label&quot; /&amp;gt;
            &amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This begins a block for each wishlist, starting off with a paragraph containing the label we gave each wishlist.  Next, let's include a few details about the product chosen.  Again, all of the bits of data included for each product are described in the AWS documentation in the &lt;em&gt;Overview&lt;/em&gt; under &lt;em&gt;Amazon Web Services Data Model&lt;/em&gt;.  Checking that out, we can see that the data includes a URL to images of several sizes representing the product.  Let's include the medium-sized image as a link to the product's detail page:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;            &amp;lt;p class=&quot;Product&quot;&amp;gt;
              &amp;lt;a href=&quot;{Details/@url}&quot;&amp;gt;
                &amp;lt;img src=&quot;{Details/ImageUrlMedium}&quot; /&amp;gt;
              &amp;lt;/a&amp;gt;
              &amp;lt;br /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can also include the product's name as a link:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;              &amp;lt;span class=&quot;ProductName&quot;&amp;gt;
                &amp;lt;a href=&quot;{Details/@url}&quot;&amp;gt;
                  &amp;lt;xsl:value-of select=&quot;Details/ProductName&quot; /&amp;gt;
                &amp;lt;/a&amp;gt;
              &amp;lt;/span&amp;gt;
              &amp;lt;br /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And, it would be nice to provide a listing of people involved in creating the product (ie. the artists and/or authors):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;          &amp;lt;xsl:for-each select=&quot;./Details/Artists/Artist | 
                                ./Details/Authors/Author&quot;&amp;gt;
            &amp;lt;span class=&quot;Author&quot;&amp;gt;by &amp;lt;xsl:value-of select=&quot;.&quot; /&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;
          &amp;lt;/xsl:for-each&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that here, the XPath selecting the data is just a bit more involved, since this information can be found in both &lt;code&gt;Artist&lt;/code&gt; and &lt;code&gt;Author&lt;/code&gt; elements.  In another case, we might care to make a distinction, but it really isn't all that important for this project.  The data model also provides an indication of from which catalog this product came, as well as its date of release.  Let's include that for good measure:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;          (
          &amp;lt;xsl:value-of select=&quot;Details/Catalog&quot; /&amp;gt; -
          &amp;lt;span class=&quot;ReleaseDate&quot;&amp;gt;
            &amp;lt;xsl:value-of select=&quot;Details/ReleaseDate&quot; /&amp;gt;
          &amp;lt;/span&amp;gt;
          )
          &amp;lt;br /&amp;gt;
        &amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another thing that would be nice to know is how much this thing costs--we've got this information provided in the XML data as well, so let's include it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        &amp;lt;p&amp;gt;
          &amp;lt;span class=&quot;PriceLabel&quot;&amp;gt;List Price:&amp;lt;/span&amp;gt; 
          &amp;lt;span class=&quot;ListPrice&quot;&amp;gt;
            &amp;lt;xsl:value-of select=&quot;Details/ListPrice&quot; /&amp;gt;
          &amp;lt;/span&amp;gt;
          &amp;lt;br /&amp;gt;

          &amp;lt;span class=&quot;PriceLabel&quot;&amp;gt;Our Price:&amp;lt;/span&amp;gt;
          &amp;lt;span class=&quot;OurPrice&quot;&amp;gt;
            &amp;lt;xsl:value-of select=&quot;Details/OurPrice&quot; /&amp;gt;
          &amp;lt;/span&amp;gt;
          &amp;lt;br /&amp;gt;

          &amp;lt;span class=&quot;PriceLabel&quot;&amp;gt;Used Price:&amp;lt;/span&amp;gt; 
          &amp;lt;span class=&quot;UsedPrice&quot;&amp;gt;
            &amp;lt;xsl:value-of select=&quot;Details/UsedPrice&quot; /&amp;gt;
          &amp;lt;/span&amp;gt;
          &amp;lt;br /&amp;gt;
        &amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Something to note about these prices, too, is that although the used price is listed, the shopping cart will contain new items from Amazon's shelves.  You might want to compare these prices though, and make a change to the shopping cart when you get there, if a used item is acceptable.  (Another good reason for manual intervention in our Wish-of-the-Month club.)&lt;/p&gt;

&lt;p&gt;Oh yeah, and we should include one other bit of information:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        &amp;lt;p&amp;gt;(&amp;lt;xsl:value-of select=&quot;Details/Availability&quot; /&amp;gt;)&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This tells us whether or not this item can actually be bought, at present.  Although we used this data earlier to try to filter out unavailable items, we should still display this information just in case we missed something.&lt;/p&gt;

&lt;p&gt;Finally, let's clean up and finish the HTML:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;      &amp;lt;/div&amp;gt;
    &amp;lt;/xsl:for-each&amp;gt;

  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Running this stylesheet (&lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/hacks/wishes/wishes-ex5.xsl&quot;&gt;wishes-ex5.xsl&lt;/a&gt;) should give you a page that looks something like this in a browser:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.decafbad.com/cvs/*checkout*/hacks/wishes/wishes.jpg&quot; alt=&quot;Wishlist HTML screenshot&quot; /&gt;&lt;/p&gt;

&lt;h3&gt;Scheduling Monthly Emails&lt;/h3&gt;

&lt;p&gt;Some ready-made files are available for this section:
* &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/hacks/wishes/wishes-ex6.xsl&quot;&gt;&lt;code&gt;wishes-ex6.xsl&lt;/code&gt;&lt;/a&gt;: The sixth (and final) iteration of the stylesheet in development.&lt;/p&gt;

&lt;p&gt;That HTML we're producing is fine, but what we really want to do is get it delivered to us.  We could set up a scheduled run that would periodically generate a page for us to visit, but the whole point of this is laziness.  How about firing off an email with this content?  There are two things to help us with this: &lt;a href=&quot;http://www.faqs.org/rfcs/rfc1521.html&quot; title=&quot;RFC 1521&quot;&gt;RFC 1521&lt;/a&gt; shows us how to construct email messages with a variety of content types; and &lt;a href=&quot;http://www.hmug.org/man/8/sendmail.html&quot; title=&quot;man: sendmail&quot;&gt;&lt;code&gt;sendmail&lt;/code&gt;&lt;/a&gt; will let us send these messages out.  And then, with the help of &lt;code&gt;cron&lt;/code&gt;, we can fire up this process every month.&lt;/p&gt;

&lt;p&gt;Along with producing XML, XSLT can also construct plain text output--which is just what we need to create MIME email messages.  &lt;a href=&quot;http://www.faqs.org/rfcs/rfc1521.html&quot; title=&quot;RFC 1521&quot;&gt;RFC 1521&lt;/a&gt; doesn't make for the most thrilling reading, but there are a few articles to be found that summarize things (such as &lt;a href=&quot;http://www.abiglime.com/webmaster/articles/cgi/010698.htm&quot; title=&quot;How to encapsulate HTML in an email message&quot;&gt;this article&lt;/a&gt; and &lt;a href=&quot;http://www.wilsonweb.com/wmt5/html-email-multi.htm&quot; title=&quot;Sending HTML and Plain Text E-Mail Simultaneously&quot;&gt;this article&lt;/a&gt;).   To make a long story short, a basic shell for an email message using MIME to include an HTML part and a plain text part looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;To: someone@example.org
Subject: Some useful email subject
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary=&quot;theBoundaryString&quot;

--theBoundaryString
Content-Type: text/plain

Some plain text representation goes here...

--theBoundaryString
Content-Type: text/html
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Content-Base: &quot;http://www.decafbad.com/&quot;

&amp;lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&amp;gt;
    &amp;lt;p&amp;gt;Some HTML representation goes here...&amp;lt;/p&amp;gt;
&amp;lt;/html&amp;gt;

--theBoundaryString--
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I've snuck in the idea of providing both an HTML version (which we've already done) and a new plain text version.  Depending on your email program and your preferences, one type might be more useful than the other.  In any case, it's not all that hard to offer both here.  To start sending these email messages, though, we'll need an email address.  So, add that as an element in &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/hacks/wishes/wishes.xml&quot;&gt;wishes.xml&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;wishes xmlns=&quot;http://www.decafbad.com/2004/05/wishes&quot;&amp;gt;
  &amp;lt;email&amp;gt;deus_x@pobox.com&amp;lt;/email&amp;gt;
  &amp;lt;maxprice&amp;gt;15.00&amp;lt;/maxprice&amp;gt;
  &amp;lt;associate&amp;gt;0xdecafbad-20&amp;lt;/associate&amp;gt;
  &amp;lt;devtoken&amp;gt;D8HVH869XA0NP&amp;lt;/devtoken&amp;gt;
  &amp;lt;wishlists&amp;gt;
    &amp;lt;wishlist label=&quot;Me&quot;&amp;gt;1QWYI6P2JF3Q5&amp;lt;/wishlist&amp;gt;
    &amp;lt;wishlist label=&quot;The Girl&quot;&amp;gt;35OIOYWQ9XQAE&amp;lt;/wishlist&amp;gt;
  &amp;lt;/wishlists&amp;gt;
&amp;lt;/wishes&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's extract this data into a global variable near the start of the stylesheet:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  &amp;lt;xsl:variable name=&quot;email_to&quot;  select=&quot;/wishes:wishes/wishes:email&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Start editing the final template of the stylesheet, inserting before the start of HTML content:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;!-- Eat all the line breaks generated so far --&amp;gt;
    &amp;lt;xsl:text&amp;gt;To: &amp;lt;/xsl:text&amp;gt;&amp;lt;xsl:value-of select=&quot;$email_to&quot; /&amp;gt;   
Subject: 0xDECAFBAD's Amazon Wish-of-the-Month Club
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary=&quot;theBoundaryString&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the header for the email.  Up until now, we've been generating XML with the stylesheet and haven't cared very much about any extra whitespace or line breaks which might sneak into the output.  However, in an email header, whitespace is important since a blank line is what's used to separate the headers from the body of the email message.  So, any stray blank lines will cause what we might have meant to be headers to be interpreted as part of the message instead.  Producing the first header in the email with &lt;code&gt;xsl:text&lt;/code&gt; tags causes the XSL processor to throw away any leading whitespace which would have appeared before the first header.&lt;/p&gt;

&lt;p&gt;Other than this little twist, the email header looks pretty much like the shell.  We fill in the &lt;code&gt;To&lt;/code&gt; address from the global variable &lt;code&gt;$email_to&lt;/code&gt; and define a &lt;code&gt;Subject&lt;/code&gt; line.  The &lt;code&gt;MIME-Version&lt;/code&gt; and &lt;code&gt;Content-Type&lt;/code&gt; headers are what enable us to include both text and HTML versions in one email.&lt;/p&gt;

&lt;p&gt;Now we can start into one of the parts:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;--theBoundaryString
Content-Type: text/plain
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This begins the plain text section of the email, using the &lt;em&gt;boundary string&lt;/em&gt; as defined in the headers to delinieate the section's beginning.  The section can also have its own set of headers, of which we use only one: &lt;code&gt;Content-Type&lt;/code&gt;.  Moving along, let's work on the text content itself.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Here are your wishlist items:

&amp;lt;xsl:value-of select=&quot;$shopping_cart_purchase_url&quot; /&amp;gt;&amp;lt;xsl:text&amp;gt;
&amp;lt;/xsl:text&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;No shopping cart image here, but this includes the human-viewable URL which leads to a shopping cart on Amazon.com.  The usage of &lt;code&gt;xsl:text&lt;/code&gt; here forces a line break where there otherwise wouldn't have been one with the usage of &lt;code&gt;xsl:value-of&lt;/code&gt;.  Now, let's iterate through each of the wishlists and list out the product details:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;xsl:for-each select=&quot;exsl:node-set($random_products)/wishes:wishitem&quot;&amp;gt;
---------------------------------------------------------------------------
&amp;lt;xsl:value-of select=&quot;wishes:wishlist/@label&quot; 
       disable-output-escaping=&quot;yes&quot; /&amp;gt;
---------------------------------------------------------------------------

&amp;lt;xsl:value-of select=&quot;Details/ProductName&quot; 
       disable-output-escaping=&quot;yes&quot; /&amp;gt;

&amp;lt;xsl:for-each select=&quot;./Details/Artists/Artist | 
                      ./Details/Authors/Author&quot;&amp;gt;
by &amp;lt;xsl:value-of select=&quot;.&quot;  
   disable-output-escaping=&quot;yes&quot;/&amp;gt;
&amp;lt;/xsl:for-each&amp;gt;

Catalog:      &amp;lt;xsl:value-of select=&quot;Details/Catalog&quot; 
   disable-output-escaping=&quot;yes&quot; /&amp;gt;
Released:     &amp;lt;xsl:value-of select=&quot;Details/ReleaseDate&quot; 
   disable-output-escaping=&quot;yes&quot; /&amp;gt;

List Price:   &amp;lt;xsl:value-of select=&quot;Details/ListPrice&quot;  
     disable-output-escaping=&quot;yes&quot;/&amp;gt; 
Our  Price:   &amp;lt;xsl:value-of select=&quot;Details/UsedPrice&quot;  
     disable-output-escaping=&quot;yes&quot;/&amp;gt; 
Used Price:   &amp;lt;xsl:value-of select=&quot;Details/OurPrice&quot;  
     disable-output-escaping=&quot;yes&quot;/&amp;gt; 

Availability: &amp;lt;xsl:value-of select=&quot;Details/Availability&quot;  
       disable-output-escaping=&quot;yes&quot;/&amp;gt;
&amp;lt;xsl:text&amp;gt;

&amp;lt;/xsl:text&amp;gt;
&amp;lt;xsl:value-of select=&quot;Details/@url&quot;  
       disable-output-escaping=&quot;yes&quot;/&amp;gt;
&amp;lt;xsl:text&amp;gt;
&amp;lt;/xsl:text&amp;gt;

&amp;lt;/xsl:for-each&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Most everything in this stretch should look very similar to the HTML version we just finished.  The biggest difference is that every bit of information pulled in using &lt;code&gt;xsl:value-of&lt;/code&gt; is done using the &lt;code&gt;disable-output-escaping&lt;/code&gt; option.  When this is &lt;code&gt;yes&lt;/code&gt;, things like ampersands are no longer escaped for valid XML output.  Since this bit of the email is plain text, we don't want to see &lt;code&gt;&amp;amp;amp;&lt;/code&gt; in album titles, so this will cause ampersands to appear unmolested.&lt;/p&gt;

&lt;p&gt;That's the plain text version finished.  Now let's create the HTML version:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;--theBoundaryString
Content-Type: text/html
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Content-Base: &quot;http://www.decafbad.com/2004/05/wishes&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The boundary string appears again, signifying the end of the plain text section and the start of the HTML section.  Headers appear here which specify that what follows is HTML; that it's encoded in 7-bit characters; that it should be included in the message display itself (rather than presented as an attachment to be saved); and that all relative URLs which might appear in the HTML should be treated as having a base URL as specified.  This last part allows HTML in email to refer to images and other pages on another site without making all the URLs absolute.&lt;/p&gt;

&lt;p&gt;We don't need to make any modifications to the HTML as we built it in the last iteration of the stylesheet, so we can just include it unchanged:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&amp;gt;
...
&amp;lt;/html&amp;gt;

--theBoundaryString--
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This final appearance of the boundary string is bracketed on both sides by dashes, which indicates the end of the final section of the document.  We should be ready to try this in combination with &lt;code&gt;sendmail&lt;/code&gt; in a shell:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ xsltproc wishes-ex6.xsl wishes.xml | sendmail -it
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If everything has worked correctly, there should be an email arriving in your mailbox sometime soon.  (Or in my inbox, if you followed the directions literally and didn't supply your own email address.)  The options supplied to &lt;code&gt;sendmail&lt;/code&gt; are fairly basic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-i&lt;/code&gt; causes lines consisting solely of &lt;code&gt;.&lt;/code&gt; &lt;em&gt;not&lt;/em&gt; to be treated as an end-of-input signal.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-t&lt;/code&gt; causes &lt;code&gt;sendmail&lt;/code&gt; to look in the message headers (ie. &lt;code&gt;To:&lt;/code&gt;) for a list of recipients.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;If you don't happen to have have &lt;code&gt;sendmail&lt;/code&gt; available, you might want to look into what local mail programs you have available which can accept the output from the stylesheet.&lt;/p&gt;

&lt;p&gt;Once you have this working, the final task is to schedule its monthly execution with your local &lt;code&gt;cron&lt;/code&gt; installation.  If you haven't played with &lt;code&gt;cron&lt;/code&gt; before, there are many resources and tutorials available (&lt;a href=&quot;http://www.lysator.liu.se/~forsberg/linux/cron.html&quot; title=&quot;Doing things periodically - Using CRON&quot;&gt;here's one&lt;/a&gt; and &lt;a href=&quot;http://www.itworld.com/Comp/2378/swol-0825-unix101/&quot; title=&quot;Using cron basics&quot;&gt;here's another&lt;/a&gt;).  You should add something like the following to your user account's &lt;code&gt;crontab&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0 0 * 1 *  (cd /your/working/path; xsltproc wishes.xsl wishes.xml | sendmail -it)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &quot;&lt;code&gt;0 0 * 1 *&lt;/code&gt;&quot; indicates to &lt;code&gt;cron&lt;/code&gt; that this set of commands should be run at midnight on the first of every months.  Note also that &lt;code&gt;/your/working/path&lt;/code&gt; should be replaced by the path to where you've been working during this project.  And finally, I've renamed the final iteration of the stylesheet file to simply &lt;code&gt;wishes.xsl&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;So that's it--we have an XSL stylesheet which queries Amazon Web Services for products contained in multiple wishlists; selects a random item from each; prepares a shopping cart containing those items; and finally generates an email message containing both plain text and HTML presentations of the shopping cart and selected items.&lt;/p&gt;

&lt;p&gt;Though this implementation serves the purpose I wrote about at the start of this article, there are definitely many areas where this can be improved upon or expanded:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Many people think Amazon is an evil company for their use of patents.  I can't say that I'm entirely happy with them for this myself, but their AWS offering is just too nice to resist tinkering with.  It might be interesting to investigate other retailers' wishlist offerings, where they exist, and to see how this idea might be made to work with other (or even multiple) retailers.  Even better, come up with your own wishlist system, and a cross-retailer shopping cart.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I chose XSLT as the implementation technology because I thought it would be more natural to deal with Amazon's XML this way.  There are, admittedly, a few awkward parts in the resulting stylesheet however.  Sometimes it's good to see a project like this through, just to get a sense for where things do go awkward with a technology or my understanding of it.  It could be interesting to transliterate this into a scripting language like Python or Perl, perhaps using the &lt;a href=&quot;http://xmlsoft.org/python.html&quot;&gt;libxml bindings&lt;/a&gt; to do so.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The error and failure handling in this implementation are all but non-existent.  Should anything unexpected happen while dealing with Amazon Web Services, the results aren't likely to be very pretty.  You may want to consider improving in this area.  One instance I identified was to report when the sanity limit was hit in looping through wishlist pages, versus an actual end of pages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you play around with making more wishlist queries using the techniques here, you might want to consider caching the full set of data pulled in by the multiple-page calls to AWS, in order to prevent hammering Amazon's servers with repeated requests for the same data, likely unchanged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I still don't know why &lt;code&gt;exsl:random&lt;/code&gt; doesn't work for me.  Although I thought using a web service for random numbers was intereting, it would be very nice if I didn't have to use it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The HTML presentation could certainly use some good CSS to make it more attractive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Feel free to send me any suggestions, criticisms, or complaints related to this article!&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;shortname=wishofthemonthclub3&lt;/p&gt;
</content>
    </entry>
    
    

    <entry>
        <title>A mini-scraper for the playlist at radioio Rock</title>
        <link href="http://decafbad.com/blog/2004/06/28/radioiorock-scraper"/>
        <updated>2004-06-28T23:17:36+00:00</updated>
        <id>http://decafbad.com/blog/2004/06/28/radioiorock-scraper</id>
        <content type="html">&lt;p&gt;Lately, my iTunes has been playing &lt;a href=&quot;http://www.radioio.com/radioiorock.php?stream=radioioRock&quot;&gt;radioio Rock&lt;/a&gt; almost exclusively lately, but one thing that peeves me is that I don't seem to see the current song while the stream's playing.  Instead, the &lt;a href=&quot;http://www.radioio.com/&quot;&gt;radioio&lt;/a&gt; site offers a pop-up window that displays the last few songs in the playlist.  However, I'm usually somewhere off in another window or a shell and don't really feel like popping over to a browser and navigating to the playlist just to see what this song is.&lt;/p&gt;

&lt;p&gt;So, I wrote myself a little mini-scraper script:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/sh

curl -s 'http://player.radioio.com/player.php?b=614&amp;amp;#38;stream=radioioRock' | \
    tidy -asxml --wrap 300 -q -f /dev/null | \
    xml sel -t -m &quot;//*[@class='leadrock']&quot; -v '.' -n \
        -o '    [http://www.radioio.com' -v '../@href' -o ']' -n 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The output looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[06/29 11:01:08] deusx@Caffeina2:~ % radioio

Vast - I Need To Say Goodbye
    [http://www.radioio.com...]
Cure - The End Of The World
    [http://www.radioio.com...]
Seachange - Avs Co 10
    [http://www.radioio.com...]
Pixies - Bam Thwok
    [http://www.radioio.com...]
Death Cab For Cutie - The New Year
    [http://www.radioio.com...]
Lovethugs - Drawing The Curtains
    [http://www.radioio.com...]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oh yeah, and to run this script, you will need these tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://curl.haxx.se/&quot;&gt;curl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tidy.sourceforge.net/&quot;&gt;HTML Tidy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://xmlstar.sourceforge.net/&quot;&gt;XMLStarlet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Personally, I like the included URLs (which I edited here for length) since they launch a search for CDs by the artist.  However, you can cut the output down to just the artist/title by removing the final line of the script and the backslash at the end of the line before.&lt;/p&gt;

&lt;p&gt;If you like a different &lt;a href=&quot;http://www.radioio.com/&quot;&gt;radioio&lt;/a&gt; station, say &lt;a href=&quot;http://www.radioio.com/radioioeclectic.php?stream=radioioEclectic&quot;&gt;radioio Eclectic&lt;/a&gt;, you can change &lt;code&gt;stream=radioioRock&lt;/code&gt; to &lt;code&gt;stream=radioioEclectic&lt;/code&gt; in the URL above and change &lt;code&gt;class='leadrock'&lt;/code&gt; to &lt;code&gt;class='leadeclectic'&lt;/code&gt;.  I could have parameterized these, but I'm lazy, and that was the whole point!&lt;/p&gt;

&lt;p&gt;ShareAndEnjoy!&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;shortname=radioiorock_scraper&lt;/p&gt;

&lt;div id=&quot;comments&quot; class=&quot;comments archived-comments&quot;&gt;
            &lt;h3&gt;Archived Comments&lt;/h3&gt;
            
        &lt;ul class=&quot;comments&quot;&gt;
            
        &lt;li class=&quot;comment&quot; id=&quot;comment-221087229&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.bytecloud.com&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=7388f3fd9cfa9436c5282542aaccf4fd&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.bytecloud.com&quot;&gt;Mike Carter&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221087229&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2004-07-01T07:39:45&quot;&gt;2004-07-01T07:39:45&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;I was listening to some streams today for the first time in a while and I was thinking how annoying it was not to know the track names.  Thanks for posting this, it may come in handy!&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221087231&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://cpe000103c34069-cm014300001653.cpe.net.cable.rogers.com/weblogs/ben/&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=871196de9b27ed994c30428eed59073c&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://cpe000103c34069-cm014300001653.cpe.net.cable.rogers.com/weblogs/ben/&quot;&gt;Gnomon&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221087231&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2004-07-01T18:31:58&quot;&gt;2004-07-01T18:31:58&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;How is this the first time I've ever found out about XML Starlet? It's magnificent!

The application is cool, too, but /man/ - I'm going to have fun with XML Starlet. Thanks so very much for the pointer, Les!&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;li class=&quot;comment&quot; id=&quot;comment-221087232&quot;&gt;
            &lt;div class=&quot;meta&quot;&gt;
                &lt;div class=&quot;author&quot;&gt;
                    &lt;a class=&quot;avatar image&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.radioio.com/&quot;&gt;&lt;img src=&quot;http://www.gravatar.com/avatar.php?gravatar_id=0cfcb3aefaca714528c009a68810e8ec&amp;amp;size=32&amp;amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png&quot;/&gt;&lt;/a&gt;
                    &lt;a class=&quot;avatar name&quot; rel=&quot;nofollow&quot; 
                       href=&quot;http://www.radioio.com/&quot;&gt;Jesse&lt;/a&gt;
                &lt;/div&gt;
                &lt;a href=&quot;#comment-221087232&quot; class=&quot;permalink&quot;&gt;&lt;time datetime=&quot;2005-01-23T11:50:41&quot;&gt;2005-01-23T11:50:41&lt;/time&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;content&quot;&gt;I was searching around with blowsearch.com today (which btw blows heheh) and found this entry.  This earl might be of interest to ya:
http://69.28.133.51:1040/7.html
The db for searchplay and our players is only updated every 30 seconds, 7.html is near reatime right from our playback software.  :)

We used to have title streaming on our mp3 streams but are in transition of server and encoding software atm while we prepare to roll out our own software, and will be adding new formats such as heaac.  :)

Too much to talk about, we have a LOT of stuff planned for 2005-2006 that we've been working on (and patent pending) for years now.  Definately going to be exciting time for net radio.  Thanks for your interest Leslie.

jesse
chief tinkerer of toys,
radioio&lt;/div&gt;
            
        &lt;/li&gt;
    
        &lt;/ul&gt;
    
        &lt;/div&gt;



</content>
    </entry>
    
    

    <entry>
        <title>Wish-of-the-Month Club, Part 2 of 3</title>
        <link href="http://decafbad.com/blog/2004/06/28/wishofthemonthclub2"/>
        <updated>2004-06-28T01:44:51+00:00</updated>
        <id>http://decafbad.com/blog/2004/06/28/wishofthemonthclub2</id>
        <content type="html">&lt;p&gt;&lt;i&gt;Here's the next installment of the Wish-of-the-Month Club.  You can &lt;a href=&quot;http://www.decafbad.com/blog/2004/06/16/wishofthemonthclub1&quot;&gt;revisit the first part&lt;/a&gt;, too, if you've missed it.  I'd meant to post it within a week of the first part, so apologies all around to anyone who has been tapping a foot waiting for it.  Enjoy!&lt;/i&gt;&lt;/p&gt;

&lt;h3&gt;Paging Through Wishes&lt;/h3&gt;

&lt;p&gt;Some ready-made files are available for this section:
* &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/hacks/wishes/wishes-ex2.xsl&quot;&gt;&lt;code&gt;wishes-ex2.xsl&lt;/code&gt;&lt;/a&gt;: The second iteration of the stylesheet in development.&lt;/p&gt;

&lt;p&gt;Now we've got a way to make queries against Amazon Web Services, not entirely unlike what you might be used to if you tinker with MySQL databases on a regular basis.  At this point, though, we still have a bit of refining to make to this query.  If you take a look at the data produced by the query in its current state, and compare that to what you see on wishlists in your browser, you should notice some things missing.&lt;/p&gt;

&lt;p&gt;If you look at &lt;a href=&quot;http://www.amazon.com/exec/obidos/registry/1QWYI6P2JF3Q5&quot; title=&quot;Buy me something, will ya?&quot;&gt;my wishlist&lt;/a&gt;, you'll notice that items span several pages when visited by browser.  As it turns out, AWS queries work in a similar fashion--each query returns only a limited number of items (about 10), and an additional parameter supplied to further queries is required to step through further pages of results.  So, using what we've built so far will only get us to the first page of wishlist items; to get all of the items, we'll need a way to step through all of the pages.&lt;/p&gt;

&lt;p&gt;In playing with this, I experienced a bit of hairpulling frustration:  The AWS documentation, under &quot;Generating Additional Product Results&quot;, claims that XML returned by the service will supply a count of the total pages available for a given query.  And although I see this element present in other types of searches, the &lt;code&gt;TotalPages&lt;/code&gt; element is absent when querying on wishlists.  This may be a bug, or it may be an undocumented change in the service--either way, it was a surprise and leaves me with no official way to know how many pages I need to ask for in order to have a complete set of data.&lt;/p&gt;

&lt;p&gt;With some further tinkering, though, I figured out a workaround: If a query is made for a page number beyond the final page, the XML returned will be a duplicate of the final page.  Once I see a duplicate item appear, I know it's time to stop paging through results.  This is completely undocumented behavior, and could break at any time (ie. if Amazon decided to start issuing an error for a page index out of bounds), but it'll work for now.&lt;/p&gt;

&lt;p&gt;This calls for reworking the &lt;code&gt;processWishlist&lt;/code&gt; template.  For a given wishlist, it will need to iterate through a sequence of page numbers, requesting XML from AWS for each, stopping when the first duplicate page is found.  Since XSLT is heavily steeped in functional programming concepts, this sort of &lt;a href=&quot;http://www.dpawson.co.uk/xsl/sect2/N4806.html&quot; title=&quot;Iteration in XSLT&quot;&gt;iteration in XSLT&lt;/a&gt; is best done &lt;a href=&quot;http://www-106.ibm.com/developerworks/xml/library/x-xslrecur/&quot; title=&quot;Use recursion effectively in XSL&quot;&gt;with recursion&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  &amp;lt;xsl:template name=&quot;processWishlist&quot;&amp;gt;

    &amp;lt;xsl:param name=&quot;wishlist&quot; /&amp;gt;              &amp;lt;!-- Wishlist ID --&amp;gt;
    &amp;lt;xsl:param name=&quot;max&quot;   select=&quot;50&quot; /&amp;gt;     &amp;lt;!-- Arbitrary upper loop limit --&amp;gt;
    &amp;lt;xsl:param name=&quot;curr_page&quot; select=&quot;1&quot; /&amp;gt;  &amp;lt;!-- Curr page # --&amp;gt;
    &amp;lt;xsl:param name=&quot;prev_first_asin&quot; /&amp;gt;       &amp;lt;!-- Keeping track of repeats --&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first modification to this template is the addition of three parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;max&lt;/code&gt; provides an arbitrary upper limit to the number of pages through which this template will iterate.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;curr_page&lt;/code&gt; contains the number of the page to be requested in this iteration.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prev_first_asin&lt;/code&gt; will contain the ASIN number of the first item from the previous iteration's page of results.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Next, we modify the URL used to query for wishlist data:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;!-- Fetch the wishlist products --&amp;gt;
    &amp;lt;xsl:variable name=&quot;details&quot; select=&quot;document(concat(
                  'http://xml.amazon.com/onca/xml3?',
                  't=',$associate,'&amp;amp;amp;',
                  'dev-t=',$devtoken,'&amp;amp;amp;',
                  'WishlistSearch=',$wishlist,'&amp;amp;amp;',
                  'type=lite&amp;amp;amp;f=xml&amp;amp;amp;',
                  'page=',$curr_page))//Details&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The only addition here beyond the previous version is the &lt;code&gt;page&lt;/code&gt; parameter in the URL.  Not much mystery here--this parameter specifies which page of results we want.  Now, let's build the loop:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;!-- Snag the first item Asin --&amp;gt;
    &amp;lt;xsl:variable name=&quot;curr_first_asin&quot; select=&quot;$details/Asin/text()&quot; /&amp;gt;

    &amp;lt;!-- If we haven't exceeded the loop limit, and this first Asin isn't --&amp;gt;
    &amp;lt;!-- a repeat of the previous loop (indicating we've run out of new   --&amp;gt;
    &amp;lt;!-- pages), then go ahead...                                         --&amp;gt;
    &amp;lt;xsl:if test=&quot;(($curr_page+1) &amp;amp;lt; $max) and
                  (string-length($curr_first_asin) &amp;amp;gt; 0) and
                  not($curr_first_asin = $prev_first_asin)&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We capture the ASIN of the first item in this page of results and check to see if we should continue.  This &lt;code&gt;if&lt;/code&gt; conditional first ensures that we're not past the sanity guard for loop iterations, makes sure that we actually got a non-empty current first ASIN, then checks our current first product's ASIN against what was passed in as the previous iteration's first product's ASIN.  If this was the first time through the loop, this value should be empty and therefore wouldn't match the current ASIN.  But, if we've gone past the end of results, the previous and current ASIN values should match, and the conditional will fail.&lt;/p&gt;

&lt;p&gt;Moving along into the body of the conditional, we copy in wishlist products filtered on a price maximum, just as before:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;      &amp;lt;!-- Copy products, filtering on a maximum price --&amp;gt;
      &amp;lt;xsl:copy-of select=&quot;$details/OurPrice[number(substring(
                   text(),2)) &amp;amp;lt; $maxprice]/..&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Having done that, we move onto the recursive end of this template:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;      &amp;lt;!-- Loop by recursion to get the next page --&amp;gt;
      &amp;lt;xsl:call-template name=&quot;processWishlist&quot;&amp;gt;
        &amp;lt;xsl:with-param name=&quot;wishlist&quot;        select=&quot;$wishlist&quot; /&amp;gt;
        &amp;lt;xsl:with-param name=&quot;max&quot;             select=&quot;$max&quot; /&amp;gt;
        &amp;lt;xsl:with-param name=&quot;curr_page&quot;       select=&quot;$curr_page + 1&quot; /&amp;gt;
        &amp;lt;xsl:with-param name=&quot;prev_first_asin&quot; select=&quot;$curr_first_asin&quot; /&amp;gt;
      &amp;lt;/xsl:call-template&amp;gt;

    &amp;lt;/xsl:if&amp;gt;    
  &amp;lt;/xsl:template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here, the template makes a recursive call back to itself, passing through the wishlist ID and the maximum iteration count.  Since variables in XSLT are immutable, meaning that their values can't be changed once they've been set, we can't increment &lt;code&gt;$curr_page&lt;/code&gt; in-place like a loop counter in other languages--so, the current page count &lt;em&gt;value&lt;/em&gt; is incremented and passed to the recursive call as a parameter.  Finally, the current first item's ASIN is passed along, to become the previous ASIN for the next iteration.&lt;/p&gt;

&lt;p&gt;Note that when the conditional fails--that is, if the loop limit is passed or a duplicate page is detected--the loop ends.  In other words, nothing further happens and execution pops back up out of all the levels of recursion and the top-level template ends.&lt;/p&gt;

&lt;p&gt;I wrote &quot;&lt;em&gt;when&lt;/em&gt; the conditional fails&quot;.  This is a key point: for the loop to eventually end, this conditional &lt;em&gt;must&lt;/em&gt; fail (or be made to fail) at some point, else this loop will happily progress through page requests forever.  This is the reason for the &lt;code&gt;$max&lt;/code&gt; parameter limiting the number of iterations, in case something goes haywire--like, oh say, a failure of our duplicate-page detection hack as a loop ending condition.  A useful exercise for the reader might be to add some additional diagnostic code to report that the limit was hit versus a natural end to results.&lt;/p&gt;

&lt;h3&gt;Random Numbers&lt;/h3&gt;

&lt;p&gt;Some ready-made files are available for this section:
* &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/hacks/wishes/wishes-ex3.xsl&quot;&gt;&lt;code&gt;wishes-ex3.xsl&lt;/code&gt;&lt;/a&gt;: The third iteration of the stylesheet in development.
* &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/hacks/wishes/random-xml&quot;&gt;&lt;code&gt;random-xml&lt;/code&gt;&lt;/a&gt;: A Perl CGI script used as a web service to generate random numbers.&lt;/p&gt;

&lt;p&gt;Armed with a template that will query against the full set of items in a wishlist, we're ready to look into making a random selection from a list of products.&lt;/p&gt;

&lt;p&gt;But first, we need to pick a random number.  Unfortunately, there doesn't appear to be any &lt;code&gt;random()&lt;/code&gt; function in the XPath or XSLT standards.  There &lt;em&gt;is&lt;/em&gt; a &lt;a href=&quot;http://www.exslt.org/math/functions/random/index.html&quot;&gt;&lt;code&gt;math:random()&lt;/code&gt;&lt;/a&gt; from EXSLT implemented in &lt;code&gt;libxslt&lt;/code&gt;, but I seem to be having a bit of a problem getting it to produce anything other than the same sequence of numbers.  I suspect there's a problem in seeding the random number generator, but I've yet to work out how to fix it.  (Suggestions welcome.)&lt;/p&gt;

&lt;p&gt;So, I cheated and made another workaround with a CGI script on my web server that generates random numbers in a simple XML document.  Currently, it's hosted here:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://www.decafbad.com/2004/05/random-xml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And this is what the script looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/perl

use strict;
use CGI;

my $q = new CGI();

my $min = $q-&amp;gt;param('min') or 0;
my $max = $q-&amp;gt;param('max') or 1;
my $int = $q-&amp;gt;param('int');

my $num = $min + ( rand() * ($max - $min));
if ($int) { $num = int($num); }

print $q-&amp;gt;header('text/xml');
print &quot;&amp;lt;rand&amp;gt;$num&amp;lt;/rand&amp;gt;\n&quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a very simple CGI.  It accepts the parameters &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;min&lt;/code&gt;, and &lt;code&gt;int&lt;/code&gt;.  The values of these parameters determine the maximum and minimum value for the random number returned, and whether or not it should be an integer.  For example, the &lt;a href=&quot;http://www.decafbad.com/2004/05/random-xml?int=1&amp;amp;#38;min=10&amp;amp;#38;max=20&quot; title=&quot;A random integer between 10 and 20, in XML&quot;&gt;following URL&lt;/a&gt; should return an integer between 10 and 20:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://www.decafbad.com/2004/05/random-xml?
int=1&amp;amp;#38;min=10&amp;amp;#38;max=20
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using this as a web service in the stylesheet with the &lt;code&gt;document()&lt;/code&gt; function, we can get a random number.  If you've got web space where you can host CGI scripts, I suggest you host a copy of this script yourself, since I can't guarantee how long mine will stick around.  But, for as long at works, feel free to use the service from my server.&lt;/p&gt;

&lt;p&gt;Moving along, let's add a new named template to the stylesheet, called &lt;code&gt;randomWishlistProduct&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  &amp;lt;xsl:template name=&quot;randomWishlistProduct&quot;&amp;gt;

    &amp;lt;xsl:param name=&quot;wishlist&quot; /&amp;gt; &amp;lt;!-- Wishlist ID --&amp;gt;

    &amp;lt;!-- Gather all the products for the current wishlist --&amp;gt;
    &amp;lt;xsl:variable name=&quot;products&quot;&amp;gt;
      &amp;lt;xsl:call-template name=&quot;processWishlist&quot;&amp;gt;
        &amp;lt;xsl:with-param name=&quot;wishlist&quot; select=&quot;$wishlist&quot; /&amp;gt;
      &amp;lt;/xsl:call-template&amp;gt;
    &amp;lt;/xsl:variable&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Just like the &lt;code&gt;processWishlist&lt;/code&gt; template, we start by defining the parameter &lt;code&gt;wishlist&lt;/code&gt; to accept a wishlist ID.  Using this ID, we call the &lt;code&gt;processWishlist&lt;/code&gt; template itself and store the complete list of products queried from the wishlist into the variable &lt;code&gt;$products&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;!-- Count the products in the wishlist --&amp;gt;
    &amp;lt;xsl:variable name=&quot;max_products&quot;
                  select=&quot;count(exsl:node-set($products)/Details)&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This next step counts the number of products found in the wishlist.  The one tricky bit here is the use of the EXSLT function &lt;a href=&quot;http://www.exslt.org/exsl/functions/node-set/index.html&quot;&gt;&lt;code&gt;exsl:node-set()&lt;/code&gt;&lt;/a&gt;: The &lt;code&gt;$products&lt;/code&gt; variable contains what's called a &lt;a href=&quot;http://www.w3.org/TR/xslt#section-Result-Tree-Fragments&quot;&gt;&lt;em&gt;result tree fragment&lt;/em&gt;&lt;/a&gt;, which is a kind of cross between XML data nodes and a plain old string.  This type of data does not normally allow the full set of XPath operators to be used on it, so first we need to use &lt;code&gt;exsl:node-set()&lt;/code&gt; to turn it into a full-fledged node set.  Then we can look up the &lt;code&gt;Details&lt;/code&gt; element nodes and count them.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;!-- Conjure up a random index within the list of products --&amp;gt;
    &amp;lt;xsl:variable name=&quot;rand_product_num&quot;
                  select=&quot;document(concat(
                  'http://www.decafbad.com/2004/05/random-xml?',
                  'int=1&amp;amp;amp;',
                  'min=1&amp;amp;amp;',
                  'max=',$max_products))/rand&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here is where the random number service comes in handy.  The &lt;code&gt;concat()&lt;/code&gt; function is used to build the URL to the service, with parameters specifying that the number should be an integer, and should fall between 1 and the number of products in the wishlist.  The &lt;code&gt;document()&lt;/code&gt; function grabs the XML document from the service, and the value is extracted from the single element the document contains.&lt;/p&gt;

&lt;p&gt;There is an alternative to this last bit, should you happen to have a properly working &lt;code&gt;math:random()&lt;/code&gt; function in your XSLT processor:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;xsl:variable name=&quot;rand_product_num&quot; select=&quot;round( math:random() *
                  $max_products ) + 1&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you can use this instead, you'll have no need for the random number web service.  This version is obviously more concise, and doesn't require another trip out to a web service.  You might want to try it--but if you find that you keep getting the same wishlist items selected, then you've run into the problem I found with the random number generator.&lt;/p&gt;

&lt;p&gt;Now, let's wrap this template up by selecting an item:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;!-- Copy the product as indexed by the random number --&amp;gt;
    &amp;lt;xsl:copy-of select=&quot;exsl:node-set($products)/Details[
                 position()=$rand_product_num]&quot; /&amp;gt;

  &amp;lt;/xsl:template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, we need to use the &lt;code&gt;exsl:node-set()&lt;/code&gt; function to turn the result tree fragment in the &lt;code&gt;$products&lt;/code&gt; variable into a node set, from which we select and copy the &lt;code&gt;Details&lt;/code&gt; element whose position in the data is indexed by the random number we just selected.  Just one last tweak needed to wrap up this iteration of our stylesheet.  We need to swap out the call to the &lt;code&gt;processWishlist&lt;/code&gt; function at the end and replace it with a call to &lt;code&gt;randomWishlistProduct&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  &amp;lt;xsl:template match=&quot;/wishes:wishes&quot;&amp;gt;

    &amp;lt;xsl:for-each select=&quot;//wishes:wishlist&quot;&amp;gt;
      &amp;lt;wishes:wishitem&amp;gt;
        &amp;lt;xsl:copy-of select=&quot;.&quot; /&amp;gt;
        &amp;lt;xsl:call-template name=&quot;randomWishlistProduct&quot;&amp;gt;
          &amp;lt;xsl:with-param name=&quot;wishlist&quot; select=&quot;.&quot; /&amp;gt;
        &amp;lt;/xsl:call-template&amp;gt;
      &amp;lt;/wishes:wishitem&amp;gt;
    &amp;lt;/xsl:for-each&amp;gt;

  &amp;lt;/xsl:template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After these changes, you should be able to run the stylesheet ([wishes-ex3.xsl][wishes_ex3]) and get something like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;wishes:wishitem xmlns:wishes=&quot;http://www.decafbad.com/2004/05/wishes&quot;&amp;gt;
    &amp;lt;wishes:wishlist label=&quot;The Girl&quot;&amp;gt;35OIOYWQ9XQAE&amp;lt;/wishes:wishlist&amp;gt;
    &amp;lt;Details ...&amp;gt;...&amp;lt;/Details&amp;gt;
&amp;lt;/wishes:wishitem&amp;gt;
&amp;lt;wishes:wishitem xmlns:wishes=&quot;http://www.decafbad.com/2004/05/wishes&quot;&amp;gt;
    &amp;lt;wishes:wishlist label=&quot;Me&quot;&amp;gt;1QWYI6P2JF3Q5&amp;lt;/wishes:wishlist&amp;gt;
    &amp;lt;Details ...&amp;gt;...&amp;lt;/Details&amp;gt;
&amp;lt;/wishes:wishitem&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is similar to the output of the previous iteration of the stylesheet, but this time there's only one product selected at random for each wishlist.&lt;/p&gt;

&lt;h3&gt;Shopping Carts&lt;/h3&gt;

&lt;p&gt;Some ready-made files are available for this section:
* &lt;a href=&quot;http://www.decafbad.com/cvs/*checkout*/hacks/wishes/wishes-ex4.xsl&quot;&gt;&lt;code&gt;wishes-ex4.xsl&lt;/code&gt;&lt;/a&gt;: The fourth iteration of the stylesheet in development.&lt;/p&gt;

&lt;p&gt;By this point, we've been able to query and filter products in Amazon wishlists, and we've selected an item at random from each wishlist we've queried.  Now, let's enable some purchases.&lt;/p&gt;

&lt;p&gt;The AWS provides for Remote Shopping Cart functionality, whereby items can be added to an Amazon.com shopping cart programmatically.  This is about as close as we can get to automating the purchase of items selected from the wishlists--there is no API functionality for actually completing the ordering of items.  If you really think about it, this really is a good thing and &lt;em&gt;should&lt;/em&gt; demand human intervention; we certainly wouldn't want this script going crazy and accidentally buying up everything on a wishlist.&lt;/p&gt;

&lt;p&gt;Documentation for the AWS Remote Shopping Cart explains that a shopping cart can be created and items added with a URL like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://xml.amazon.com/onca/xml3?
ShoppingCart=add&amp;amp;#38;
f=xml&amp;amp;#38;
dev-t=[Developer Token goes here]&amp;amp;#38;
t=[Associates ID goes here]&amp;amp;#38;
Asin.[ASIN goes here]=[quantity goes here]&amp;amp;#38;
sims=true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Part of this should look familiar, so we already know what to do with the developer token and the associates ID.  The last part, specifying product ASIN and quantity, can be filled out with information contained in the product records selected at random from the wishlists.&lt;/p&gt;

&lt;p&gt;So, let's start by revising the template at the end of the stylesheet:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;xsl:template match=&quot;/wishes:wishes&quot;&amp;gt;

    &amp;lt;xsl:variable name=&quot;random_products&quot;&amp;gt;      
      &amp;lt;xsl:for-each select=&quot;//wishes:wishlist&quot;&amp;gt;
        &amp;lt;wishes:wishitem&amp;gt;
          &amp;lt;xsl:copy-of select=&quot;.&quot; /&amp;gt;
          &amp;lt;xsl:call-template name=&quot;randomWishlistProduct&quot;&amp;gt;
            &amp;lt;xsl:with-param name=&quot;wishlist&quot; select=&quot;.&quot; /&amp;gt;
          &amp;lt;/xsl:call-template&amp;gt;
        &amp;lt;/wishes:wishitem&amp;gt;
      &amp;lt;/xsl:for-each&amp;gt;
    &amp;lt;/xsl:variable&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here, we've taken what was the output of the previous iteration of the stylesheet and stuffed it into the variable &lt;code&gt;$random_products&lt;/code&gt;.  Next, let's fill in the blanks and build a Remote Shopping Cart URL:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;xsl:variable name=&quot;shopping_cart_create_url&quot;&amp;gt;
      &amp;lt;!-- Standard AWS URL --&amp;gt;
      &amp;lt;xsl:text&amp;gt;http://xml.amazon.com/onca/xml3?&amp;lt;/xsl:text&amp;gt;

      &amp;lt;!-- Add in the selected items --&amp;gt;
      &amp;lt;xsl:for-each select=&quot;exsl:node-set($random_products)
                            /wishes:wishitem/Details&quot;&amp;gt;
        &amp;lt;xsl:text&amp;gt;Asin.&amp;lt;/xsl:text&amp;gt;&amp;lt;xsl:value-of select=&quot;Asin&quot; /&amp;gt;
        &amp;lt;xsl:text&amp;gt;=1&amp;amp;amp;&amp;lt;/xsl:text&amp;gt;
      &amp;lt;/xsl:for-each&amp;gt;

      &amp;lt;!-- Wrap up with the shopping cart function and required tokens --&amp;gt;
      &amp;lt;xsl:text&amp;gt;ShoppingCart=add&amp;amp;amp;&amp;lt;/xsl:text&amp;gt;
      &amp;lt;xsl:text&amp;gt;f=xml&amp;amp;amp;&amp;lt;/xsl:text&amp;gt;
      &amp;lt;xsl:text&amp;gt;dev-t=&amp;lt;/xsl:text&amp;gt;&amp;lt;xsl:value-of select=&quot;$devtoken&quot; /&amp;gt;
      &amp;lt;xsl:text&amp;gt;&amp;amp;amp;&amp;lt;/xsl:text&amp;gt;
      &amp;lt;xsl:text&amp;gt;t=&amp;lt;/xsl:text&amp;gt;&amp;lt;xsl:value-of select=&quot;$associate&quot; /&amp;gt;
    &amp;lt;/xsl:variable&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since simple XPath doesn't allow for the looping needed for multiple items, we can't just concatenate this URL together in a &lt;code&gt;select&lt;/code&gt; expression like we did with the wishlist item query.  So, we use &lt;code&gt;xslt:foreach&lt;/code&gt; to build this with blocks of text using the &lt;code&gt;xsl:text&lt;/code&gt; element.  We iterate though the random products chosen from wishlists and add an ASIN for each to the URL with a quantity of 1. Then, we use the &lt;code&gt;$devtoken&lt;/code&gt; and &lt;code&gt;$associate&lt;/code&gt; variables to fill in their respective spots.&lt;/p&gt;

&lt;p&gt;Note that this could have been written without using the &lt;code&gt;xsl:text&lt;/code&gt; elements like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;xsl:variable name=&quot;shopping_cart_create_url&quot;&amp;gt;http://xml.amazon.
    com/onca/xml3?ShoppingCart=add&amp;amp;amp;f=xml&amp;amp;amp;dev-t=&amp;lt;xsl:value-of 
    select=&quot;$devtoken&quot; /&amp;gt;&amp;amp;amp;t=&amp;lt;xsl:value-of select=&quot;$associate&quot; /&amp;gt;
    &amp;amp;amp;&amp;lt;xsl:for-each select=&quot;exsl:node-set($random_products)/
    wishes:wishitem/Details&quot;&amp;gt;Asin.&amp;lt;xsl:value-of select=&quot;Asin&quot; /&amp;gt;=1
    &amp;amp;amp;&amp;lt;/xsl:for-each&amp;gt;&amp;lt;/xsl:variable&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This removes the clutter of all the &lt;code&gt;xsl:text&lt;/code&gt; elements, but it would need to be piled all on one line in order to keep undesired whitespace from getting into the URL.  I made a small attempt at wrapping this line here, but line breaks and spaces would leave us with a non-functioning shopping cart URL.  It's up to you to decide which to use--personally, I prefer the &lt;code&gt;xsl:text&lt;/code&gt; clutter for the ability to add in comments and clarify things a bit.&lt;/p&gt;

&lt;p&gt;Finally, having built the shopping cart URL, let's use it to get a shopping cart and wrap things up:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &amp;lt;xsl:variable name=&quot;shopping_cart&quot;
                  select=&quot;document($shopping_cart_create_url)&quot; /&amp;gt;

    &amp;lt;xsl:copy-of select=&quot;$shopping_cart&quot; /&amp;gt;

&amp;lt;/xsl:template&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As an aside, this part is pushing the concept of a REST web service a bit: In the REST philosophy, requests using the GET method (which is what &lt;code&gt;document()&lt;/code&gt; uses) should only return existing resources and not create new resources or cause modifications to happen.  Instead, these sorts of actions should use a POST request.  But, since we've already accepted a few rough edges and workarounds in this project so far, we won't let a point of esoterica like that stop us.  (That and, well, this is the way Amazon designed their web service, so we'll take what we can get.)&lt;/p&gt;

&lt;p&gt;Once you run this iteration of the stylesheet ([wishes-ex4.xsl][wishes_ex4]), you should get something like this XML as output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;ShoppingCartResponse ...&amp;gt;
  ...
  &amp;lt;ShoppingCart&amp;gt;
   &amp;lt;CartId&amp;gt;...&amp;lt;/CartId&amp;gt;
   &amp;lt;HMAC&amp;gt;...&amp;lt;/HMAC&amp;gt;
   &amp;lt;PurchaseUrl&amp;gt;...&amp;lt;/PurchaseUrl&amp;gt;
   &amp;lt;Items&amp;gt;
    &amp;lt;Item&amp;gt;...&amp;lt;/item&amp;gt;
    &amp;lt;Item&amp;gt;...&amp;lt;/item&amp;gt;
   &amp;lt;/Items&amp;gt;
  &amp;lt;/ShoppingCart&amp;gt;
  ...
&amp;lt;/ShoppingCartResponse&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The AWS documentation describes the vital elements here like so:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CartId&lt;/code&gt; - The Cart ID is the unique identifier for a given shopping cart.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HMAC&lt;/code&gt; - The HMAC is a security token that must be passed back to Amazon Web Services for using an existing cart.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PurchaseUrl&lt;/code&gt; - Use the purchase URL to transfer the remote shopping cart from your application to Amazon so that your application's users may complete their purchases.&amp;#160; The purchase URL merges the remote shopping cart with the Amazon.com shopping cart.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;So, in short, whenever we want to do any sort of manipulation on this Remote Shopping Cart via AWS, we'll need to remember and later supply both the &lt;code&gt;CartId&lt;/code&gt; and &lt;code&gt;HMAC&lt;/code&gt; found in the XML returned at its creation.  And, once we're all ready to check out, the &lt;code&gt;PurchaseUrl&lt;/code&gt; points to where we'll need to browse in person.&lt;/p&gt;

&lt;h3&gt;Stay Tuned!&lt;/h3&gt;

&lt;p&gt;This concludes Part 2 of the Wish-of-the-Month Club.  Following this will be the final part, where we tie everything together and start firing off monthly emails!&lt;/p&gt;

&lt;!-- links --&gt;




&lt;!--more--&gt;


&lt;p&gt;shortname=wishofthemonthclub2&lt;/p&gt;
</content>
    </entry>
    
    
</feed>

