diff -up footnotes.module footnotes-alt.module
--- footnotes.module	2007-12-24 23:02:33.000000000 +0000
+++ footnotes-alt.module	2008-07-12 16:07:39.000000000 +0000
@@ -98,7 +98,7 @@ function footnotes_filter($op, $delta = 
         // The actual filtering is performed here. The supplied text should be
         // returned, once any necessary substitutions have taken place.
         case 'process':
-          $text = preg_replace_callback('|<fn>(.*?)</fn>|s', '_footnotes_replace_callback', $text);
+          $text = preg_replace_callback('|<fn([^>]*)>(.*?)</fn>|s', '_footnotes_replace_callback', $text);
           
           //Replace tag <footnotes> with the list of footnotes.
           //If tag is not present, by default add the footnotes at the end.
@@ -163,17 +163,19 @@ function _footnotes_replace_callback( $m
   $str = '';
   
   if( $op == 'output footer' ) {
-    if( $n > 0 ) {
+    if (count($store_matches) > 0) {
       $str = '<ol class="footnotes">';
-      for( $m = 1; $m <= $n; $m++ ){
-        $text = $store_matches[ $m - 1 ][0];
-        $randstr = $store_matches[ $m - 1 ][1];
-        $str .= '<li><a class="footnote" name="footnote' . $m . '_' . $randstr .
-                '" href="#footnoteref' . $m . '_' . $randstr . '">' . $m . '.</a> ';
+      // loop through the stored footnotes
+      foreach ($store_matches as $fn_attr) {
+        list($text,$randstr,$label) = $fn_attr; 
+        $str .= '<li><a class="footnote" name="footnote' . $label . '_' .
+                $randstr .'" href="#footnoteref' . $label . '_' . 
+                $randstr . '">' . $label . '.</a> ';
         $str .= $text . "</li>\n";
       }
       $str .= "</ol>\n";
     }
+  
     $n = 0;
     $store_matches = array();
     return $str;
@@ -184,9 +186,28 @@ function _footnotes_replace_callback( $m
   //Random string used to ensure footnote id's are unique, even 
   //when contents of multiple nodes reside on same page. (fixes http://drupal.org/node/194558)
   $randstr = _footnotes_helper_randstr();
-
-  array_push( $store_matches, array( $matches[1], $randstr ) );
+  
   $n++;
+  $label = '';
+  //did the pattern match anything in the <fn> tag?
+  if ($matches[1]) {
+    // see if label can parsed, either well-formed in quotes eg <fn label='3'>
+  	if (preg_match('|label=["\'](.*?)["\']|',$matches[1],$label_match)) {
+      $label = $label_match[1];
+    // or without quotes eg <fn label=8>  
+  	} elseif (preg_match('|label=(\S*?)|',$matches[1],$label_match)) {
+      $label = $label_match[1];
+  	} else {
+  	  // no valid label, use the item count
+  	  $label = $n;
+  	}
+  } else {
+    // plain <fn>, use the item count
+    $label = $n;
+  }
+  // store the footnote text, randstr, and the footnote label
+  array_push( $store_matches, array( $matches[2], $randstr, $label) );
+
   $allowed_tags = array();
   $title = filter_xss($matches[1], $allowed_tags);
   //html attribute cannot contain quotes
@@ -194,8 +215,8 @@ function _footnotes_replace_callback( $m
   //remove newlines. Browsers don't support them anyway and they'll confuse line break converter in filter.module
   $title = str_replace("\n", " ", $title);
   $title = str_replace("\r", "", $title);
-  return '<a class="see_footnote" id="footnoteref' . $n . '_' . $randstr .
-         '" title="' . $title . '" href="#footnote' . $n . '_' . $randstr . '">' . $n . '</a>';
+  return '<a class="see_footnote" id="footnoteref' . $label . '_' . $randstr .
+         '" title="' . $title . '" href="#footnote' . $label . '_' . $randstr . '">' . $label . '</a>';
 }
 
 
