diff --git a/src/Text/HTML/Basic/String.hs b/src/Text/HTML/Basic/String.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/HTML/Basic/String.hs
@@ -0,0 +1,17 @@
+module Text.HTML.Basic.String (Encoded, decode, ) where
+
+import Text.XML.Basic.String (Encoded, )
+import qualified Text.XML.Basic.String as XMLString
+import qualified Text.HTML.Basic.Character as HTMLChar
+import qualified Text.HTML.Basic.Entity as HTMLEnt
+import qualified Data.Char as Char
+
+{- |
+Invalid references are silently skipped.
+-}
+decode ::
+   (Encoded -> String) ->
+   [HTMLChar.T] ->
+   String
+decode =
+   XMLString.decodeGen HTMLEnt.mapNameToChar
diff --git a/src/Text/HTML/Basic/Tag.hs b/src/Text/HTML/Basic/Tag.hs
--- a/src/Text/HTML/Basic/Tag.hs
+++ b/src/Text/HTML/Basic/Tag.hs
@@ -6,22 +6,28 @@
 -}
 module Text.HTML.Basic.Tag (
    Tag.Name(..),
-   Tag.doctype, Tag.doctypeString,
-   Tag.cdata, Tag.cdataString,
+   Tag.doctype, Tag.doctypeName, Tag.doctypeString,
+   Tag.cdata,   Tag.cdataName,   Tag.cdataString,
    isEmpty, isSloppy, isInnerOf, closes,
+   maybeMetaHTTPHeader, maybeMetaEncoding,
    ) where
 
 
 import Text.XML.Basic.Tag (Name, )
 
 import qualified Text.XML.Basic.Tag as Tag
+import qualified Text.XML.Basic.Attribute as Attr
 import qualified Text.XML.Basic.Name as Name
 
 import qualified Data.Map as Map
 import qualified Data.Set as Set
-import Data.Tuple.HT (mapFst, )
 
+import qualified Data.Char as Char
+import           Data.List.HT (takeWhileRev, )
+import           Data.Tuple.HT (mapFst, )
+import           Control.Monad (guard, liftM2, )
 
+
 {- |
 Check whether a HTML tag is empty.
 -}
@@ -175,3 +181,30 @@
 thdrSet    = nameSet ["th","td","tr"]
 liSet      = nameSet ["li"]
 headingSet = nameSet ["h1","h2","h3","h4","h5","h6","p" {- not "div" -}]
+
+
+
+
+maybeMetaHTTPHeader ::
+   (Name.Tag name, Name.Attribute name) =>
+   Tag.Name name -> [Attr.T name string] -> Maybe (string, string)
+maybeMetaHTTPHeader name attrs =
+   do guard (Name.match "meta" name)
+      liftM2 (,)
+         (Attr.lookupLit "http-equiv" attrs)
+         (Attr.lookupLit "content" attrs)
+
+
+{- |
+A simple routine that does not check for valid syntax
+of the Content-Type specification.
+
+In future we might use a distinct @Encoding@ type instead of plain String.
+-}
+maybeMetaEncoding ::
+   (Name.Tag name, Name.Attribute name) =>
+   Tag.Name name -> [Attr.T name String] -> Maybe String
+maybeMetaEncoding name attrs =
+   do (headerName, content) <- maybeMetaHTTPHeader name attrs
+      guard (("content-type"==) . map Char.toLower $ headerName)
+      return (map Char.toLower . takeWhileRev ('='/=) $ content)
diff --git a/src/Text/XML/Basic/Attribute.hs b/src/Text/XML/Basic/Attribute.hs
--- a/src/Text/XML/Basic/Attribute.hs
+++ b/src/Text/XML/Basic/Attribute.hs
@@ -93,6 +93,20 @@
    toString = Name.attributeToString . unname
 
 
+versionName :: (Name.Attribute name) => Name name
+versionName = Name.fromString versionString
+
+encodingName :: (Name.Attribute name) => Name name
+encodingName = Name.fromString encodingString
+
+
+versionString :: String
+versionString = "version"
+
+encodingString :: String
+encodingString = "encoding"
+
+
 -- * attribute lists
 
 mapValues ::
diff --git a/src/Text/XML/Basic/Name.hs b/src/Text/XML/Basic/Name.hs
--- a/src/Text/XML/Basic/Name.hs
+++ b/src/Text/XML/Basic/Name.hs
@@ -2,7 +2,6 @@
 We provide a type class for tag and attribute names.
 Instances can be names that preserve case,
 names with lowercase letters as canonical representation.
-To do: Qualified names.
 -}
 module Text.XML.Basic.Name where
 
