Index: gsitemap.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/gsitemap/Attic/gsitemap.module,v
retrieving revision 1.56.2.1
diff -u -p -r1.56.2.1 gsitemap.module
--- gsitemap.module	11 Jan 2007 07:04:16 -0000	1.56.2.1
+++ gsitemap.module	14 Mar 2007 18:52:08 -0000
@@ -95,7 +95,7 @@ function gsitemap_nodeapi(&$node, $op, $
       }
       db_query("INSERT INTO {gsitemap} (nid, last_changed, priority_override) VALUES(%d, %d, %s)", $node->nid, $node->changed, $node->priority_override);
       if (variable_get('gsitemap_submit', 0) && $node->status) {
-        _gsitemap_submit();
+        _gsitemap_submit_on_exit();
       }
       break;
     case 'load':
@@ -126,13 +126,13 @@ function gsitemap_nodeapi(&$node, $op, $
         }
       }
       if (variable_get('gsitemap_submit', 0) && ($node->status || $oldnode->status)) {
-        _gsitemap_submit();
+        _gsitemap_submit_on_exit();
       }
       break;
     case 'delete':
       db_query("DELETE FROM {gsitemap} WHERE nid=%d", $node->nid);
       if (variable_get('gsitemap_submit', 0) && $node->status) {
-        _gsitemap_submit();
+        _gsitemap_submit_on_exit();
       }
       break;
     case 'validate':
@@ -163,7 +163,7 @@ function gsitemap_comment($op, $comment)
         db_query("UPDATE {gsitemap} SET last_comment=%d, previous_comment=%d WHERE nid=%d", $comment[timestamp], $node->last_comment, $node->nid);
       }
       if (variable_get('gsitemap_submit', 0)) {
-        _gsitemap_submit();
+        _gsitemap_submit_on_exit();
       }
     }
   }
@@ -181,7 +181,7 @@ function gsitemap_comment($op, $comment)
         db_query("UPDATE {gsitemap} SET last_comment=%d, previous_comment=%d WHERE nid=%d", $comment->timestamp, $node->last_comment, $node->nid);
       }
       if (variable_get('gsitemap_submit', 0)) {
-        _gsitemap_submit();
+        _gsitemap_submit_on_exit();
       }
     }
   }
@@ -196,6 +196,14 @@ function gsitemap_admin_settings() {
     '#title' => t('Priority Settings'),
     '#collapsible' => TRUE,
   );
