diff --git includes/common.inc includes/common.inc
index 5cea431..bf206ae 100644
--- includes/common.inc
+++ includes/common.inc
@@ -4346,15 +4346,12 @@ function drupal_common_theme() {
       'arguments' => array('form' => NULL),
     ),
     // from menu.inc
-    'menu_item_link' => array(
-      'arguments' => array('item' => NULL),
+    'menu_link' => array(
+      'arguments' => array('element' => NULL),
     ),
     'menu_tree' => array(
       'arguments' => array('tree' => NULL),
     ),
-    'menu_item' => array(
-      'arguments' => array('link' => NULL, 'has_children' => NULL, 'menu' => ''),
-    ),
     'menu_local_task' => array(
       'arguments' => array('link' => NULL, 'active' => FALSE),
     ),
diff --git includes/menu.inc includes/menu.inc
index 07c1a5f..f0b00b6 100644
--- includes/menu.inc
+++ includes/menu.inc
@@ -808,13 +808,13 @@ function menu_tree($menu_name) {
  * @param $tree
  *   A data structure representing the tree as returned from menu_tree_data.
  * @return
- *   The rendered HTML of that data structure.
+ *   A strcutured array to be rendered by drupal_render().
  */
 function menu_tree_output($tree) {
-  $output = '';
+  $content = array();
   $items = array();
 
-  // Pull out just the menu items we are going to render so that we
+  // Pull out just the menu links we are going to render so that we
   // get an accurate count for the first/last classes.
   foreach ($tree as $data) {
     if (!$data['link']['hidden']) {
@@ -824,23 +824,42 @@ function menu_tree_output($tree) {
 
   $num_items = count($items);
   foreach ($items as $i => $data) {
-    $extra_class = array();
+    $extra_classes = array();
     if ($i == 0) {
-      $extra_class[] = 'first';
+      $extra_classes[] = 'first';
     }
     if ($i == $num_items - 1) {
-      $extra_class[] = 'last';
+      $extra_classes[] = 'last';
     }
-    $extra_class = implode(' ', $extra_class);
-    $link = theme('menu_item_link', $data['link']);
+    // Set another classe based on whether the link has children.
     if ($data['below']) {
-      $output .= theme('menu_item', $link, $data['link']['has_children'], menu_tree_output($data['below']), $data['link']['in_active_trail'], $extra_class);
+      $extra_classes[] = 'expanded';
+    }
+    elseif ($data['link']['has_children']) {
+      $extra_classes[] = 'collapsed';
     }
     else {
-      $output .= theme('menu_item', $link, $data['link']['has_children'], '', $data['link']['in_active_trail'], $extra_class);
+      $extra_classes[] = 'leaf';
+    }
+    // Set a class if the link is in the active trail.
+    if ($data['link']['in_active_trail']) {
+      $extra_classes[] = 'active-trail';
     }
+
+    $element['#theme'] = 'menu_link';
+    $element['#attributes']['class'] = $extra_classes;
+    $element['#title'] = $data['link']['title'];
+    $element['#href'] = $data['link']['href'];
+    $element['#localized_options'] = !empty($data['localized_options']) ? $data['localized_options'] : array();
+    $element['#below'] = $data['below'] ? menu_tree_output($data['below']) : $data['below'];
+    $element['#original_link'] = $data['link'];
+    $content[] = $element;
+  }
+  if ($content) {
+    $content['#theme'] = 'menu_tree';
   }
-  return $output ? theme('menu_tree', $output) : '';
+
+  return $content;
 }
 
 /**
@@ -1253,29 +1272,20 @@ function _menu_tree_data(&$links, $parents, $depth) {
 }
 
 /**
- * Generate the HTML output for a single menu link.
- *
- * @ingroup themeable
- */
-function theme_menu_item_link($link) {
-  if (empty($link['localized_options'])) {
-    $link['localized_options'] = array();
-  }
-
-  return l($link['title'], $link['href'], $link['localized_options']);
-}
-
-/**
  * Generate the HTML output for a menu tree
  *
  * @ingroup themeable
  */
 function theme_menu_tree($tree) {
-  return '<ul class="menu">' . $tree . '</ul>';
+  $output = '<ul class="menu">';
+  foreach(element_children($tree) as $index) {
+    $output .= drupal_render($tree[$index]);
+  }
+  return $output. '</ul>';
 }
 
 /**
- * Generate the HTML output for a menu item and submenu.
+ * Generate the HTML output for a menu link and submenu.
  *
  * The menu item's LI element is given one of the following classes:
  * - expanded: The menu item is showing its submenu.
@@ -1284,29 +1294,18 @@ function theme_menu_tree($tree) {
  *
  * @ingroup themeable
  *
- * @param $link
- *   The fully-formatted link for this menu item.
- * @param $has_children
- *   Boolean value indicating if this menu item has children.
- * @param $menu
- *   Contains a fully-formatted submenu, if one exists for this menu item.
- *   Defaults to NULL.
- * @param $in_active_trail
- *   Boolean determining if the current page is below the menu item in the
- *   menu system. Defaults to FALSE.
- * @param $extra_class
- *   Extra classes that should be added to the class of the list item.
- *   Defaults to NULL.
+ * @param $element
+ *   The data for this menu link.
  */
-function theme_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
-  $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
-  if (!empty($extra_class)) {
-    $class .= ' ' . $extra_class;
-  }
-  if ($in_active_trail) {
-    $class .= ' active-trail';
+ function theme_menu_link(array $element) {
+  $output = '';
+  $sub_menu = '';
+
+  if ($element['#below']) {
+    $sub_menu = drupal_render($element['#below']);
   }
-  return '<li class="' . $class . '">' . $link . $menu . "</li>\n";
+  $link = l($element['#title'], $element['#href'], $element['#localized_options']);
+  return '<li ' . drupal_attributes($element['#attributes']) . '>' . $link . $sub_menu . "</li>\n";
 }
 
 /**
@@ -1531,13 +1530,13 @@ function menu_local_tasks($level = 0) {
           if ($item['type'] == MENU_DEFAULT_LOCAL_TASK) {
             // Find the first parent which is not a default local task or action.
             for ($p = $item['tab_parent']; $tasks[$p]['type'] == MENU_DEFAULT_LOCAL_TASK; $p = $tasks[$p]['tab_parent']);
-            $link = theme('menu_item_link', array('href' => $tasks[$p]['href']) + $item);
+            $link = l($item['title'], $tasks[$p]['href'], $item['localized_options']);
             $tabs_current .= theme('menu_local_task', $link, TRUE);
             $next_path = $item['path'];
             $tab_count++;
           }
           else {
-            $link = theme('menu_item_link', $item);
+            $link = l($item['title'], $item['href'], $item['localized_options']);
             if ($item['type'] == MENU_LOCAL_TASK) {
               $tabs_current .= theme('menu_local_task', $link);
               $tab_count++;
@@ -1576,13 +1575,13 @@ function menu_local_tasks($level = 0) {
           if ($item['type'] == MENU_DEFAULT_LOCAL_TASK) {
             // Find the first parent which is not a default local task.
             for ($p = $item['tab_parent']; $tasks[$p]['type'] == MENU_DEFAULT_LOCAL_TASK; $p = $tasks[$p]['tab_parent']);
-            $link = theme('menu_item_link', array('href' => $tasks[$p]['href']) + $item);
+            $link = l($item['title'], $tasks[$p]['href'], $item['localized_options']);
             if ($item['path'] == $router_item['path']) {
               $root_path = $tasks[$p]['path'];
             }
           }
           else {
-            $link = theme('menu_item_link', $item);
+            $link = l($item['title'], $item['href'], $item['localized_options']);
           }
           // We check for the active tab.
           if ($item['path'] == $path) {
diff --git modules/book/book-all-books-block.tpl.php modules/book/book-all-books-block.tpl.php
index 63a6926..7d49360 100644
--- modules/book/book-all-books-block.tpl.php
+++ modules/book/book-all-books-block.tpl.php
@@ -15,6 +15,6 @@
 ?>
 <?php foreach ($book_menus as $book_id => $menu) : ?>
 <div id="book-block-menu-<?php print $book_id; ?>" class="book-block-menu">
-  <?php print $menu; ?>
+  <?php print drupal_render($menu); ?>
 </div>
 <?php endforeach; ?>
diff --git modules/book/book.module modules/book/book.module
index 7d31ddc..3d83fa4 100644
--- modules/book/book.module
+++ modules/book/book.module
@@ -248,7 +248,8 @@ function book_block_view($delta = '') {
         $book_menus[$book_id] = menu_tree_output($pseudo_tree);
       }
     }
-    $block['content'] = theme('book_all_books_block', $book_menus);
+    $book_menus['#theme'] = 'book_all_books_block';
+    $block['content'] = $book_menus;
   }
   elseif ($current_bid) {
     // Only display this block when the user is browsing a book.
@@ -703,7 +704,7 @@ function book_children($book_link) {
     }
   }
 
-  return $children ? menu_tree_output($children) : '';
+  return $children ? drupal_render(menu_tree_output($children)) : '';
 }
 
 /**
@@ -890,6 +891,23 @@ function _book_link_defaults($nid) {
 }
 
 /**
+ * Process variables for book-all-books-block.tpl.php.
+ *
+ * The $variables array contains the following arguments:
+ * - $book_menus
+ *
+ * @see book-navigation.tpl.php
+ */
+function template_preprocess_book_all_books_block(&$variables) {
+  // Remove all non-renderable elements.
+  $elements = $variables['book_menus'];
+  $variables['book_menus'] = array();
+  foreach (element_children($elements) as $index) {
+    $variables['book_menus'][$index] = $elements[$index];
+  }
+}
+
+/**
  * Process variables for book-navigation.tpl.php.
  *
  * The $variables array contains the following arguments:
