diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,8 @@
+## 1.25.10 (2022-09-12)
+- allow empty text content (@TeofilC, #10)
+- allow building with GHC 9.4 (@andreasabel, #9)
+- better pretty printer formatting (@avieth, #8)
+
 ## 1.25.9 (2022-04-10)
 - fix 1.25.7 regression in Xtract.Parse (#7 by Isaac van Bakel)
 - comment typo fixes (#6 by Eric Lindblad)
diff --git a/HaXml.cabal b/HaXml.cabal
--- a/HaXml.cabal
+++ b/HaXml.cabal
@@ -1,6 +1,6 @@
 cabal-version:  1.18
 name:           HaXml
-version:        1.25.9
+version:        1.25.10
 
 license:        LGPL-2.1
 license-files:  COPYRIGHT, LICENCE-GPL, LICENCE-LGPL
@@ -17,8 +17,9 @@
 extra-doc-files: Changelog.md README
 
 tested-with:
-  GHC ==9.2.1
-   || ==9.0.1
+  GHC ==9.4.1
+   || ==9.2.4
+   || ==9.0.2
    || ==8.10.7
    || ==8.8.4
    || ==8.6.5
@@ -86,7 +87,7 @@
         Text.XML.HaXml.Schema.Schema
   hs-source-dirs: src
   build-depends:
-    base       >= 4.3.1.0  && < 4.17,
+    base       >= 4.3.1.0  && < 4.18,
     bytestring >= 0.9.1.10 && < 0.12,
     containers >= 0.4.0.0  && <0.7,
     filepath   >= 1.2.0.0  && <1.5,
diff --git a/src/Text/XML/HaXml/ByteStringPP.hs b/src/Text/XML/HaXml/ByteStringPP.hs
--- a/src/Text/XML/HaXml/ByteStringPP.hs
+++ b/src/Text/XML/HaXml/ByteStringPP.hs
@@ -140,12 +140,17 @@
 --  | any isText cs    = text "<" <> text n <+> fsep (map attribute as) <>
 --                       text ">" <> hcat (map content cs) <>
 --                       text "</" <> qname n <> text ">"
-    | isText (head cs) = text "<" <> qname n <+> fsep (Prelude.map attribute as) <>
+    | isText (head cs) = text "<" <> qname n <> attributes as <>
                          text ">" <> hcat (Prelude.map content cs) <>
                          text "</" <> qname n <> text ">"
-    | otherwise        = let (d,c) = carryelem e empty
-                         in d <> c
+    | otherwise        = vcat [ text "<" <> qname n <> attributes as <> text ">"
+                              , nest 2 (vcat (Prelude.map content cs))
+                              , text "</" <> qname n <> text ">"
+                              ]
 
+attributes [] = empty
+attributes as@(_:_) = text " " <> fsep (Prelude.map attribute as)
+
 isText :: Content t -> Bool
 isText (CString _ _ _) = True
 isText (CRef _ _)      = True
@@ -158,10 +163,11 @@
                          , text "/>")
 carryelem (Elem n as cs) c
 {-  | any isText cs    =  ( c <> element e, empty)
-    | otherwise -}     =  let (cs0,d0) = carryscan carrycontent cs (text ">")
+    | otherwise -}     =  let (cs0,d0) = carryscan carrycontent cs empty
                           in
                           ( c <>
-                            text "<" <> qname n <+> fsep (Prelude.map attribute as) $$
+                            text "<" <> qname n <+> fsep (Prelude.map attribute as) <> text ">" $$
+                            -- This is wrong. It includes the close tag of the previous one
                             nest 2 (vcat cs0) <> --- $$
                             d0 <> text "</" <> qname n
                           , text ">")
diff --git a/src/Text/XML/HaXml/Pretty.hs b/src/Text/XML/HaXml/Pretty.hs
--- a/src/Text/XML/HaXml/Pretty.hs
+++ b/src/Text/XML/HaXml/Pretty.hs
@@ -103,8 +103,13 @@
     | all isText cs    = text "<" <> qname n <+> fsep (map attribute as) <>
                          text ">" <> hcat (map content cs) <>
                          text "</" <> qname n <> text ">"
-    | otherwise        = let (d,c) = carryelem e empty
-                         in d <> c
+    | otherwise        = vcat [ text "<" <> qname n <> attributes as <> text ">"
+                              , nest 2 $ vcat (map content cs)
+                              , text "</" <> qname n <> text ">"
+                              ]
+
+attributes [] = empty
+attributes as@(_:_) = text " " <> fsep (map attribute as)
 
 isText :: Content t -> Bool
 isText (CString _ _ _) = True
diff --git a/src/Text/XML/HaXml/XmlContent/Parser.hs b/src/Text/XML/HaXml/XmlContent/Parser.hs
--- a/src/Text/XML/HaXml/XmlContent/Parser.hs
+++ b/src/Text/XML/HaXml/XmlContent/Parser.hs
@@ -224,12 +224,10 @@
                  CRef (RefEntity s) _ -> text' (('&':s++";"):acc)
                  CMisc _ _            -> text' acc
                  CElem _ _         -> do { reparse [c] -- put it back!
-                                         ; if null acc then fail "empty string"
-                                           else return (concat (reverse acc))
+                                         ; return (concat (reverse acc))
                                          }
              }
-          `onFail` ( if null acc then fail "empty string"
-                     else return (concat (reverse acc)) )
+          `onFail` return (concat (reverse acc))
 
 
 -- | 'choice f p' means if parseContents succeeds, apply f to the result,