+  $form['priority_settings']['gsitemap_chunk_size'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Chunk size'),
+    '#default_value' => variable_get('gsitemap_chunk_size', '10000'),
+    '#size' => 10,
+    '#maxlength' => 5,
+    '#description' => t('This is the number of links to send at one time.  Values can range between 1 and 50,000.'),
+  );
   $form['priority_settings']['gsitemap_frontpage'] = array(
     '#type' => 'textfield',
     '#title' => t('Front page priority'),
@@ -265,6 +273,13 @@ function gsitemap_admin_settings() {
     '#default_value' => variable_get('gsitemap_showterms', 0),
     '#description' => t('If enabled, links to taxonomy term pages will be included in the sitemap.'),
   );
+  $form['other_settings']['gsitemap_showusers'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Include links to user profile pages'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('gsitemap_showusers', 0),
+    '#description' => t('If enabled, links to user profile pages will be included in the sitemap (requires requestor to have "access user profiles" permission).'),
+  );
   $form['other_settings']['gsitemap_submit'] = array(
     '#type' => 'checkbox',
     '#title' => t('Submit sitemap to Google when updated'),
@@ -292,16 +307,86 @@ function gsitemap_admin_settings() {
   return system_settings_form($form);
 }
 
+function gsitemap_admin_settings_validate($form_id, $form_values) {
+  if ($form_values['gsitemap_chunk_size'] > 50000) {
+    form_set_error('priority_settings][gsitemap_chunk_size', t('Cannot send more than 50,000 links at one time.'));
+  }
+}
+
 function gsitemap_cron() {
   if (variable_get('gsitemap_cron_submit', 0)) {
     _gsitemap_submit();
   }
 }
 
-function gsitemap_output() {
+function gsitemap_output($chunk=NULL) {
+  if (!isset($chunk)) {
+    gsitemap_output_index();
+    $type = "Sitemap index";
+  } else {
+    gsitemap_output_chunk($chunk);
+    $type = "Sitemap chunk $chunk";
+  }
+
+  if(variable_get('gsitemap_logacc',0)) {
+    if(strpos(getenv('HTTP_USER_AGENT'),'Googlebot')) {
+      watchdog('gsitemap',$type . ' downloaded by Google.');
+    }
+    else {
+      watchdog('gsitemap',$type . ' downloaded by ' . getenv('HTTP_USER_AGENT') . ' at ' . getenv('REMOTE_ADDR') . '.');
+    }
+  }
+}
+
+function gsitemap_get_chunk_range($chunk) {
+  $range->low = $chunk * variable_get('gsitemap_chunk_size', '10000');
+  $range->high = ($chunk + 1) * variable_get('gsitemap_chunk_size', '10000');
+  return $range;
+}
+
+function gsitemap_output_index() {
+  global $base_url;
+  $countcom = variable_get('gsitemap_countcom',1);
+
+  header("Content-type: text/xml");
+  print '<?xml version="1.0" encoding="UTF-8"?>';
+  print '<?xml-stylesheet type="text/xsl" href="' . $base_url .'/'. drupal_get_path('module', 'gsitemap') .'/gss.xsl'.'"?>';
+
+  $result = db_fetch_object(db_query("SELECT MAX(nid) as max FROM {node}"));
+  $max_nid = $result->max;
+
+  print '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd">';
+  for ($i = 0; $i < $max_nid / variable_get('gsitemap_chunk_size', '10000'); $i++) {
+    print '<sitemap>';
+    print '<loc>' . url("gsitemap/" . $i, NULL, NULL, TRUE) . '</loc>';
+
+    $range = gsitemap_get_chunk_range($i);
+    $result = db_fetch_object(
+      db_query(sprintf("SELECT MAX(changed) as changed from {node} WHERE nid >= %d AND nid < %d",
+		       $range->low, $range->high)));
+    $last_changed_node = $result->changed;
+
+    if ($countcom) {
+      $result = db_fetch_object(
+	db_query(sprintf("SELECT MAX(timestamp) as timestamp from {comments} WHERE nid >= %d AND nid < %d",
+			 $range->low, $range->high)));
+      $last_changed_comment = $result->timestamp;
+    } else {
+      $last_changed_comment = 0;
+    }
+
+    print '<lastmod>' . gmdate("Y-m-d\TH:i:s+00:00", max($last_changed_node, $last_changed_comment)) . '</lastmod>';
+    print '</sitemap>';
+  }
+  print '</sitemapindex>';
+}
+
+function gsitemap_output_chunk($chunk) {
+  global $base_url;
   if (!ini_get('safe_mode')) {
     set_time_limit(240);
   }
+  $range = gsitemap_get_chunk_range($chunk);
   $countcom = variable_get('gsitemap_countcom', 1);
   $excluded_types = array("''");
   foreach (node_get_types() as $type => $name) {
@@ -312,16 +397,19 @@ function gsitemap_output() {
   $excludes = implode(',', $excluded_types);
   drupal_set_header("Content-type: text/xml; charset=utf-8");
   print '<?xml version="1.0" encoding="UTF-8"?>';
-  print '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
+  print '<?xml-stylesheet type="text/xsl" href="' . $base_url .'/'. drupal_get_path('module', 'gsitemap') .'/gss.xsl'.'"?>';
+  print '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">';
   print '<url><loc>' . url('', NULL, NULL, TRUE) . '</loc><changefreq>always</changefreq><priority>' . variable_get('gsitemap_frontpage', '1.0') . '</priority></url>';
   $count = array();
-  $result = db_query("SELECT COUNT(*) AS count FROM {node}");
+  $result = db_query(sprintf("SELECT COUNT(*) AS count FROM {node} WHERE nid >= %d AND nid < %d",
+			     $range->low, $range->high));
   $count[0] = db_fetch_object($result);
-  $result = db_query("SELECT COUNT(*) AS count FROM {gsitemap}");
+  $result = db_query(sprintf("SELECT COUNT(*) AS count FROM {gsitemap} WHERE nid >= %d AND nid < %d",
+			     $range->low, $range->high));
   $count[1] = db_fetch_object($result); 
   if (module_exists('comment')) {
     if ($count[0]->count != $count[1]->count) {
-      $result = db_query("SELECT {node}.nid, changed FROM {node} LEFT JOIN {gsitemap} USING(nid) WHERE {gsitemap}.nid IS NULL");
+      $result = db_query(sprintf("SELECT {node}.nid, changed FROM {node} LEFT JOIN {gsitemap} USING(nid) WHERE {gsitemap}.nid IS NULL AND {node}.nid >= %d AND {node}.nid < %d", $range->low, $range->high));
       while($node = db_fetch_object($result)) {
         db_query("INSERT INTO {gsitemap} (nid, last_changed) VALUES(%d, %d)", $node->nid, $node->changed);
       }
@@ -331,7 +419,7 @@ function gsitemap_output() {
       }
     }
     $maxcomments = db_fetch_object(db_query("SELECT MAX(comment_count) AS max_comments FROM {node_comment_statistics}"));
-    $result = db_query(db_rewrite_sql("SELECT DISTINCT(n.nid), n.type, n.status, n.promote, s.comment_count, n.changed, g.previously_changed, s.last_comment_timestamp, g.previous_comment, g.priority_override FROM {node} n LEFT JOIN {node_comment_statistics} s ON n.nid=s.nid LEFT JOIN {gsitemap} g ON n.nid=g.nid LEFT JOIN {url_alias} u ON src=CONCAT('node/', n.nid) WHERE n.status > 0 AND (g.priority_override >= 0 OR g.priority_override IS NULL) AND n.type NOT IN (" . $excludes . ")", 'n'));
+    $result = db_query(db_rewrite_sql(sprintf("SELECT DISTINCT(n.nid), n.type, n.status, n.promote, s.comment_count, n.changed, g.previously_changed, s.last_comment_timestamp, g.previous_comment, g.priority_override FROM {node} n LEFT JOIN {node_comment_statistics} s ON n.nid=s.nid LEFT JOIN {gsitemap} g ON n.nid=g.nid LEFT JOIN {url_alias} u ON src=CONCAT('node/', n.nid) WHERE n.status > 0 AND (g.priority_override >= 0 OR g.priority_override IS NULL) AND n.type NOT IN (" . $excludes . ") AND n.nid >= %d AND n.nid < %d", $range->low, $range->high), 'n'));
   }
   else {
     if ($count[0]->count != $count[1]->count) {
@@ -340,7 +428,7 @@ function gsitemap_output() {
         db_query("INSERT INTO {gsitemap} (nid, last_changed) VALUES(%d, %d)", $node->nid, $node->changed);
       }
     }
-    $result = db_query(db_rewrite_sql("SELECT DISTINCT(n.nid), n.type, n.status, n.promote, n.changed, g.previously_changed, g.priority_override FROM {node} n LEFT JOIN {gsitemap} g ON n.nid=g.nid LEFT JOIN {url_alias} u ON src=CONCAT('node/', n.nid) WHERE n.status > 0 AND (g.priority_override >=0 OR g.priority_override IS NULL) AND n.type NOT IN (" . $excludes . ")", 'n'));
+    $result = db_query(db_rewrite_sql(sprintf("SELECT DISTINCT(n.nid), n.type, n.status, n.promote, n.changed, g.previously_changed, g.priority_override FROM {node} n LEFT JOIN {gsitemap} g ON n.nid=g.nid LEFT JOIN {url_alias} u ON src=CONCAT('node/',n.nid) WHERE n.status > 0 AND (g.priority_override >=0 OR g.priority_override IS NULL) AND n.type NOT IN (" . $excludes . ") AND n.nid >= %d AND n.nid < %d", $range->low, $range->high), 'n'));
   } 
   while($node = db_fetch_object($result)) {
     $pri = _gsitemap_calc_priority($node, $maxcomments->max_comments);
@@ -411,6 +499,15 @@ function gsitemap_output() {
       }
     }
   }
+  if(variable_get('gsitemap_showusers', 0)) {
+    foreach(user_search() as $user) {
+      /* The user module passes the link through url(), which returns a URL
+       * relative to the server.  We need an absolute URL, so we employ this
+       * wonderful hack to get it.
+       */
+      print '<url><loc>' . url(strstr($user[link], 'user/'), NULL, NULL, TRUE) . '</loc><changefreq>always</changefreq></url>';
+    }
+  }
   $additional = module_invoke_all('gsitemap');
   foreach ($additional as $entry) {
     print '<url>';
@@ -471,6 +568,32 @@ function _gsitemap_calc_priority($node, 
   return $pri;
 } 
 
+/**
+ * Schedule a call to _gsitemap_submit() to be run on exit. Use this function
+ * instead of _gsitemap_submit() to avoid a delay for outputting the page to
+ * the user.
+ *
+ * @return If the function has not been called previously, FALSE. Otherwise,
+ * TRUE.
+ */
+function _gsitemap_submit_on_exit() {
+  static $called = FALSE;
+
+  $return = $called;
+  $called = TRUE;
+  return $return;
+}
+
+/**
+ * Implementation of hook_exit() which is used to call _gsitemap_submit() if
+ * _gsitemap_submit_on_exit() was called.
+ */
+function gsitemap_exit() {
+  if (_gsitemap_submit_on_exit()) {
+    _gsitemap_submit();
+  }
+}
+
 function _gsitemap_submit() {
   $result = drupal_http_request('http://www.google.com/webmasters/tools/ping?sitemap='. url('gsitemap', NULL, NULL, TRUE));
   if ($result->code == 200) {
@@ -480,3 +603,4 @@ function _gsitemap_submit() {
     watchdog('gsitemap', t('Error occurred submitting sitemap to Google: @code', array('@code' => $result->code)), WATCHDOG_ERROR); 
   }
 }
+
Index: gss.xsl
===================================================================
RCS file: gss.xsl
diff -N gss.xsl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gss.xsl	14 Mar 2007 18:52:08 -0000
@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- Google Sitmaps Stylesheets (GSStylesheets)
+     Project Home: http://sourceforge.net/projects/gstoolbox
+     Copyright (c) 2005 Baccou Bonneville SARL (http://www.baccoubonneville.com)
+     License http://www.gnu.org/copyleft/lesser.html GNU/LGPL
+     
+     Created by Serge Baccou
+     1.0 / 20 Aug 2005
+       
+     Changes by Johannes Müller (http://GSiteCrawler.com)
+     1.1 / 20 Aug 2005 - sorting by clicking on column headers
+                       - open urls in new window/tab 
+                       - some stylesheet/CSS cleanup 
+     1.5a/ 31 Aug 2005 - added version number in footer
+                       - removed images (don't allow tracking on other servers)
+     
+     Changes by Tobias Kluge (http://enarion.net)
+     1.2 / 22 Aug 2005 - moved sitemap file and sitemap index file into one file gss.xsl
+	 1.5 / 27 Aug 2005 - added js and css into xslt stylesheet; only gss.xsl is needed now
+     
+     Changes by Serge Baccou
+     1.3 / 23 Aug 2005 - some XSLT cleanup
+     1.4 / 24 Aug 2005 - sourceForge and LGPL links and logos
+                       - sorting is working for siteindex (see gss.js) 
+     
+     Changes by Matthew Loar
+     1.5 / 11 Jan 2007 - made to work with sitemaps.org schema -->
+
+
+<xsl:stylesheet version="2.0" 
+                xmlns:html="http://www.w3.org/TR/REC-html40"
+                xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  
+  <xsl:output method="html" version="1.0" encoding="iso-8859-1" indent="yes"/>
+  
+  <!-- Root template -->    
+  <xsl:template match="/">
+    <html>     
+      <head>  
+        <title>Google Sitemap File</title>
+        <link href="http://www.google.com/webmasters/sitemaps/docs/sitemaps.css" type="text/css" rel="stylesheet"/>
+		<style type="text/css">
+		  <![CDATA[
+			<!--
+			h1 { 
+				font-weight:bold;
+				font-size:1.5em;
+				margin-bottom:0;
+				margin-top:1px; }
+			
+			h2 { 
+				font-weight:bold;
+				font-size:1.2em;
+				margin-bottom:0; 
+				color:#707070;
+				margin-top:1px; }
+			
+			#gssTitle {
+			  background: url(http://www.baccoubonneville.com/gss.jpg) no-repeat;   	
+			  line-height: 70px;
+			  text-indent: 70px; }
+			
+			p.sml { 
+				font-size:0.8em;
+				margin-top:0; }
+			
+			.sortup {
+				background-position: right center;
+				background-image: url(http://www.google.com/webmasters/sitemaps/images/sortup.gif);
+				background-repeat: no-repeat;
+				font-style:italic;
+				white-space:pre; }
+				
+			.sortdown {
+				background-position: right center;
+				background-image: url(http://www.google.com/webmasters/sitemaps/images/sortdown.gif);
+				background-repeat: no-repeat;
+				font-style:italic;
+				white-space:pre; }
+			
+			table.copyright {
+				width:100%;
+				border-top:1px solid #ddad08;
+				margin-top:1em;
+				text-align:center;
+				padding-top:1em;
+				vertical-align:top; }
+			-->
+		  ]]>
+		</style>
+        <script language="JavaScript">
+		  <![CDATA[
+			var selectedColor = "blue";
+			var defaultColor = "black";
+			var hdrRows = 1;
+			var numeric = '..';
+			var desc = '..';
+			var html = '..';
+			var freq = '..';
+			
+			function initXsl(tabName,fileType) {
+				hdrRows = 1;
+			
+			  if(fileType=="sitemap") {
+			  	numeric = ".3.";
+			  	desc = ".1.";
+			  	html = ".0.";
+			  	freq = ".2.";
+			  	initTable(tabName);
+				  setSort(tabName, 3, 1);
+			  }
+			  else {
+			  	desc = ".1.";
+			  	html = ".0.";
+			  	initTable(tabName);
+				  setSort(tabName, 1, 1);
+			  }
+			
+				var theURL = document.getElementById("head1");
+				theURL.innerHTML += ' ' + location;
+				document.title += ': ' + location;
+			}
+			
+			function initTable(tabName) {
+			  var theTab = document.getElementById(tabName);
+			  for(r=0;r<hdrRows;r++)
+			   for(c=0;c<theTab.rows[r].cells.length;c++)
+			     if((r+theTab.rows[r].cells[c].rowSpan)>hdrRows)
+			       hdrRows=r+theTab.rows[r].cells[c].rowSpan;
+			  for(r=0;r<hdrRows; r++){
+			    colNum = 0;
+			    for(c=0;c<theTab.rows[r].cells.length;c++, colNum++){
+			      if(theTab.rows[r].cells[c].colSpan<2){
+			        theCell = theTab.rows[r].cells[c];
+			        rTitle = theCell.innerHTML.replace(/<[^>]+>|&nbsp;/g,'');
+			        if(rTitle>""){
+			          theCell.title = "Change sort order for " + rTitle;
+			          theCell.onmouseover = function(){setCursor(this, "selected")};
+			          theCell.onmouseout = function(){setCursor(this, "default")};
+			          var sortParams = 15; // bitmapped: numeric|desc|html|freq
+			          if(numeric.indexOf("."+colNum+".")>-1) sortParams -= 1;
+			          if(desc.indexOf("."+colNum+".")>-1) sortParams -= 2;
+			          if(html.indexOf("."+colNum+".")>-1) sortParams -= 4;
+			          if(freq.indexOf("."+colNum+".")>-1) sortParams -= 8;
+			          theCell.onclick = new Function("sortTable(this,"+(colNum+r)+","+hdrRows+","+sortParams+")");
+			        }
+			      } else {
+			        colNum = colNum+theTab.rows[r].cells[c].colSpan-1;
+			      }
+			    }
+			  }
+			}
+			
+			function setSort(tabName, colNum, sortDir) {
+				var theTab = document.getElementById(tabName);
+				theTab.rows[0].sCol = colNum;
+				theTab.rows[0].sDir = sortDir;
+				if (sortDir) 
+					theTab.rows[0].cells[colNum].className='sortdown'
+				else
+					theTab.rows[0].cells[colNum].className='sortup';
+			}
+			
+			function setCursor(theCell, mode){
+			  rTitle = theCell.innerHTML.replace(/<[^>]+>|&nbsp;|\W/g,'');
+			  if(mode=="selected"){
+			    if(theCell.style.color!=selectedColor) 
+			      defaultColor = theCell.style.color;
+			    theCell.style.color = selectedColor;
+			    theCell.style.cursor = "hand";
+			    window.status = "Click to sort by '"+rTitle+"'";
+			  } else {
+			    theCell.style.color = defaultColor;
+			    theCell.style.cursor = "";
+			    window.status = "";
+			  }
+			}
+			
+			function sortTable(theCell, colNum, hdrRows, sortParams){
+			  var typnum = !(sortParams & 1);
+			  sDir = !(sortParams & 2);
+			  var typhtml = !(sortParams & 4);
+			  var typfreq = !(sortParams & 8);
+			  var tBody = theCell.parentNode;
+			  while(tBody.nodeName!="TBODY"){
+			    tBody = tBody.parentNode;
+			  }
+			  var tabOrd = new Array();
+			  if(tBody.rows[0].sCol==colNum) sDir = !tBody.rows[0].sDir;
+			  if (tBody.rows[0].sCol>=0)
+			    tBody.rows[0].cells[tBody.rows[0].sCol].className='';
+			  tBody.rows[0].sCol = colNum;
+			  tBody.rows[0].sDir = sDir;
+			  if (sDir) 
+			  	 tBody.rows[0].cells[colNum].className='sortdown'
+			  else 
+			     tBody.rows[0].cells[colNum].className='sortup';
+			  for(i=0,r=hdrRows;r<tBody.rows.length;i++,r++){
+			    colCont = tBody.rows[r].cells[colNum].innerHTML;
+			    if(typhtml) colCont = colCont.replace(/<[^>]+>/g,'');
+			    if(typnum) {
+			      colCont*=1;
+			      if(isNaN(colCont)) colCont = 0;
+			    }
+			    if(typfreq) {
+					switch(colCont.toLowerCase()) {
+						case "always":  { colCont=0; break; }
+						case "hourly":  { colCont=1; break; }
+						case "daily":   { colCont=2; break; }
+						case "weekly":  { colCont=3; break; }
+						case "monthly": { colCont=4; break; }
+						case "yearly":  { colCont=5; break; }
+						case "never":   { colCont=6; break; }
+					}
+				}
+			    tabOrd[i] = [r, tBody.rows[r], colCont];
+			  }
+			  tabOrd.sort(compRows);
+			  for(i=0,r=hdrRows;r<tBody.rows.length;i++,r++){
+			    tBody.insertBefore(tabOrd[i][1],tBody.rows[r]);
+			  } 
+			  window.status = ""; 
+			}
+			
+			function compRows(a, b){
+			  if(sDir){
+			    if(a[2]>b[2]) return -1;
+			    if(a[2]<b[2]) return 1;
+			  } else {
+			    if(a[2]>b[2]) return 1;
+			    if(a[2]<b[2]) return -1;
+			  }
+			  return 0;
+			}
+
+		  ]]>
+		</script>
+        
+      </head>
+
+      <!-- Store in $fileType if we are in a sitemap or in a siteindex -->
+      <xsl:variable name="fileType">
+        <xsl:choose>
+		  <xsl:when test="//sitemap:url">sitemap</xsl:when>
+		  <xsl:otherwise>siteindex</xsl:otherwise>
+        </xsl:choose>      
+      </xsl:variable>            
+
+      <!-- Body -->
+      <body onLoad="initXsl('table0','{$fileType}');">  
+            
+        <!-- Text and table -->
+        <h1 id="head1">Google Sitemap</h1>        
+        <xsl:choose>
+	      <xsl:when test="$fileType='sitemap'"><xsl:call-template name="sitemapTable"/></xsl:when>
+	      <xsl:otherwise><xsl:call-template name="siteindexTable"/></xsl:otherwise>
+  		</xsl:choose>
+          
+        <!-- Copyright notice
+             &#x0020; means significant space character -->          
+        <br/>
+        <table class="copyright" id="table_copyright">
+          <tr>
+            <td>
+              <p>Google Sitemaps: © 2005 <a href="http://www.google.com">Google</a> - <a href="https://www.google.com/webmasters/sitemaps/stats">My Sitemaps</a> - <a href="http://www.google.com/webmasters/sitemaps/docs/en/about.html">About</a> - <a href="http://www.google.com/webmasters/sitemaps/docs/en/faq.html">FAQ</a> - <a href="http://groups-beta.google.com/group/google-sitemaps">Discussion</a> - <a href="http://sitemaps.blogspot.com/">Blog</a></p>
+              Google Sitemaps Stylesheets v1.5a: © 2005 <a href="http://www.baccoubonneville.com">Baccou Bonneville</a> - <a href="http://sourceforge.net/projects/gstoolbox">Project</a> - <a href="http://www.baccoubonneville.com/blogs/index.php/webdesign/2005/08/20/google-sitemaps-stylesheets">Blog</a><br/>
+              Contributions: Johannes Müller, SOFTplus <a href="http://gsitecrawler.com">GSiteCrawler</a> - Tobias Kluge, enarion.net <a href="http://enarion.net/google/phpsitemapng">phpSitemapNG</a>
+            </td>
+          </tr>
+        </table>
+      </body>
+    </html>
+  </xsl:template>     
+
+  <!-- siteindexTable template -->
+  <xsl:template name="siteindexTable">
+    <h2>Number of sitemaps in this Google sitemap index: <xsl:value-of select="count(sitemap:sitemapindex/sitemap:sitemap)"></xsl:value-of></h2>          
+    <p class="sml">Click on the table headers to change sorting.</p>
+    <table border="1" width="100%" class="data" id="table0">
+      <tr class="header">
+        <td>Sitemap URL</td>
+        <td>Last modification date</td>
+      </tr>
+      <xsl:apply-templates select="sitemap:sitemapindex/sitemap:sitemap">
+        <xsl:sort select="sitemap:lastmod" order="descending"/>              
+      </xsl:apply-templates>  
+    </table>            
+  </xsl:template>  
+  
+  <!-- sitemapTable template -->  
+  <xsl:template name="sitemapTable">
+    <h2>Number of URLs in this Google Sitemap: <xsl:value-of select="count(sitemap:urlset/sitemap:url)"></xsl:value-of></h2>          
+    <p class="sml">Click on the table headers to change sorting.</p>
+    <table border="1" width="100%" class="data" id="table0">
+	  <tr class="header">
+	    <td>Sitemap URL</td>
+		<td>Last modification date</td>
+		<td>Change freq.</td>
+		<td>Priority</td>
+	  </tr>
+	  <xsl:apply-templates select="sitemap:urlset/sitemap:url">
+	    <xsl:sort select="sitemap:priority" order="descending"/>              
+	  </xsl:apply-templates>
+	</table>  
+  </xsl:template>    
+  
+  <!-- sitemap:url template -->  
+  <xsl:template match="sitemap:url">
+    <tr>  
+      <td>
+        <xsl:variable name="sitemapURL"><xsl:value-of select="sitemap:loc"/></xsl:variable>  
+        <a href="{$sitemapURL}" target="_blank" ref="nofollow"><xsl:value-of select="$sitemapURL"></xsl:value-of></a>
+      </td>
+      <td><xsl:value-of select="sitemap:lastmod"/></td>
+      <td><xsl:value-of select="sitemap:changefreq"/></td>
+      <td><xsl:value-of select="sitemap:priority"/></td>
+    </tr>  
+  </xsl:template>
+  
+  <!-- sitemap:sitemap template -->
+  <xsl:template match="sitemap:sitemap">
+    <tr>  
+      <td>        
+        <xsl:variable name="sitemapURL"><xsl:value-of select="sitemap:loc"/></xsl:variable>  
+        <a href="{$sitemapURL}"><xsl:value-of select="$sitemapURL"></xsl:value-of></a>
+      </td>
+      <td><xsl:value-of select="sitemap:lastmod"/></td>
+    </tr>  
+  </xsl:template>  
+  
+</xsl:stylesheet>
