diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.3.2.0
+=======
+
+  * Add `texts`
+
 0.3.1.0
 =======
 
diff --git a/src/Text/Xml/Lens.hs b/src/Text/Xml/Lens.hs
--- a/src/Text/Xml/Lens.hs
+++ b/src/Text/Xml/Lens.hs
@@ -1,7 +1,5 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE Rank2Types #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 -- | Optics for xml-conduit and html-conduit
@@ -35,6 +33,7 @@
   , attr
   , attributed
   , text
+  , texts
   , HasComments(..)
   , HasInstructions(..)
     -- * Name
@@ -61,6 +60,7 @@
   , module Text.Xml.Lens.LowLevel
   ) where
 
+import           Control.Applicative
 import           Control.Exception (SomeException)
 import           Control.Exception.Lens (exception)
 import           Control.Lens
@@ -71,7 +71,7 @@
 import           Text.XML
   ( ParseSettings, RenderSettings
   , Document(Document), Doctype, Prologue(Prologue)
-  , Node, Element, Instruction, Name, Miscellaneous(..)
+  , Node(..), Element, Instruction, Name, Miscellaneous(..)
   , XMLException(..), UnresolvedEntityException(..)
   , parseLBS, parseText, renderLBS, renderText, def
   )
@@ -79,7 +79,7 @@
 import           Text.XML.Unresolved (InvalidEventStream(..))
 import qualified Text.HTML.DOM as Html
 
-import Text.Xml.Lens.LowLevel
+import           Text.Xml.Lens.LowLevel
 
 -- $setup
 -- >>> :set -XOverloadedStrings
@@ -393,6 +393,21 @@
 text :: Traversal' Element Text
 text = elementNodes . traverse . _NodeContent
 {-# INLINE text #-}
+
+-- | Traverse node text contents recursively
+--
+-- >>> let doc = "<root>qux<foo>boo</foo><bar><baz>hoo</baz>quux</bar></root>" :: TL.Text
+--
+-- >>> doc ^.. xml.texts
+-- ["qux","boo","hoo","quux"]
+--
+-- >>> doc & xml.texts %~ Text.toUpper
+-- "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>QUX<foo>BOO</foo><bar><baz>HOO</baz>QUUX</bar></root>"
+texts :: Traversal' Element Text
+texts f = elementNodes (traverse go) where
+  go (NodeElement e) = NodeElement <$> texts f e
+  go (NodeContent c) = NodeContent <$> f c
+  go x = pure x
 
 -- | Anything that has comments
 class HasComments t where
diff --git a/xml-html-conduit-lens.cabal b/xml-html-conduit-lens.cabal
--- a/xml-html-conduit-lens.cabal
+++ b/xml-html-conduit-lens.cabal
@@ -1,5 +1,5 @@
 name:                xml-html-conduit-lens
-version:             0.3.1.0
+version:             0.3.2.0
 synopsis:            Optics for xml-conduit and html-conduit
 description:         Optics for xml-conduit and html-conduit
 homepage:            https://github.com/supki/xml-html-conduit-lens#readme
@@ -21,7 +21,7 @@
 
 source-repository this
   type: git
-  tag: 0.3.1.0
+  tag: 0.3.2.0
   location: https://github.com/supki/xml-html-conduit-lens
 
 library