diff --git a/src/Text/XML/Basic/String.hs b/src/Text/XML/Basic/String.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/XML/Basic/String.hs
@@ -0,0 +1,46 @@
+module Text.XML.Basic.String where
+
+import qualified Text.XML.Basic.Character as XMLChar
+import qualified Text.XML.Basic.Entity as XMLEnt
+import qualified Data.Map as Map
+import qualified Data.Char as Char
+
+
+-- | should be [Word8]
+type Encoded  = String
+
+{- |
+Decode encoded characters and XML references.
+Invalid references are silently skipped.
+-}
+decode ::
+   (Encoded -> String) ->
+   [XMLChar.T] ->
+   String
+decode =
+   decodeGen XMLEnt.mapNameToChar
+
+decodeGen ::
+   Map.Map XMLEnt.Name Char ->
+   (Encoded -> String) ->
+   [XMLChar.T] ->
+   String
+decodeGen mapNameToChar decoder =
+   foldr ($) [] .
+   XMLChar.switchUnicodeRuns
+      ((++) . decoder)
+      (\n ->
+         if XMLChar.validCharRef n
+           then (Char.chr n :)
+           else id)
+      (\n ->
+         maybe id (:) $
+         Map.lookup n mapNameToChar)
+
+
+{-
+type Reference = Either Int String
+
+data T = Cons String Reference R
+data R = R Reference R | S T
+-}
diff --git a/src/Text/XML/Basic/Tag.hs b/src/Text/XML/Basic/Tag.hs
--- a/src/Text/XML/Basic/Tag.hs
+++ b/src/Text/XML/Basic/Tag.hs
@@ -6,11 +6,16 @@
 -}
 module Text.XML.Basic.Tag (
    Name(..),
-   doctype, doctypeString,
-   cdata, cdataString,
+   doctype, doctypeName, doctypeString,
+   cdata, cdataName, cdataString,
+   xmlName, xmlString,
+   maybeXMLEncoding,
    ) where
 
-import Text.XML.Basic.Name as Name
+import qualified Text.XML.Basic.Name as Name
+import qualified Text.XML.Basic.ProcessingInstruction as PI
+import qualified Text.XML.Basic.Attribute as Attr
+import Control.Monad (guard, )
 
 
 newtype Name ident = Name {unname :: ident}
@@ -26,15 +31,39 @@
 
 
 
+{-# DEPRECATED doctype "use doctypeName instead" #-}
 doctype :: (Name.Tag name) => Name name
-doctype = Name.fromString doctypeString
+doctype = doctypeName
 
+{-# DEPRECATED cdata "use cdataName instead" #-}
 cdata :: (Name.Tag name) => Name name
-cdata = Name.fromString cdataString
+cdata = cdataName
 
 
+doctypeName :: (Name.Tag name) => Name name
+doctypeName = Name.fromString doctypeString
+
+cdataName :: (Name.Tag name) => Name name
+cdataName = Name.fromString cdataString
+
+xmlName :: (Name.Tag name) => Name name
+xmlName = Name.fromString xmlString
+
+
 doctypeString :: String
 doctypeString = "DOCTYPE"
 
 cdataString :: String
 cdataString = "[CDATA["
+
+xmlString :: String
+xmlString = "xml"
+
+
+maybeXMLEncoding ::
+   (Name.Tag name, Name.Attribute name) =>
+   Name name -> PI.T name string -> Maybe string
+maybeXMLEncoding name instr =
+   do guard (xmlName == name)
+      let (PI.Known attrs) = instr
+      Attr.lookup Attr.encodingName attrs
diff --git a/xml-basic.cabal b/xml-basic.cabal
--- a/xml-basic.cabal
+++ b/xml-basic.cabal
@@ -1,5 +1,5 @@
 Name:             xml-basic
-Version:          0.1
+Version:          0.1.1
 License:          BSD3
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
@@ -25,7 +25,7 @@
 Source-Repository this
   type:     darcs
   location: http://code.haskell.org/~thielema/xml-basic/
-  tag:      0.1
+  tag:      0.1.1
 
 Flag splitBase
   description: Choose the new smaller, split-up base package.
@@ -36,14 +36,19 @@
     data-accessor >=0.2 && <0.3,
     utility-ht >=0.0.4 && <0.1
   If flag(splitBase)
-    Build-Depends: base >= 2, containers >=0.1 && <0.3
+    Build-Depends:
+      containers >=0.1 && <0.3,
+      base >= 2 && <5
   Else
-    Build-Depends: base >= 1.0 && < 2, special-functors >=1.0 && <1.1
+    Build-Depends:
+      special-functors >=1.0 && <1.1,
+      base >= 1.0 && < 2
 
   GHC-Options:      -Wall
   Hs-Source-Dirs:   src
   Exposed-Modules:
     Text.HTML.Basic.Tag
+    Text.HTML.Basic.String
     Text.HTML.Basic.Character
     Text.HTML.Basic.Entity
     Text.XML.Basic.Tag
@@ -54,6 +59,7 @@
     Text.XML.Basic.Name.LowerCase
     Text.XML.Basic.Name.Qualified
     Text.XML.Basic.Position
+    Text.XML.Basic.String
     Text.XML.Basic.Character
     Text.XML.Basic.Entity
     Text.XML.Basic.Format
