Sitemap Generator

Earlier today Yahoo and Google announced their collaboration on Sitemaps provide a way to describe to a search engine what pages make up your web site. I've had sitemap support in BlogCFC for a while, but today I wrote a little UDF you can use to generate sitemap xml. It will take either a list of URLs or a query of URLs. Enjoy. I'll post it to CFLib later in the week.

<cffunction name="generateSiteMap" output="false" returnType="xml"> <cfargument name="data" type="any" required="true"> <cfargument name="lastmod" type="date" required="false"> <cfargument name="changefreq" type="string" required="false"> <cfargument name="priority" type="numeric" required="false">
&lt;cfset var header = "&lt;?xml version=""1.0"" encoding=""UTF-8""?&gt;&lt;urlset xmlns=""""&gt;"&gt;
&lt;cfset var result = header&gt;
&lt;cfset var aurl = ""&gt;
&lt;cfset var item = ""&gt;
&lt;cfset var validChangeFreq = "always,hourly,daily,weekly,monthly,yearly,never"&gt;
&lt;cfset var newDate = ""&gt;
&lt;cfset var tz = getTimeZoneInfo().utcHourOffset&gt;

&lt;cfif structKeyExists(arguments, "changefreq") and not listFindNoCase(validChangeFreq, arguments.changefreq)&gt;
	&lt;cfthrow message="Invalid changefreq (#arguments.changefreq#) passed. Valid values are #validChangeFreq#"&gt;

&lt;cfif structKeyExists(arguments, "priority") and (arguments.priority lt 0 or arguments.priority gt 1)&gt;
	&lt;cfthrow message="Invalid priority (#arguments.priority#) passed. Must be between 0.0 and 1.0"&gt;

&lt;!--- reformat datetime as w3c datetime / ---&gt;
&lt;cfif structKeyExists(arguments, "lastmod")&gt;			
	&lt;cfset newDate = dateFormat(arguments.lastmod, "YYYY-MM-DD") & "T" & timeFormat(arguments.lastmod, "HH:mm")&gt;
	&lt;cfif tz gte 0&gt;
		&lt;cfset newDate = newDate & "-" & tz & ":00"&gt;
		&lt;cfset newDate = newDate & "+" & tz & ":00"&gt;

&lt;!--- Support either a query or list of URLs ---&gt;
&lt;cfif isSimpleValue(;
	&lt;cfloop index="aurl" list=""&gt;
		&lt;cfsavecontent variable="item"&gt;

<cfoutput> <url> <loc>#xmlFormat(aurl)#</loc> <cfif structKeyExists(arguments,"lastmod")> <lastmod>#newDate#</lastmod> </cfif> <cfif structKeyExists(arguments,"changefreq")> <changefreq>#arguments.changefreq#</changefreq> </cfif> <cfif structKeyExists(arguments,"priority")> <priority>#arguments.priority#</priority> </cfif> </url> </cfoutput> </cfsavecontent> <cfset item = trim(item)> <cfset result = result & item> </cfloop>

&lt;cfelseif isQuery(;
	&lt;cfloop query=""&gt;
		&lt;cfsavecontent variable="item"&gt;

<cfoutput> <url> <loc>#xmlFormat(url)#</loc> <cfif listFindNoCase(,"lastmod")> <cfset newDate = dateFormat(lastmod, "YYYY-MM-DD") & "T" & timeFormat(lastmod, "HH:mm")> <cfif tz gte 0> <cfset newDate = newDate & "-" & tz & ":00"> <cfelse> <cfset newDate = newDate & "+" & tz & ":00"> </cfif> <lastmod>#newDate#</lastmod> </cfif> <cfif listFindNoCase(,"changefreq")> <changefreq>#changefreq#</changefreq> </cfif> <cfif listFindNoCase(,"priority")> <priority>#priority#</priority> </cfif> </url> </cfoutput> </cfsavecontent> <cfset item = trim(item)> <cfset result = result & item>


&lt;cfset result = result & "&lt;/urlset&gt;"&gt;

&lt;cfreturn result&gt;


Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA