I've written some code to render sitemaps, although not as part of a module. It's included below.
One gotcha: yahoo's size limit for sitemaps is smaller than google or bing, so you may need to gzip larger site maps. This is probably best done by the webserver rather than a module, but maybe it can be included in the module documentation.
Going over the routes file is a good start, however presumably each of the main urls will have a different priority.
This is what I have in my conf:
sitemap.sites=google,yahoo,bing
sitemap.sites.google=
http://www.google.com/webmasters/sitemaps/ping?sitemap=
sitemap.sites.yahoo=
http://search.yahooapis.com/SiteExplorerService/V1/ping?sitemap=sitemap.sites.bing=
http://www.bing.com/webmaster/ping.aspx?siteMap=
Here's the class that all my site maps extend from:
public class RenderSitemapXml extends RenderXml {
public RenderSitemapXml(Document doc) {
super(doc);
}
protected static Document createSiteMapDocument() {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new UnexpectedException(e);
}
Document doc = builder.newDocument();
// Create root (urlset) element
Element root = doc.createElement("urlset");
root.setAttribute("xmlns", "
http://www.sitemaps.org/schemas/sitemap/0.9");
root.setAttribute("xmlns:geo", "
http://www.google.com/geo/schemas/sitemap/1.0");
root.setAttribute("xmlns:xsi", "
http://www.w3.org/2001/XMLSchema-instance");
String xsiVersion = "
http://www.sitemaps.org/schemas/sitemap/0.9";
String xsiXsd = "
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd";
root.setAttribute("xsi:schemaLocation", xsiVersion + " " + xsiXsd);
doc.appendChild(root);
return doc;
}
protected static Element createUrl(Document doc, String loc, String changefreq, Double priority) {
Element url = doc.createElement("url");
appendTextElement(url, "loc", loc);
appendTextElement(url, "changefreq", changefreq);
appendTextElement(url, "priority", priority);
return url;
}
protected static void appendTextElement(Element parent, String name, Object value) {
if (value == null) {
return;
}
Document doc = parent.getOwnerDocument();
Element child = doc.createElement(name);
parent.appendChild(child);
child.appendChild(doc.createTextNode(value.toString()));
}
}
An example Controller:
public static void siteMap() {
List<ServiceType> serviceTypes = ServiceType.findAll();
List<City> cities = City.findAll();
throw new RenderSitemap(serviceTypes, cities);
}
An example site map:
public class RenderSitemap extends RenderSitemapXml {
private final static String[] pages = { "/help", "/providers/login", "/legal",
"/users/privacy", "/feedback/new", "/serviceTypes/suggest",
"/providers/forgotPassword", "/support/new" };
public RenderSitemap(List<ServiceType> serviceTypes, List<City> cities) {
super(getDocument(serviceTypes, cities));
}
private static Document getDocument(List<ServiceType> serviceTypes, List<City> cities) {
String currentLang = Lang.get();
// The main language for my site is Spanish
Lang.set("es");
Document doc = createSiteMapDocument();
Element root = doc.getDocumentElement();
String homeLoc = Router.getFullUrl("ServiceTypes.all");
root.appendChild(createUrl(doc, homeLoc, "daily", 0.9));
for (String page : pages) {
String pageLoc = Request.current().getBase() + page;
root.appendChild(createUrl(doc, pageLoc, "daily", 0.1));
}
...
Lang.set(currentLang);
return doc;
}