O'Reilly Hacks
oreilly.comO'Reilly NetworkSafari BookshelfConferences Sign In/My Account | View Cart   
Book List Learning Lab PDFs O'Reilly Gear Newsletters Press Room Jobs  


 
Buy the book!
XML Hacks
By Michael Fitzgerald
July 2004
More Info

HACK
#90
Syndicate a List of Books from Amazon with RSS and ASP
Someday all date will be available as RSS. Get a head start by syndicating Amazon search results.
The Code
[Discuss (0) | Link to this hack]

The Code

The file amazon_rss.asp is in the file archive for the book. Be sure to change the Const declarations to match your setup.

<%
'' AMAZON-RSS.ASP
'' Sean P. Nolan
'' http://www.yaywastaken.com/
''
'' This code is free for you to use as you see fit. Copy it, rewrite it, 
'' run it yourself, whatever. But no warranties or guarantees either. Who
'' knows what the hell it does. Not me, that's for sure!
''
'' Generates an RSS 0.91 feed from an Amazon book query
''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Const MAX_PAGES_DEFAULT = 10
    Const DEV_TOKEN = "insert developer token"
    Const AFFILIATE_CODE = "insert associate tag"
    Const XSL_FILE = "amazon_lite.xsl" 'change to heavy for more info.

    Dim szTitle, szMaxPages, nMaxPages

    Response.ContentType = "text/xml"
    Server.ScriptTimeout = 60 * 4 ' 4-minute maximum
    Response.Expires = 0

    szMaxPages = Request.QueryString("maxpages")
    If (szMaxPages = "") Then
        nMaxPages = MAX_PAGES_DEFAULT
    Else
        nMaxPages = CLng(szMaxPages)
    End If

    szTitle = "Amazon Books: " & XMLify(Request.QueryString("keywords"))

    %><?xml version="1.0" encoding="ISO-8859-1" ?>
<rss version="0.91">
    <channel>
        <link>http://www.yaywastaken.com/amazon/</link>
        <title><%= szTitle %></title>
        <description>Create your own custom Amazon RSS feed!</description>
        <language>en-us</language>
<% 
RenderItems Request.QueryString("keywords"), _
            Request.QueryString("browse") , _
            Request.QueryString("author") , _
            Request.QueryString("shortdesc"), _
            nMaxPages
%>

    </channel>
</rss>
    <%

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' RenderItems

    Sub RenderItems(szKeywords, szBrowseNode, szAuthor, szShortDesc, 

nMaxPages)
        Dim szURLFmt, szURL, xmlDoc, ipage, http, xmlErr
        Dim fParsed, xslDoc, szXSLPath, szOutput

        'On Error Resume Next

        If (szShortDesc <> "") Then
            szXSLPath = "amazon-lite.xsl"
        Else
            szXSLPath = "amazon-heavy.xsl"
        End If

        Set xslDoc = Server.CreateObject("Msxml2.DOMDocument")
        xslDoc.async = False
        xslDoc.load(Server.MapPath(szXSLPath))

        If (szBrowseNode <> "") Then
            szURLFmt = "http://xml.amazon.com/onca/xml?v=1.0&" & _
                       "t=" & AFFILIATE_CODE & _
                          "&dev-t=" & DEV_TOKEN & "&BrowseNodeSearch=" & _
                          Server.URLEncode(szBrowseNode) & _
                          "&mode=books&type=heavy&page=%%%PAGE%%%&f=xml"
        ElseIf (szAuthor <> "") Then
            szURLFmt = "http://xml.amazon.com/onca/xml?v=1.0&" & _
                       "t=" & AFFILIATE_CODE & _
                          "&dev-t=" & DEV_TOKEN & "&AuthorSearch=" & _
                          Server.URLEncode(szAuthor) & _
                          "&mode=books&type=heavy&page=%%%PAGE%%%&f=xml"
        Else
            szURLFmt = "http://xml.amazon.com/onca/xml?v=1.0&" & _
                       "t=" & AFFILIATE_CODE & _
                          "&dev-t=" & DEV_TOKEN & "&KeywordSearch=" & _
                          Server.URLEncode(szKeywords) & _
                          "&mode=books&type=heavy&page=%%%PAGE%%%&f=xml"
        End If

        ipage = 1
        Do
            szURL = Replace(szURLFmt, "%%%PAGE%%%", ipage)

            Set http = Server.CreateObject("Msxml2.ServerXMLHTTP")
            http.open "GET", szURL, False
            http.send ""

            If (http.status <> 200) Then
                Exit Do
            End If

            Set xmlDoc = Server.CreateObject("Msxml2.DOMDocument")
            xmlDoc.async = False
            xmlDoc.validateOnParse = False
            xmlDoc.resolveExternals = False
            fParsed = xmlDoc.loadXML(http.responseText)

            If (Not fParsed) Then
                Exit Do
            End If

            Set xmlErr = Nothing
            Set xmlErr = xmlDoc.selectSingleNode("ProductInfo/ErrorMsg")
            If (Not xmlErr Is Nothing) Then
                Exit Do
            End If

        Set xslDoc = Nothing
            Set xslDoc = Server.CreateObject("Msxml2.DOMDocument")
            xslDoc.async = False
            xslDoc.validateOnParse = False
            xslDoc.resolveExternals = False
        xslDoc.load(Server.MapPath(XSL_FILE))

            szOutput = xmlDoc.transformNode(xslDoc)
            Response.Write szOutput

            ipage = ipage + 1
            If (ipage > nMaxPages) Then
                Exit Do
            End If
        Loop
    End Sub

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Helpers

    Function XMLify(sz)
        XMLify = Replace(sz, "&", "&amp;")
        XMLify = Replace(XMLify, "<", "<")
        XMLify = Replace(XMLify, ">", ">")
        XMLify = Replace(XMLify, """""", """")
        XMLify = Replace(XMLify, "'", "&apos;")
    End Function
%>

This file makes an Amazon Web Services XML/HTTP request based on querystring variables passed in the URL, and transforms the XML locally with an XSL stylesheet. Depending on how much detail you want in the RSS feed, there are two different stylesheets. The first, for light data, is called amazon_lite.xsl.

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" />
<xsl:template match="ProductInfo/Details">
    <item><link>
    <xsl:value-of select="@url" />
    </link><title>
    <xsl:value-of select="ProductName" />
    </title><description>
        <xsl:text>Author: </xsl:text>
        <xsl:value-of select="Authors/Author[1]" />
        <xsl:text>; </xsl:text>
        <xsl:value-of select="OurPrice" />
        <xsl:if test="Availability">
            <xsl:text> (</xsl:text>
            <xsl:value-of select="Availability" />
            <xsl:if test="Availability = 'Pre Order'">
                <xsl:text>: release date </xsl:text>
                <xsl:value-of select="ReleaseDate" />
            </xsl:if>
            <xsl:text>)</xsl:text>
        </xsl:if>
    </description></item>
</xsl:template>

<xsl:template match="/">
    <xsl:apply-templates select="ProductInfo/Details" />
</xsl:template>

</xsl:stylesheet>

Another stylesheet, appropriately titled amazon_heavy.xsl, provides more detailed information in the feed.

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" />
<xsl:template match="ProductInfo/Details">
    <item><link>
    <xsl:value-of select="@url" />
    </link><title>
    <xsl:value-of select="ProductName" />
    </title><description>
        <br />
        <xsl:element name="a">
            <xsl:attribute name="href">
                <xsl:value-of select="@url" />
            </xsl:attribute>
            <xsl:element name="img">
                <xsl:attribute name="src">
                    <xsl:value-of select="ImageUrlMedium" />
                </xsl:attribute>
                <xsl:attribute name="border">0</xsl:attribute>
                <xsl:attribute name="hspace">4</xsl:attribute>
                <xsl:attribute name="vspace">4</xsl:attribute>
                <xsl:attribute name="align">left</xsl:attribute>
            </xsl:element>
        </xsl:element>

        <font size="+1">
        <xsl:element name="a">
            <xsl:attribute name="href">
                <xsl:value-of select="@url" />
            </xsl:attribute>
            <xsl:value-of select="ProductName" />
        </xsl:element>
        </font>
        <br />
        <xsl:text>Author: </xsl:text>
        <xsl:value-of select="Authors/Author[1]" />
        <xsl:text>; </xsl:text>
        <xsl:value-of select="OurPrice" />
        <xsl:if test="Availability">
            <xsl:text> (</xsl:text>
            <xsl:value-of select="Availability" />
            <xsl:if test="Availability = 'Pre Order'">
                <xsl:text>, release date </xsl:text>
                <xsl:value-of select="ReleaseDate" />
            </xsl:if>
            <xsl:text>)</xsl:text>
        </xsl:if>
        <br clear="all" />

        <xsl:for-each select="Reviews/CustomerReview">
            <xsl:choose>
                <xsl:when test="Rating = 1">
                    <img src="http://g-images.amazon.com/images/G/01/

detail/stars-1-0.gif" border="0" hspace="2" vspace="2" />
                </xsl:when>
                <xsl:when test="Rating = 2">
                    <img src="http://g-images.amazon.com/images/G/01/

detail/stars-2-0.gif" border="0" hspace="2" vspace="2" />
                </xsl:when>
                <xsl:when test="Rating = 3">
                    <img src="http://g-images.amazon.com/images/G/01/

detail/stars-3-0.gif" border="0" hspace="2" vspace="2" />
                </xsl:when>
                <xsl:when test="Rating = 4">
                    <img src="http://g-images.amazon.com/images/G/01/

detail/stars-4-0.gif" border="0" hspace="2" vspace="2" />
                </xsl:when>
                <xsl:when test="Rating = 5">
                    <img src="http://g-images.amazon.com/images/G/01/

detail/stars-5-0.gif" border="0" hspace="2" vspace="2" />
                </xsl:when>
            </xsl:choose>
            <b><xsl:value-of select="Summary" /></b>
            <br />
            <xsl:value-of select="Comment" />
            <br /><br />
        </xsl:for-each>
    </description></item>
</xsl:template>

<xsl:template match="/">
    <xsl:apply-templates select="ProductInfo/Details" />
</xsl:template>

</xsl:stylesheet>


O'Reilly Home | Privacy Policy

© 2007 O'Reilly Media, Inc.
Website: | Customer Service: | Book issues:

All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.