CFLib.org – Common Function Library Project

generateSiteMap(data[, lastmod][, changefreq][, priority])

Last updated August 14, 2007

author

Raymond Camden

Version: 2 | Requires: CF6 | Library: UtilityLib

Description:
Generates a valid Site Map XML from either a list of URLs or a query of URLs.

Return Values:
Returns a string.

Example:

<cfset urls = "http://www.foo.com/index.cfm,http://www.foo.com/index2.cfm,http://www.foo.com/index3.cfm">

<cfset siteMapXML = generateSiteMap(urls)>
<cfdump var="#xmlParse(siteMapXML)#">

<cfset siteMapXML = generateSiteMap(data=urls,changefreq="hourly",priority="0.2", lastmod=now())>
<cfdump var="#xmlParse(siteMapXML)#">

<cfset qUrls = queryNew("url,lastmod,changefreq,priority")>
<cfset changefreq = "always,hourly,daily,weekly,monthly,yearly,never">

<cfloop index="x" from="1" to="30">
	<cfset queryAddRow(qUrls)>
	<cfset querySetCell(qUrls, "url", "http://www.foo.com/page/#x#")>
	<cfset randomdate = dateAdd("d", -1 * randrange(1,7), now())>
	<cfset randomdate = dateAdd("h", -1 * randrange(1,24), randomdate)>
	<cfset querySetCell(qUrls, "lastmod", randomdate)>
	<cfset querySetCell(qUrls, "changefreq", listGetAt(changefreq, randRange(1, listLen(changefreq))))>
	<cfset querySetCell(qUrls, "priority", randrange(1,10)/10)>
</cfloop>

<cfset siteMapXML = generateSiteMap(qurls)>
<cfdump var="#xmlParse(siteMapXML)#">

Parameters:

Name Description Required
data Either a list of URLs or a query. Yes
lastmod Date to use for all URLs as their lastmod property. If not passed, the value will not be used in the XML unless a query is used and the column lastmod exists. No
changefreq Value to use for all URLs as their changefreq property. If not passed, the value will not be used in the XML unless a query is used and the column changefreq exists. No
priority Value to use for all URLs as their priority property. If not passed, the value will not be used in the XML unless a query is used and the column priority exists. No

Full UDF Source:

<!---
 Generates a valid Site Map XML from either a list of URLs or a query of URLs.
 
 @param data 	 Either a list of URLs or a query. (Required)
 @param lastmod 	 Date to use for all URLs as their lastmod property. If not passed, the value will not be used in the XML unless a query is used and the column lastmod exists. (Optional)
 @param changefreq 	 Value to use for all URLs as their changefreq property. If not passed, the value will not be used in the XML unless a query is used and the column changefreq exists. (Optional)
 @param priority 	 Value to use for all URLs as their priority property. If not passed, the value will not be used in the XML unless a query is used and the column priority exists. (Optional)
 @return Returns a string. 
 @author Raymond Camden (ray@camdenfamily.com) 
 @version 2, August 14, 2007 
--->
<cffunction name="generateSiteMap" output="false" returnType="string">
	<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">
	
	<cfset var header = "<?xml version=""1.0"" encoding=""UTF-8""?><urlset xmlns=""http://www.sitemaps.org/schemas/sitemap/0.9"">">
	<cfset var s = createObject('java','java.lang.StringBuffer').init(header)>
	<cfset var aurl = "">
	<cfset var item = "">
	<cfset var validChangeFreq = "always,hourly,daily,weekly,monthly,yearly,never">
	<cfset var newDate = "">
	<cfset var tz = getTimeZoneInfo().utcHourOffset>
	<cfset var btz = replaceList(tz, "+,-","")>
	
	<cfif structKeyExists(arguments, "changefreq") and not listFindNoCase(validChangeFreq, arguments.changefreq)>
		<cfthrow message="Invalid changefreq (#arguments.changefreq#) passed. Valid values are #validChangeFreq#">
	</cfif>

	<cfif structKeyExists(arguments, "priority") and (arguments.priority lt 0 or arguments.priority gt 1)>
		<cfthrow message="Invalid priority (#arguments.priority#) passed. Must be between 0.0 and 1.0">
	</cfif>
	
	<!--- reformat datetime as w3c datetime / http://www.w3.org/TR/NOTE-datetime --->
	<cfif structKeyExists(arguments, "lastmod")>			
		<cfset newDate = dateFormat(arguments.lastmod, "YYYY-MM-DD") & "T" & timeFormat(arguments.lastmod, "HH:mm")>
		<cfif tz gt 0>
			<cfset newDate = newDate & "-" & numberFormat(btz,"00") & ":00">
		<cfelse>
			<cfset newDate = newDate & "+" & numberFormat(btz,"00") & ":00">
		</cfif>		
	</cfif>
	
	<!--- Support either a query or list of URLs --->
	<cfif isSimpleValue(arguments.data)>
		<cfloop index="aurl" list="#arguments.data#">
			<cfsavecontent variable="item">
				<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 s.append(item)>
		</cfloop>
	<!--- url, lastmod, changefreq, and priority were changed to have the arguments.data.whatever and I also added the array notation to each like so [arguments.data.currentrow] --->
	<cfelseif isQuery(arguments.data)>
		<cfloop query="arguments.data">
			<cfsavecontent variable="item">
				<cfoutput>
				<url>
					<loc>#xmlFormat(arguments.data.url[arguments.data.currentrow])#</loc>
					<cfif listFindNoCase(arguments.data.columnlist,"lastmod")>
						<cfset newDate = dateFormat(arguments.data.lastmod[arguments.data.currentrow], "YYYY-MM-DD") & "T" & timeFormat(arguments.data.lastmod[arguments.data.currentrow], "HH:mm")>
						<cfif tz gt 0>
							<cfset newDate = newDate & "-" & numberFormat(btz,"00") & ":00">
						<cfelse>
							<cfset newDate = newDate & "+" & numberFormat(btz,"00") & ":00">
						</cfif>		
						<lastmod>#newDate#</lastmod>
					</cfif>
					<cfif listFindNoCase(arguments.data.columnlist,"changefreq")>
					<changefreq>#arguments.data.changefreq[arguments.data.currentrow]#</changefreq>
					</cfif>
					<cfif listFindNoCase(arguments.data.columnlist,"priority")>
					<priority>#arguments.data.priority[arguments.data.currentrow]#</priority>
					</cfif>
				</url>
				</cfoutput>
			</cfsavecontent>
			<cfset item = trim(item)>
			<cfset s.append(item)>
		
		</cfloop>
	</cfif>	
	<cfset s.append("</urlset>")>

	<cfreturn s>
	
</cffunction>
blog comments powered by Disqus

Search CFLib.org


Latest Additions

Kevin Cotton added
date2ExcelDate
May 5, 2016

Raymond Camden added
CapFirst
April 25, 2016

Chris Wigginton added
loremIpsum
January 18, 2016

Gary Stanton added
calculateArrival...
November 19, 2015

Sebastiaan Naafs - van Dijk added
getDaysInQuarter
November 13, 2015

Created by Raymond Camden / Design by Justin Johnson