diff --git a/heist.cabal b/heist.cabal
--- a/heist.cabal
+++ b/heist.cabal
@@ -1,5 +1,5 @@
 name:           heist
-version:        0.10.0
+version:        0.10.1
 synopsis:       An Haskell template system supporting both HTML5 and XML.
 description:
     Heist is a powerful template system that supports both HTML5 and XML.
diff --git a/src/Heist/Compiled.hs b/src/Heist/Compiled.hs
--- a/src/Heist/Compiled.hs
+++ b/src/Heist/Compiled.hs
@@ -48,6 +48,7 @@
   , runNodeList
   , runNode
   , compileNode
+  , runAttributes
   , runSplice
 
   ) where
diff --git a/src/Heist/Compiled/Internal.hs b/src/Heist/Compiled/Internal.hs
--- a/src/Heist/Compiled/Internal.hs
+++ b/src/Heist/Compiled/Internal.hs
@@ -413,7 +413,7 @@
     -- If the tag is not a splice, but it contains dynamic children
     compileStaticElement = do
         -- Parse the attributes: we have Left for static and Right for runtime
-        compiledAttrs <- mapM parseAtt attrs
+        compiledAttrs <- runAttributes attrs
 
         childHtml <- runNodeList ch
 
@@ -429,6 +429,14 @@
                          , DL.singleton $! pureTextChunk $! end
                          ]
 compileNode _ = error "impossible"
+
+
+------------------------------------------------------------------------------
+-- | Performs splice processing on a list of attributes.  This is useful in
+-- situations where you need to stop recursion, but still run splice
+-- processing on the node's attributes.
+runAttributes :: Monad n => [(Text, Text)] -> HeistT n IO [DList (Chunk n)]
+runAttributes = mapM parseAtt
 
 
 attrToChunk :: Text -> DList (Chunk n) -> DList (Chunk n)
diff --git a/src/Heist/Interpreted.hs b/src/Heist/Interpreted.hs
--- a/src/Heist/Interpreted.hs
+++ b/src/Heist/Interpreted.hs
@@ -65,6 +65,7 @@
   -- * HeistT functions
   , stopRecursion
   , runNode
+  , runAttributes
   , runNodeList
   , evalTemplate
   , bindStrings
diff --git a/src/Heist/Interpreted/Internal.hs b/src/Heist/Interpreted/Internal.hs
--- a/src/Heist/Interpreted/Internal.hs
+++ b/src/Heist/Interpreted/Internal.hs
@@ -177,7 +177,7 @@
 -- | Performs splice processing on a single node.
 runNode :: Monad n => X.Node -> Splice n
 runNode (X.Element nm at ch) = do
-    newAtts <- (return . concat) =<< mapM runAttrSplice at
+    newAtts <- runAttributes at
     let n = X.Element nm newAtts ch
     s <- liftM (lookupSplice nm) getHS
     maybe (runKids newAtts) (recurseSplice n) s
@@ -189,6 +189,14 @@
 
 
 ------------------------------------------------------------------------------
+-- | Performs splice processing on a list of attributes.  This is useful in
+-- situations where you need to stop recursion, but still run splice
+-- processing on the node's attributes.
+runAttributes :: Monad n => [(Text, Text)] -> HeistT n n [(Text, Text)]
+runAttributes attrs = (return . concat) =<< mapM runAttrSplice attrs
+
+
+------------------------------------------------------------------------------
 -- | Runs the attribute splice if it exists, otherwise it does inline $()
 -- substitution.
 runAttrSplice :: (Monad n) => (Text, Text) -> HeistT n n [(Text, Text)]
@@ -226,6 +234,9 @@
     renderEscaped c = do
         hs <- getHS
         if _preprocessingMode hs
+          -- Load time splices can't be descructive, therefore we need to
+          -- output the slashes so we don't change anything before later
+          -- splice processing.
           then return $ T.snoc "\\" c
           else return $ T.singleton c
 
@@ -288,7 +299,8 @@
                        restoreHS hs
                        return res
                else return result `orError` err
-        else return result
+        else do modifyHS (\st -> st { _recurse = True })
+                return result
   where
     err = unwords
         ["Recursion limit reached in node"
diff --git a/test/suite/Heist/Tutorial/CompiledSplices.lhs b/test/suite/Heist/Tutorial/CompiledSplices.lhs
--- a/test/suite/Heist/Tutorial/CompiledSplices.lhs
+++ b/test/suite/Heist/Tutorial/CompiledSplices.lhs
@@ -193,19 +193,19 @@
 
 This composability turns out to be a very powerful feature.  Head merging is
 one feature that can't be done without it.  Head merging allows you to put
-<head> tags anyhere in any template and have them all merged into a single
-<head> tag at the top of your HTML document.  This is useful because it allows
+`<head>` tags anyhere in any template and have them all merged into a single
+`<head>` tag at the top of your HTML document.  This is useful because it allows
 you to keep concerns localized.  For instance, you can have a template
 represent a small piece of functionality that uses a less common javascript or
 CSS file.  Instead of having to depend on that resource being included in the
-top-level <head> tag, you can include it in a <head> tag right where you're
+top-level `<head>` tag, you can include it in a `<head>` tag right where you're
 using it.  Then it will only be included on your pages when you are using the
 markup that needs it.
 
-Our implementation of head merging uses a splice bound to the <html> tag.
-This splice removes all the <head> nodes from its children, combines them, and
-inserts them as its first child.  This won't work unless the <html> splice
-first runs all its children to make sure all <apply> and <bind> tags have
+Our implementation of head merging uses a splice bound to the `<html>` tag.
+This splice removes all the `<head>` nodes from its children, combines them, and
+inserts them as its first child.  This won't work unless the `<html>` splice
+first runs all its children to make sure all `<apply>` and `<bind>` tags have
 happened first.  And that is impossible to do with compiled splices.
 
 To get around this problem we added the concept of load time splices.  Load
