From e897aa91a2a5c68a2f795f6a0a995600f13a85f8 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 14 May 2014 21:29:29 -0700 Subject: Convert to extension-less headers for API --- configure.ac | 2 +- doc/intro.xhtml | 8 +- examples/hybrid/dom.cxx | 4 +- examples/hybrid/dom.hxx | 4 +- examples/hybrid/driver.cxx | 4 +- examples/hybrid/makefile | 2 +- examples/inheritance/driver.cxx | 4 +- examples/inheritance/position.cxx | 4 +- examples/inheritance/position.hxx | 2 +- examples/performance/driver.cxx | 2 +- examples/persistence/driver.cxx | 4 +- examples/persistence/position.cxx | 4 +- examples/persistence/position.hxx | 2 +- examples/processing/driver.cxx | 6 +- examples/roundtrip/driver.cxx | 4 +- examples/template/Makefile.am | 6 + tests/parser/driver.cxx | 2 +- tests/roundtrip/driver.cxx | 4 +- tests/serializer/driver.cxx | 2 +- tests/template/Makefile.am | 6 + xml/Makefile.am | 7 + xml/content | 35 +++ xml/content.hxx | 35 --- xml/exception | 21 ++ xml/exception.hxx | 21 -- xml/forward | 19 ++ xml/forward.hxx | 19 -- xml/makefile | 9 +- xml/parser | 473 ++++++++++++++++++++++++++++++++++++++ xml/parser.cxx | 2 +- xml/parser.hxx | 473 -------------------------------------- xml/parser.ixx | 2 +- xml/parser.txx | 2 +- xml/qname | 87 +++++++ xml/qname.cxx | 2 +- xml/qname.hxx | 87 ------- xml/serializer | 227 ++++++++++++++++++ xml/serializer.cxx | 2 +- xml/serializer.hxx | 227 ------------------ xml/serializer.ixx | 2 +- xml/value-traits | 53 +++++ xml/value-traits.cxx | 2 +- xml/value-traits.hxx | 53 ----- xml/value-traits.txx | 4 +- 44 files changed, 984 insertions(+), 956 deletions(-) create mode 100644 xml/content delete mode 100644 xml/content.hxx create mode 100644 xml/exception delete mode 100644 xml/exception.hxx create mode 100644 xml/forward delete mode 100644 xml/forward.hxx create mode 100644 xml/parser delete mode 100644 xml/parser.hxx create mode 100644 xml/qname delete mode 100644 xml/qname.hxx create mode 100644 xml/serializer delete mode 100644 xml/serializer.hxx create mode 100644 xml/value-traits delete mode 100644 xml/value-traits.hxx diff --git a/configure.ac b/configure.ac index 8a81bde..9354db9 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ AC_PREREQ(2.60) AC_INIT([libstudxml], [__value__(version)], [studxml-users@codesynthesis.com]) AC_CONFIG_AUX_DIR([config]) AC_CONFIG_MACRO_DIR([m4]) -AC_CONFIG_SRCDIR([xml/exception.hxx]) +AC_CONFIG_SRCDIR([xml/exception]) AM_INIT_AUTOMAKE([-Wall -Werror foreign nostdinc subdir-objects dist-bzip2 dist-zip tar-ustar]) m4_equote()[m4_ifdef]m4_dquote()([AM_PROG_AR], [AM_PROG_AR]) # Required by automake 1.12. diff --git a/doc/intro.xhtml b/doc/intro.xhtml index 46eb03a..ea0b8c9 100644 --- a/doc/intro.xhtml +++ b/doc/intro.xhtml @@ -278,7 +278,7 @@ and US-ASCII input encodings.

-#include <xml/parser.hxx>
+#include <xml/parser>
 
 namespace xml
 {
@@ -287,7 +287,7 @@ namespace xml
   
-#include <xml/serializer.hxx>
+#include <xml/serializer>
 
 namespace xml
 {
@@ -595,7 +595,7 @@ for (parser::event_type e: p)
      class to represent such names:

-#include <xml/qname.hxx>
+#include <xml/qname>
 
 namespace xml
 {
@@ -993,6 +993,8 @@ cerr << p.next () << endl;
      the table:

+#include <xml/content>
+
 namespace xml
 {
   enum class content
diff --git a/examples/hybrid/dom.cxx b/examples/hybrid/dom.cxx
index cd1e0e0..c2ae6fd 100644
--- a/examples/hybrid/dom.cxx
+++ b/examples/hybrid/dom.cxx
@@ -1,8 +1,8 @@
 // file      : examples/hybrid/dom.cxx
 // copyright : not copyrighted - public domain
 
-#include 
-#include 
+#include 
+#include 
 
 #include "dom.hxx"
 
diff --git a/examples/hybrid/dom.hxx b/examples/hybrid/dom.hxx
index 3e1f8e3..4d99feb 100644
--- a/examples/hybrid/dom.hxx
+++ b/examples/hybrid/dom.hxx
@@ -8,8 +8,8 @@
 #include 
 #include 
 
-#include 
-#include 
+#include 
+#include 
 
 // A simple, DOM-like in-memory representation of raw XML. It only supports
 // empty, simple, and complex content (no mixed content) and is not
diff --git a/examples/hybrid/driver.cxx b/examples/hybrid/driver.cxx
index ca7421a..c1f5a0e 100644
--- a/examples/hybrid/driver.cxx
+++ b/examples/hybrid/driver.cxx
@@ -4,8 +4,8 @@
 #include 
 #include 
 
-#include 
-#include 
+#include 
+#include 
 
 #include "dom.hxx"
 
diff --git a/examples/hybrid/makefile b/examples/hybrid/makefile
index 8e4a4f8..fe9439b 100644
--- a/examples/hybrid/makefile
+++ b/examples/hybrid/makefile
@@ -32,7 +32,7 @@ $(out_base)/: $(driver)
 #
 $(dist): name := $(subst $(src_root)/examples/,,$(src_base))
 $(dist): sources := $(cxx_tun)
-$(dist): extras := README dom.xml
+$(dist): extras := README position.xml
 $(dist): export extra_sources := $(filter-out driver.cxx,$(cxx_tun))
 $(dist): export extra_headers := dom.hxx
 $(dist): export extra_dist := $(extras) $(name)-vc9.vcproj \
diff --git a/examples/inheritance/driver.cxx b/examples/inheritance/driver.cxx
index d6cd5ea..c07a0ea 100644
--- a/examples/inheritance/driver.cxx
+++ b/examples/inheritance/driver.cxx
@@ -4,8 +4,8 @@
 #include 
 #include 
 
-#include 
-#include 
+#include 
+#include 
 
 #include "position.hxx"
 
diff --git a/examples/inheritance/position.cxx b/examples/inheritance/position.cxx
index 9dde29e..1123efa 100644
--- a/examples/inheritance/position.cxx
+++ b/examples/inheritance/position.cxx
@@ -3,8 +3,8 @@
 
 #include 
 
-#include 
-#include 
+#include 
+#include 
 
 #include "position.hxx"
 
diff --git a/examples/inheritance/position.hxx b/examples/inheritance/position.hxx
index d86995d..d6f3a3f 100644
--- a/examples/inheritance/position.hxx
+++ b/examples/inheritance/position.hxx
@@ -8,7 +8,7 @@
 #include 
 #include 
 
-#include  // xml::{parser,serializer} forward declarations.
+#include  // xml::{parser,serializer} forward declarations.
 
 class position
 {
diff --git a/examples/performance/driver.cxx b/examples/performance/driver.cxx
index 7d096d6..403e821 100644
--- a/examples/performance/driver.cxx
+++ b/examples/performance/driver.cxx
@@ -5,7 +5,7 @@
 #include 
 #include 
 
-#include 
+#include 
 
 #include "time.hxx"
 
diff --git a/examples/persistence/driver.cxx b/examples/persistence/driver.cxx
index d62dd3b..8792716 100644
--- a/examples/persistence/driver.cxx
+++ b/examples/persistence/driver.cxx
@@ -4,8 +4,8 @@
 #include 
 #include 
 
-#include 
-#include 
+#include 
+#include 
 
 #include "position.hxx"
 
diff --git a/examples/persistence/position.cxx b/examples/persistence/position.cxx
index 9f4f701..a0430b4 100644
--- a/examples/persistence/position.cxx
+++ b/examples/persistence/position.cxx
@@ -3,8 +3,8 @@
 
 #include 
 
-#include 
-#include 
+#include 
+#include 
 
 #include "position.hxx"
 
diff --git a/examples/persistence/position.hxx b/examples/persistence/position.hxx
index 26b04f5..fb8c897 100644
--- a/examples/persistence/position.hxx
+++ b/examples/persistence/position.hxx
@@ -8,7 +8,7 @@
 #include 
 #include 
 
-#include  // xml::{parser,serializer} forward declarations.
+#include  // xml::{parser,serializer} forward declarations.
 
 enum object_type {building, mountain};
 
diff --git a/examples/processing/driver.cxx b/examples/processing/driver.cxx
index 97669c5..18950b2 100644
--- a/examples/processing/driver.cxx
+++ b/examples/processing/driver.cxx
@@ -5,9 +5,9 @@
 #include 
 #include 
 
-#include 
-#include 
-#include 
+#include 
+#include 
+#include 
 
 using namespace std;
 using namespace xml;
diff --git a/examples/roundtrip/driver.cxx b/examples/roundtrip/driver.cxx
index b83988b..9b8d512 100644
--- a/examples/roundtrip/driver.cxx
+++ b/examples/roundtrip/driver.cxx
@@ -5,8 +5,8 @@
 #include 
 #include 
 
-#include 
-#include 
+#include 
+#include 
 
 using namespace std;
 using namespace xml;
diff --git a/examples/template/Makefile.am b/examples/template/Makefile.am
index 64e4d1f..37d9509 100644
--- a/examples/template/Makefile.am
+++ b/examples/template/Makefile.am
@@ -11,3 +11,9 @@ AM_CPPFLAGS = -I'$(top_builddir)' -I'$(top_srcdir)'
 
 TESTS=$(top_builddir)/tester
 TESTS_ENVIRONMENT=example=1; export example;
+
+# Make sure make doesn't try to build the no-extension headers
+# thinking that they are executable. Those are pulled in through
+# auto-generated dependencies.
+#
+__foreach_w__(__f,__path__(xml_headers),$(top_srcdir)/xml/__f ): ; @:
diff --git a/tests/parser/driver.cxx b/tests/parser/driver.cxx
index 2afe522..4e0fbae 100644
--- a/tests/parser/driver.cxx
+++ b/tests/parser/driver.cxx
@@ -12,7 +12,7 @@
 #include 
 #include 
 
-#include 
+#include 
 
 using namespace std;
 using namespace xml;
diff --git a/tests/roundtrip/driver.cxx b/tests/roundtrip/driver.cxx
index 48c96b4..e7a07f8 100644
--- a/tests/roundtrip/driver.cxx
+++ b/tests/roundtrip/driver.cxx
@@ -7,8 +7,8 @@
 #include 
 #include 
 
-#include 
-#include 
+#include 
+#include 
 
 using namespace std;
 using namespace xml;
diff --git a/tests/serializer/driver.cxx b/tests/serializer/driver.cxx
index 0f22107..796a384 100644
--- a/tests/serializer/driver.cxx
+++ b/tests/serializer/driver.cxx
@@ -11,7 +11,7 @@
 #include 
 #include 
 
-#include 
+#include 
 
 using namespace std;
 using namespace xml;
diff --git a/tests/template/Makefile.am b/tests/template/Makefile.am
index 9d198f1..d8b5b50 100644
--- a/tests/template/Makefile.am
+++ b/tests/template/Makefile.am
@@ -13,3 +13,9 @@ TESTS=$(top_builddir)/tester
 TESTS_ENVIRONMENT=example=; export example;
 
 CLEANFILES = test.out
+
+# Make sure make doesn't try to build the no-extension headers
+# thinking that they are executable. Those are pulled in through
+# auto-generated dependencies.
+#
+__foreach_w__(__f,__path__(xml_headers),$(top_srcdir)/xml/__f ): ; @:
diff --git a/xml/Makefile.am b/xml/Makefile.am
index ebe357e..46be59f 100644
--- a/xml/Makefile.am
+++ b/xml/Makefile.am
@@ -20,5 +20,12 @@ endif
 libstudxml_la_SOURCES += __path__(genx_sources)
 nobase_studxmlinclude_HEADERS += __path__(genx_headers)
 
+nobase_studxmlinclude_HEADERS += __path__(xml_headers)
+
+# Make sure make doesn't try to build the no-extension headers
+# thinking that they are executable.
+#
+__foreach_w__(__f,__path__(xml_headers),__f $(top_srcdir)/xml/__f ): ; @:
+
 AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -DLIBSTUDXML_DYNAMIC_LIB
 AM_LDFLAGS = -release __value__(interface_version) -no-undefined
diff --git a/xml/content b/xml/content
new file mode 100644
index 0000000..e37607f
--- /dev/null
+++ b/xml/content
@@ -0,0 +1,35 @@
+// file      : xml/content -*- C++ -*-
+// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
+// license   : MIT; see accompanying LICENSE file
+
+#ifndef XML_CONTENT
+#define XML_CONTENT
+
+#include 
+
+namespace xml
+{
+  // XML content model. C++11 enum class emulated for C++98.
+  //
+  struct content
+  {
+    enum value
+    {
+               //  element   characters  whitespaces        notes
+      empty,   //    no          no        ignored
+      simple,  //    no          yes       preserved   content accumulated
+      complex, //    yes         no        ignored
+      mixed    //    yes         yes       preserved
+    };
+
+    content (value v): v_ (v) {};
+    operator value () const {return v_;}
+
+  private:
+    value v_;
+  };
+}
+
+#include 
+
+#endif // XML_CONTENT
diff --git a/xml/content.hxx b/xml/content.hxx
deleted file mode 100644
index 575ef1d..0000000
--- a/xml/content.hxx
+++ /dev/null
@@ -1,35 +0,0 @@
-// file      : xml/content.hxx
-// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
-// license   : MIT; see accompanying LICENSE file
-
-#ifndef XML_CONTENT_HXX
-#define XML_CONTENT_HXX
-
-#include 
-
-namespace xml
-{
-  // XML content model. C++11 enum class emulated for C++98.
-  //
-  struct content
-  {
-    enum value
-    {
-               //  element   characters  whitespaces        notes
-      empty,   //    no          no        ignored
-      simple,  //    no          yes       preserved   content accumulated
-      complex, //    yes         no        ignored
-      mixed    //    yes         yes       preserved
-    };
-
-    content (value v): v_ (v) {};
-    operator value () const {return v_;}
-
-  private:
-    value v_;
-  };
-}
-
-#include 
-
-#endif // XML_CONTENT_HXX
diff --git a/xml/exception b/xml/exception
new file mode 100644
index 0000000..1fe1eb2
--- /dev/null
+++ b/xml/exception
@@ -0,0 +1,21 @@
+// file      : xml/exception -*- C++ -*-
+// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
+// license   : MIT; see accompanying LICENSE file
+
+#ifndef XML_EXCEPTION
+#define XML_EXCEPTION
+
+#include 
+
+#include 
+
+#include 
+
+namespace xml
+{
+  struct LIBSTUDXML_EXPORT exception: std::exception {};
+}
+
+#include 
+
+#endif // XML_EXCEPTION
diff --git a/xml/exception.hxx b/xml/exception.hxx
deleted file mode 100644
index c9895bb..0000000
--- a/xml/exception.hxx
+++ /dev/null
@@ -1,21 +0,0 @@
-// file      : xml/exception.hxx
-// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
-// license   : MIT; see accompanying LICENSE file
-
-#ifndef XML_EXCEPTION_HXX
-#define XML_EXCEPTION_HXX
-
-#include 
-
-#include 
-
-#include 
-
-namespace xml
-{
-  struct LIBSTUDXML_EXPORT exception: std::exception {};
-}
-
-#include 
-
-#endif // XML_EXCEPTION_HXX
diff --git a/xml/forward b/xml/forward
new file mode 100644
index 0000000..8d474c7
--- /dev/null
+++ b/xml/forward
@@ -0,0 +1,19 @@
+// file      : xml/forward -*- C++ -*-
+// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
+// license   : MIT; see accompanying LICENSE file
+
+#ifndef XML_FORWARD
+#define XML_FORWARD
+
+#include 
+
+namespace xml
+{
+  class qname;
+  class parser;
+  class serializer;
+}
+
+#include 
+
+#endif // XML_FORWARD
diff --git a/xml/forward.hxx b/xml/forward.hxx
deleted file mode 100644
index bacd5f5..0000000
--- a/xml/forward.hxx
+++ /dev/null
@@ -1,19 +0,0 @@
-// file      : xml/forward.hxx
-// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
-// license   : MIT; see accompanying LICENSE file
-
-#ifndef XML_FORWARD_HXX
-#define XML_FORWARD_HXX
-
-#include 
-
-namespace xml
-{
-  class qname;
-  class parser;
-  class serializer;
-}
-
-#include 
-
-#endif // XML_FORWARD_HXX
diff --git a/xml/makefile b/xml/makefile
index 6c8f3b9..52203aa 100644
--- a/xml/makefile
+++ b/xml/makefile
@@ -5,6 +5,7 @@
 include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
 
 sources := qname.cxx parser.cxx serializer.cxx value-traits.cxx
+xml_headers := content exception forward qname parser serializer value-traits
 
 # Expat.
 #
@@ -72,6 +73,12 @@ $(out_base)/: $(studxml.l)
 
 # Dist.
 #
+
+# Set it for the out_root so that it is visible in examples/tests. See
+# Makefile.am for why we need it there.
+#
+$(our_root)/%.dist: export xml_headers := $(xml_headers) 
+
 $(dist): export sources := $(sources)
 $(dist): export expat_sources := $(expat_sources)
 $(dist): export expat_headers := $(expat_headers)
@@ -89,7 +96,7 @@ $(dist): export interface_version = $(shell sed -e \
 
 $(dist):
 	$(call dist-data,$(sources) $(expat_sources) $(genx_sources))
-	$(call dist-data,$(headers) $(expat_headers) $(genx_headers))
+	$(call dist-data,$(headers) $(xml_headers) $(expat_headers) $(genx_headers))
 	$(call dist-data,$(data_dist) details/config.h.in)
 	$(call meta-vc9proj,libstudxml-vc9.vcproj)
 	$(call meta-vc10proj,libstudxml-vc10.vcxproj)
diff --git a/xml/parser b/xml/parser
new file mode 100644
index 0000000..a1b6250
--- /dev/null
+++ b/xml/parser
@@ -0,0 +1,473 @@
+// file      : xml/parser -*- C++ -*-
+// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
+// license   : MIT; see accompanying LICENSE file
+
+#ifndef XML_PARSER
+#define XML_PARSER
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include  // std::size_t
+
+#include  // LIBSTUDXML_EXTERNAL_EXPAT
+
+#ifndef LIBSTUDXML_EXTERNAL_EXPAT
+#  include 
+#else
+#  include 
+#endif
+
+// We only support UTF-8 Expat.
+//
+#ifdef XML_UNICODE
+#  error UTF-16 expat (XML_UNICODE defined) is not supported
+#endif
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+namespace xml
+{
+  class parser;
+
+  struct LIBSTUDXML_EXPORT parsing: exception
+  {
+    virtual
+    ~parsing () throw ();
+
+    parsing (const std::string& name,
+             unsigned long long line,
+             unsigned long long column,
+             const std::string& description);
+
+    parsing (const parser&, const std::string& description);
+
+    const std::string&
+    name () const {return name_;}
+
+    unsigned long long
+    line () const {return line_;}
+
+    unsigned long long
+    column () const {return column_;}
+
+    const std::string&
+    description () const {return description_;}
+
+    virtual const char*
+    what () const throw ();
+
+    private:
+    void
+    init ();
+
+  private:
+    std::string name_;
+    unsigned long long line_;
+    unsigned long long column_;
+    std::string description_;
+    std::string what_;
+  };
+
+  class LIBSTUDXML_EXPORT parser
+  {
+  public:
+    typedef xml::qname qname_type;
+    typedef xml::content content_type;
+
+    typedef unsigned short feature_type;
+
+    // If both receive_attributes_event and receive_attributes_map are
+    // specified, then receive_attributes_event is assumed.
+    //
+    static const feature_type receive_elements = 0x0001;
+    static const feature_type receive_characters = 0x0002;
+    static const feature_type receive_attributes_map = 0x0004;
+    static const feature_type receive_attributes_event = 0x0008;
+    static const feature_type receive_namespace_decls = 0x0010;
+
+    static const feature_type receive_default = receive_elements |
+                                                receive_characters |
+                                                receive_attributes_map;
+
+    // Parse std::istream. Input name is used in diagnostics to identify
+    // the document being parsed.
+    //
+    // If stream exceptions are enabled then std::ios_base::failure
+    // exception is used to report io errors (badbit and failbit).
+    // Otherwise, those are reported as the parsing exception.
+    //
+    parser (std::istream&,
+            const std::string& input_name,
+            feature_type = receive_default);
+
+    // Parse memory buffer that contains the whole document. Input name
+    // is used in diagnostics to identify the document being parsed.
+    //
+    parser (const void* data,
+            std::size_t size,
+            const std::string& input_name,
+            feature_type = receive_default);
+
+    const std::string&
+    input_name () const {return iname_;}
+
+    ~parser ();
+
+  private:
+    parser (const parser&);
+    parser& operator= (const parser&);
+
+    // Parsing events.
+    //
+  public:
+    enum event_type
+    {
+      // If adding new events, also update the stream insertion operator.
+      //
+      start_element,
+      end_element,
+      start_attribute,
+      end_attribute,
+      characters,
+      start_namespace_decl,
+      end_namespace_decl,
+      eof
+    };
+
+    event_type
+    next ();
+
+    // Get the next event and make sure that it's what's expected. If it
+    // is not, then throw an appropriate parsing exception.
+    //
+    void
+    next_expect (event_type);
+
+    void
+    next_expect (event_type, const std::string& name);
+
+    void
+    next_expect (event_type, const qname_type& qname);
+
+    void
+    next_expect (event_type, const std::string& ns, const std::string& name);
+
+    event_type
+    peek ();
+
+    // Return the even that was last returned by the call to next() or
+    // peek().
+    //
+    event_type
+    event () {return event_;}
+
+    // Event data.
+    //
+  public:
+    const qname_type& qname () const {return *pqname_;}
+
+    const std::string& namespace_ () const {return pqname_->namespace_ ();}
+    const std::string& name () const {return pqname_->name ();}
+    const std::string& prefix () const {return pqname_->prefix ();}
+
+    std::string& value () {return *pvalue_;}
+    const std::string& value () const {return *pvalue_;}
+    template  T value () const;
+
+    unsigned long long line () const {return line_;}
+    unsigned long long column () const {return column_;}
+
+    // Attribute map lookup. If attribute is not found, then the version
+    // without the default value throws an appropriate parsing exception
+    // while the version with the default value returns that value.
+    //
+    // Note also that there is no attribute(ns,name) version since it
+    // would conflict with attribute(name,dv) (qualified attributes
+    // are not very common).
+    //
+    // Attribute map is valid throughout at the "element level" until
+    // end_element and not just during start_element. As a special case,
+    // the map is still valid after peek() that returned end_element until
+    // this end_element event is retrieved with next().
+    //
+    const std::string&
+    attribute (const std::string& name) const;
+
+    template 
+    T
+    attribute (const std::string& name) const;
+
+    std::string
+    attribute (const std::string& name,
+               const std::string& default_value) const;
+
+    template 
+    T
+    attribute (const std::string& name, const T& default_value) const;
+
+    const std::string&
+    attribute (const qname_type& qname) const;
+
+    template 
+    T
+    attribute (const qname_type& qname) const;
+
+    std::string
+    attribute (const qname_type& qname,
+               const std::string& default_value) const;
+
+    template 
+    T
+    attribute (const qname_type& qname, const T& default_value) const;
+
+    bool
+    attribute_present (const std::string& name) const;
+
+    bool
+    attribute_present (const qname_type& qname) const;
+
+    // Low-level attribute map access. Note that this API assumes
+    // all attributes are handled.
+    //
+    struct attribute_value_type
+    {
+      std::string value;
+      mutable bool handled;
+    };
+
+    typedef std::map attribute_map_type;
+
+    const attribute_map_type&
+    attribute_map () const;
+
+    // Optional content processing.
+    //
+  public:
+    // Note that you cannot get/set content while peeking.
+    //
+    void
+    content (content_type);
+
+    content_type
+    content () const;
+
+    // Versions that also set the content. Event type must be start_element.
+    //
+    void
+    next_expect (event_type, const std::string& name, content_type);
+
+    void
+    next_expect (event_type, const qname_type& qname, content_type);
+
+    void
+    next_expect (event_type,
+                 const std::string& ns, const std::string& name,
+                 content_type);
+
+    // Helpers for parsing elements with simple content. The first two
+    // functions assume that start_element has already been parsed. The
+    // rest parse the complete element, from start to end.
+    //
+    // Note also that as with attribute(), there is no (namespace,name)
+    // overload since it would conflicts with (namespace,default_value).
+    //
+  public:
+    std::string
+    element ();
+
+    template 
+    T
+    element ();
+
+    std::string
+    element (const std::string& name);
+
+    std::string
+    element (const qname_type& qname);
+
+    template 
+    T
+    element (const std::string& name);
+
+    template 
+    T
+    element (const qname_type& qname);
+
+    std::string
+    element (const std::string& name, const std::string& default_value);
+
+    std::string
+    element (const qname_type& qname, const std::string& default_value);
+
+    template 
+    T
+    element (const std::string& name, const T& default_value);
+
+    template 
+    T
+    element (const qname_type& qname, const T& default_value);
+
+    // C++11 range-based for support. Generally, the iterator interface
+    // doesn't make much sense for the parser so for now we have an
+    // implementation that is just enough to the range-based for.
+    //
+  public:
+    struct iterator
+    {
+      typedef event_type value_type;
+
+      iterator (parser* p = 0, event_type e = eof): p_ (p), e_ (e) {}
+      value_type operator* () const {return e_;}
+      iterator& operator++ () {e_ = p_->next (); return *this;}
+
+      // Comparison only makes sense when comparing to end (eof).
+      //
+      bool operator== (iterator y) const {return e_ == eof && y.e_ == eof;}
+      bool operator!= (iterator y) const {return !(*this == y);}
+
+    private:
+      parser* p_;
+      event_type e_;
+    };
+
+    iterator begin () {return iterator (this, next ());}
+    iterator end () {return iterator (this, eof);}
+
+  private:
+    static void XMLCALL
+    start_element_ (void*, const XML_Char*, const XML_Char**);
+
+    static void XMLCALL
+    end_element_ (void*, const XML_Char*);
+
+    static void XMLCALL
+    characters_ (void*, const XML_Char*, int);
+
+    static void XMLCALL
+    start_namespace_decl_ (void*, const XML_Char*, const XML_Char*);
+
+    static void XMLCALL
+    end_namespace_decl_ (void*, const XML_Char*);
+
+  private:
+    void
+    init ();
+
+    event_type
+    next_ (bool peek);
+
+    event_type
+    next_body ();
+
+    void
+    handle_error ();
+
+  private:
+    // If size_ is 0, then data is std::istream. Otherwise, it is a buffer.
+    //
+    union
+    {
+      std::istream* is;
+      const void* buf;
+    } data_;
+
+    std::size_t size_;
+
+    const std::string iname_;
+    feature_type feature_;
+
+    XML_Parser p_;
+    std::size_t depth_;
+    bool accumulate_; // Whether we are accumulating character content.
+    enum {state_next, state_peek} state_;
+    event_type event_;
+    event_type queue_;
+
+    qname_type qname_;
+    std::string value_;
+
+    // These are used to avoid copying when we are handling attributes
+    // and namespace decls.
+    //
+    const qname_type* pqname_;
+    std::string* pvalue_;
+
+    unsigned long long line_;
+    unsigned long long column_;
+
+    // Attributes as events.
+    //
+    struct attribute_type
+    {
+      qname_type qname;
+      std::string value;
+    };
+
+    typedef std::vector attributes;
+
+    attributes attr_;
+    attributes::size_type attr_i_; // Index of the current attribute.
+
+    // Namespace declarations.
+    //
+    typedef std::vector namespace_decls;
+
+    namespace_decls start_ns_;
+    namespace_decls::size_type start_ns_i_; // Index of the current decl.
+
+    namespace_decls end_ns_;
+    namespace_decls::size_type end_ns_i_; // Index of the current decl.
+
+    // Element state consisting of the content model and attribute map.
+    //
+    struct element_entry
+    {
+      element_entry (std::size_t d, content_type c = content_type::mixed)
+          : depth (d), content (c), attr_unhandled_ (0) {}
+
+      std::size_t depth;
+      content_type content;
+      attribute_map_type attr_map_;
+      mutable attribute_map_type::size_type attr_unhandled_;
+    };
+
+    typedef std::vector element_state;
+    std::vector element_state_;
+
+    // Empty attribute map to return when an element has no attributes.
+    //
+    const attribute_map_type empty_attr_map_;
+
+    // Return the element entry corresponding to the current depth, if
+    // exists, and NULL otherwise.
+    //
+    const element_entry*
+    get_element () const;
+
+    const element_entry*
+    get_element_ () const;
+
+    void
+    pop_element ();
+  };
+
+  LIBSTUDXML_EXPORT
+  std::ostream&
+  operator<< (std::ostream&, parser::event_type);
+}
+
+#include 
+#include 
+
+#include 
+
+#endif // XML_PARSER
diff --git a/xml/parser.cxx b/xml/parser.cxx
index 37f9f76..5e117b9 100644
--- a/xml/parser.cxx
+++ b/xml/parser.cxx
@@ -9,7 +9,7 @@
 #include 
 #include 
 
-#include 
+#include 
 
 using namespace std;
 
diff --git a/xml/parser.hxx b/xml/parser.hxx
deleted file mode 100644
index 6f90522..0000000
--- a/xml/parser.hxx
+++ /dev/null
@@ -1,473 +0,0 @@
-// file      : xml/parser.hxx
-// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
-// license   : MIT; see accompanying LICENSE file
-
-#ifndef XML_PARSER_HXX
-#define XML_PARSER_HXX
-
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include  // std::size_t
-
-#include  // LIBSTUDXML_EXTERNAL_EXPAT
-
-#ifndef LIBSTUDXML_EXTERNAL_EXPAT
-#  include 
-#else
-#  include 
-#endif
-
-// We only support UTF-8 Expat.
-//
-#ifdef XML_UNICODE
-#  error UTF-16 expat (XML_UNICODE defined) is not supported
-#endif
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-namespace xml
-{
-  class parser;
-
-  struct LIBSTUDXML_EXPORT parsing: exception
-  {
-    virtual
-    ~parsing () throw ();
-
-    parsing (const std::string& name,
-             unsigned long long line,
-             unsigned long long column,
-             const std::string& description);
-
-    parsing (const parser&, const std::string& description);
-
-    const std::string&
-    name () const {return name_;}
-
-    unsigned long long
-    line () const {return line_;}
-
-    unsigned long long
-    column () const {return column_;}
-
-    const std::string&
-    description () const {return description_;}
-
-    virtual const char*
-    what () const throw ();
-
-    private:
-    void
-    init ();
-
-  private:
-    std::string name_;
-    unsigned long long line_;
-    unsigned long long column_;
-    std::string description_;
-    std::string what_;
-  };
-
-  class LIBSTUDXML_EXPORT parser
-  {
-  public:
-    typedef xml::qname qname_type;
-    typedef xml::content content_type;
-
-    typedef unsigned short feature_type;
-
-    // If both receive_attributes_event and receive_attributes_map are
-    // specified, then receive_attributes_event is assumed.
-    //
-    static const feature_type receive_elements = 0x0001;
-    static const feature_type receive_characters = 0x0002;
-    static const feature_type receive_attributes_map = 0x0004;
-    static const feature_type receive_attributes_event = 0x0008;
-    static const feature_type receive_namespace_decls = 0x0010;
-
-    static const feature_type receive_default = receive_elements |
-                                                receive_characters |
-                                                receive_attributes_map;
-
-    // Parse std::istream. Input name is used in diagnostics to identify
-    // the document being parsed.
-    //
-    // If stream exceptions are enabled then std::ios_base::failure
-    // exception is used to report io errors (badbit and failbit).
-    // Otherwise, those are reported as the parsing exception.
-    //
-    parser (std::istream&,
-            const std::string& input_name,
-            feature_type = receive_default);
-
-    // Parse memory buffer that contains the whole document. Input name
-    // is used in diagnostics to identify the document being parsed.
-    //
-    parser (const void* data,
-            std::size_t size,
-            const std::string& input_name,
-            feature_type = receive_default);
-
-    const std::string&
-    input_name () const {return iname_;}
-
-    ~parser ();
-
-  private:
-    parser (const parser&);
-    parser& operator= (const parser&);
-
-    // Parsing events.
-    //
-  public:
-    enum event_type
-    {
-      // If adding new events, also update the stream insertion operator.
-      //
-      start_element,
-      end_element,
-      start_attribute,
-      end_attribute,
-      characters,
-      start_namespace_decl,
-      end_namespace_decl,
-      eof
-    };
-
-    event_type
-    next ();
-
-    // Get the next event and make sure that it's what's expected. If it
-    // is not, then throw an appropriate parsing exception.
-    //
-    void
-    next_expect (event_type);
-
-    void
-    next_expect (event_type, const std::string& name);
-
-    void
-    next_expect (event_type, const qname_type& qname);
-
-    void
-    next_expect (event_type, const std::string& ns, const std::string& name);
-
-    event_type
-    peek ();
-
-    // Return the even that was last returned by the call to next() or
-    // peek().
-    //
-    event_type
-    event () {return event_;}
-
-    // Event data.
-    //
-  public:
-    const qname_type& qname () const {return *pqname_;}
-
-    const std::string& namespace_ () const {return pqname_->namespace_ ();}
-    const std::string& name () const {return pqname_->name ();}
-    const std::string& prefix () const {return pqname_->prefix ();}
-
-    std::string& value () {return *pvalue_;}
-    const std::string& value () const {return *pvalue_;}
-    template  T value () const;
-
-    unsigned long long line () const {return line_;}
-    unsigned long long column () const {return column_;}
-
-    // Attribute map lookup. If attribute is not found, then the version
-    // without the default value throws an appropriate parsing exception
-    // while the version with the default value returns that value.
-    //
-    // Note also that there is no attribute(ns,name) version since it
-    // would conflict with attribute(name,dv) (qualified attributes
-    // are not very common).
-    //
-    // Attribute map is valid throughout at the "element level" until
-    // end_element and not just during start_element. As a special case,
-    // the map is still valid after peek() that returned end_element until
-    // this end_element event is retrieved with next().
-    //
-    const std::string&
-    attribute (const std::string& name) const;
-
-    template 
-    T
-    attribute (const std::string& name) const;
-
-    std::string
-    attribute (const std::string& name,
-               const std::string& default_value) const;
-
-    template 
-    T
-    attribute (const std::string& name, const T& default_value) const;
-
-    const std::string&
-    attribute (const qname_type& qname) const;
-
-    template 
-    T
-    attribute (const qname_type& qname) const;
-
-    std::string
-    attribute (const qname_type& qname,
-               const std::string& default_value) const;
-
-    template 
-    T
-    attribute (const qname_type& qname, const T& default_value) const;
-
-    bool
-    attribute_present (const std::string& name) const;
-
-    bool
-    attribute_present (const qname_type& qname) const;
-
-    // Low-level attribute map access. Note that this API assumes
-    // all attributes are handled.
-    //
-    struct attribute_value_type
-    {
-      std::string value;
-      mutable bool handled;
-    };
-
-    typedef std::map attribute_map_type;
-
-    const attribute_map_type&
-    attribute_map () const;
-
-    // Optional content processing.
-    //
-  public:
-    // Note that you cannot get/set content while peeking.
-    //
-    void
-    content (content_type);
-
-    content_type
-    content () const;
-
-    // Versions that also set the content. Event type must be start_element.
-    //
-    void
-    next_expect (event_type, const std::string& name, content_type);
-
-    void
-    next_expect (event_type, const qname_type& qname, content_type);
-
-    void
-    next_expect (event_type,
-                 const std::string& ns, const std::string& name,
-                 content_type);
-
-    // Helpers for parsing elements with simple content. The first two
-    // functions assume that start_element has already been parsed. The
-    // rest parse the complete element, from start to end.
-    //
-    // Note also that as with attribute(), there is no (namespace,name)
-    // overload since it would conflicts with (namespace,default_value).
-    //
-  public:
-    std::string
-    element ();
-
-    template 
-    T
-    element ();
-
-    std::string
-    element (const std::string& name);
-
-    std::string
-    element (const qname_type& qname);
-
-    template 
-    T
-    element (const std::string& name);
-
-    template 
-    T
-    element (const qname_type& qname);
-
-    std::string
-    element (const std::string& name, const std::string& default_value);
-
-    std::string
-    element (const qname_type& qname, const std::string& default_value);
-
-    template 
-    T
-    element (const std::string& name, const T& default_value);
-
-    template 
-    T
-    element (const qname_type& qname, const T& default_value);
-
-    // C++11 range-based for support. Generally, the iterator interface
-    // doesn't make much sense for the parser so for now we have an
-    // implementation that is just enough to the range-based for.
-    //
-  public:
-    struct iterator
-    {
-      typedef event_type value_type;
-
-      iterator (parser* p = 0, event_type e = eof): p_ (p), e_ (e) {}
-      value_type operator* () const {return e_;}
-      iterator& operator++ () {e_ = p_->next (); return *this;}
-
-      // Comparison only makes sense when comparing to end (eof).
-      //
-      bool operator== (iterator y) const {return e_ == eof && y.e_ == eof;}
-      bool operator!= (iterator y) const {return !(*this == y);}
-
-    private:
-      parser* p_;
-      event_type e_;
-    };
-
-    iterator begin () {return iterator (this, next ());}
-    iterator end () {return iterator (this, eof);}
-
-  private:
-    static void XMLCALL
-    start_element_ (void*, const XML_Char*, const XML_Char**);
-
-    static void XMLCALL
-    end_element_ (void*, const XML_Char*);
-
-    static void XMLCALL
-    characters_ (void*, const XML_Char*, int);
-
-    static void XMLCALL
-    start_namespace_decl_ (void*, const XML_Char*, const XML_Char*);
-
-    static void XMLCALL
-    end_namespace_decl_ (void*, const XML_Char*);
-
-  private:
-    void
-    init ();
-
-    event_type
-    next_ (bool peek);
-
-    event_type
-    next_body ();
-
-    void
-    handle_error ();
-
-  private:
-    // If size_ is 0, then data is std::istream. Otherwise, it is a buffer.
-    //
-    union
-    {
-      std::istream* is;
-      const void* buf;
-    } data_;
-
-    std::size_t size_;
-
-    const std::string iname_;
-    feature_type feature_;
-
-    XML_Parser p_;
-    std::size_t depth_;
-    bool accumulate_; // Whether we are accumulating character content.
-    enum {state_next, state_peek} state_;
-    event_type event_;
-    event_type queue_;
-
-    qname_type qname_;
-    std::string value_;
-
-    // These are used to avoid copying when we are handling attributes
-    // and namespace decls.
-    //
-    const qname_type* pqname_;
-    std::string* pvalue_;
-
-    unsigned long long line_;
-    unsigned long long column_;
-
-    // Attributes as events.
-    //
-    struct attribute_type
-    {
-      qname_type qname;
-      std::string value;
-    };
-
-    typedef std::vector attributes;
-
-    attributes attr_;
-    attributes::size_type attr_i_; // Index of the current attribute.
-
-    // Namespace declarations.
-    //
-    typedef std::vector namespace_decls;
-
-    namespace_decls start_ns_;
-    namespace_decls::size_type start_ns_i_; // Index of the current decl.
-
-    namespace_decls end_ns_;
-    namespace_decls::size_type end_ns_i_; // Index of the current decl.
-
-    // Element state consisting of the content model and attribute map.
-    //
-    struct element_entry
-    {
-      element_entry (std::size_t d, content_type c = content_type::mixed)
-          : depth (d), content (c), attr_unhandled_ (0) {}
-
-      std::size_t depth;
-      content_type content;
-      attribute_map_type attr_map_;
-      mutable attribute_map_type::size_type attr_unhandled_;
-    };
-
-    typedef std::vector element_state;
-    std::vector element_state_;
-
-    // Empty attribute map to return when an element has no attributes.
-    //
-    const attribute_map_type empty_attr_map_;
-
-    // Return the element entry corresponding to the current depth, if
-    // exists, and NULL otherwise.
-    //
-    const element_entry*
-    get_element () const;
-
-    const element_entry*
-    get_element_ () const;
-
-    void
-    pop_element ();
-  };
-
-  LIBSTUDXML_EXPORT
-  std::ostream&
-  operator<< (std::ostream&, parser::event_type);
-}
-
-#include 
-#include 
-
-#include 
-
-#endif // XML_PARSER_HXX
diff --git a/xml/parser.ixx b/xml/parser.ixx
index e5656d4..b0bffab 100644
--- a/xml/parser.ixx
+++ b/xml/parser.ixx
@@ -4,7 +4,7 @@
 
 #include 
 
-#include 
+#include 
 
 namespace xml
 {
diff --git a/xml/parser.txx b/xml/parser.txx
index 0167522..86d9ed7 100644
--- a/xml/parser.txx
+++ b/xml/parser.txx
@@ -2,7 +2,7 @@
 // copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
 // license   : MIT; see accompanying LICENSE file
 
-#include 
+#include 
 
 namespace xml
 {
diff --git a/xml/qname b/xml/qname
new file mode 100644
index 0000000..85d6424
--- /dev/null
+++ b/xml/qname
@@ -0,0 +1,87 @@
+// file      : xml/qname -*- C++ -*-
+// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
+// license   : MIT; see accompanying LICENSE file
+
+#ifndef XML_QNAME
+#define XML_QNAME
+
+#include 
+
+#include 
+#include 
+
+#include 
+
+#include 
+
+namespace xml
+{
+  // Note that the optional prefix is just a "syntactic sugar". In
+  // particular, it is ignored by the comparison operators and the
+  // std::ostream insertion operator.
+  //
+  class LIBSTUDXML_EXPORT qname
+  {
+  public:
+    qname () {}
+    qname (const std::string& name): name_ (name) {}
+    qname (const std::string& ns, const std::string& name)
+      : ns_ (ns), name_ (name) {}
+    qname (const std::string& ns,
+           const std::string& name,
+           const std::string& prefix)
+      : ns_ (ns), name_ (name), prefix_ (prefix) {}
+
+    const std::string& namespace_ () const {return ns_;}
+    const std::string& name () const {return name_;}
+    const std::string& prefix () const {return prefix_;}
+
+    std::string& namespace_ () {return ns_;}
+    std::string& name () {return name_;}
+    std::string& prefix () {return prefix_;}
+
+    bool
+    empty () const {return name_.empty () && ns_.empty ();}
+
+    // String representation in the [#] form.
+    //
+    std::string
+    string () const;
+
+    // Note that comparison operators ignore prefixes.
+    //
+  public:
+    friend bool
+    operator< (const qname& x, const qname& y)
+    {
+      return x.ns_ < y.ns_ || (x.ns_ == y.ns_ && x.name_ < y.name_);
+    }
+
+    friend bool
+    operator== (const qname& x, const qname& y)
+    {
+      return x.ns_ == y.ns_ && x.name_ == y.name_;
+    }
+
+    friend bool
+    operator!= (const qname& x, const qname& y)
+    {
+      return !(x == y);
+    }
+
+  private:
+    std::string ns_;
+    std::string name_;
+    std::string prefix_;
+  };
+
+  // Print the string representation ([#]).
+  //
+  LIBSTUDXML_EXPORT
+  std::ostream&
+  operator<< (std::ostream&, const qname&);
+}
+
+#include 
+
+#endif // XML_QNAME
diff --git a/xml/qname.cxx b/xml/qname.cxx
index 2261ab8..de24e57 100644
--- a/xml/qname.cxx
+++ b/xml/qname.cxx
@@ -4,7 +4,7 @@
 
 #include 
 
-#include 
+#include 
 
 using namespace std;
 
diff --git a/xml/qname.hxx b/xml/qname.hxx
deleted file mode 100644
index 7ffd215..0000000
--- a/xml/qname.hxx
+++ /dev/null
@@ -1,87 +0,0 @@
-// file      : xml/qname.hxx
-// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
-// license   : MIT; see accompanying LICENSE file
-
-#ifndef XML_QNAME_HXX
-#define XML_QNAME_HXX
-
-#include 
-
-#include 
-#include 
-
-#include 
-
-#include 
-
-namespace xml
-{
-  // Note that the optional prefix is just a "syntactic sugar". In
-  // particular, it is ignored by the comparison operators and the
-  // std::ostream insertion operator.
-  //
-  class LIBSTUDXML_EXPORT qname
-  {
-  public:
-    qname () {}
-    qname (const std::string& name): name_ (name) {}
-    qname (const std::string& ns, const std::string& name)
-      : ns_ (ns), name_ (name) {}
-    qname (const std::string& ns,
-           const std::string& name,
-           const std::string& prefix)
-      : ns_ (ns), name_ (name), prefix_ (prefix) {}
-
-    const std::string& namespace_ () const {return ns_;}
-    const std::string& name () const {return name_;}
-    const std::string& prefix () const {return prefix_;}
-
-    std::string& namespace_ () {return ns_;}
-    std::string& name () {return name_;}
-    std::string& prefix () {return prefix_;}
-
-    bool
-    empty () const {return name_.empty () && ns_.empty ();}
-
-    // String representation in the [#] form.
-    //
-    std::string
-    string () const;
-
-    // Note that comparison operators ignore prefixes.
-    //
-  public:
-    friend bool
-    operator< (const qname& x, const qname& y)
-    {
-      return x.ns_ < y.ns_ || (x.ns_ == y.ns_ && x.name_ < y.name_);
-    }
-
-    friend bool
-    operator== (const qname& x, const qname& y)
-    {
-      return x.ns_ == y.ns_ && x.name_ == y.name_;
-    }
-
-    friend bool
-    operator!= (const qname& x, const qname& y)
-    {
-      return !(x == y);
-    }
-
-  private:
-    std::string ns_;
-    std::string name_;
-    std::string prefix_;
-  };
-
-  // Print the string representation ([#]).
-  //
-  LIBSTUDXML_EXPORT
-  std::ostream&
-  operator<< (std::ostream&, const qname&);
-}
-
-#include 
-
-#endif // XML_QNAME_HXX
diff --git a/xml/serializer b/xml/serializer
new file mode 100644
index 0000000..6c55d51
--- /dev/null
+++ b/xml/serializer
@@ -0,0 +1,227 @@
+// file      : xml/serializer -*- C++ -*-
+// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
+// license   : MIT; see accompanying LICENSE file
+
+#ifndef XML_SERIALIZER
+#define XML_SERIALIZER
+
+#include 
+
+#include 
+#include 
+#include  // std::size_t
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+
+namespace xml
+{
+  class serializer;
+
+  struct LIBSTUDXML_EXPORT serialization: exception
+  {
+    virtual
+    ~serialization () throw ();
+
+    serialization (const std::string& name,
+                   const std::string& description);
+
+    serialization (const serializer&, const std::string& description);
+
+    const std::string&
+    name () const {return name_;}
+
+    const std::string&
+    description () const {return description_;}
+
+    virtual const char*
+    what () const throw ();
+
+  private:
+    void
+    init ();
+
+  private:
+    std::string name_;
+    std::string description_;
+    std::string what_;
+  };
+
+  class LIBSTUDXML_EXPORT serializer
+  {
+  public:
+    typedef xml::qname qname_type;
+
+    // Serialize to std::ostream. Output name is used in diagnostics to
+    // identify the document being serialized. The indentation argument
+    // specifies the number of indentation spaces that should be used for
+    // pretty-printing. If 0 is passed, no pretty-printing is performed.
+    //
+    // If stream exceptions are enabled then std::ios_base::failure
+    // exception is used to report io errors (badbit and failbit).
+    // Otherwise, those are reported as the serialization exception.
+    //
+    serializer (std::ostream&,
+                const std::string& output_name,
+                unsigned short indentation = 2);
+
+    const std::string&
+    output_name () const {return oname_;}
+
+    ~serializer ();
+
+  private:
+    serializer (const serializer&);
+    serializer& operator= (const serializer&);
+
+    // Serialization functions.
+    //
+  public:
+
+    // Elements.
+    //
+    void
+    start_element (const qname_type& qname);
+
+    void
+    start_element (const std::string& name);
+
+    void
+    start_element (const std::string& ns, const std::string& name);
+
+    void
+    end_element ();
+
+    // Helpers for serializing elements with simple content. The first two
+    // functions assume that start_element() has already been called. The
+    // other two serialize the complete element, from start to end.
+    //
+    void
+    element (const std::string& value);
+
+    template 
+    void
+    element (const T& value);
+
+    void
+    element (const std::string& name, const std::string& value);
+
+    template 
+    void
+    element (const std::string& name, const T& value);
+
+    void
+    element (const qname_type& qname, const std::string& value);
+
+    template 
+    void
+    element (const qname_type& qname, const T& value);
+
+    void
+    element (const std::string& namespace_,
+             const std::string& name,
+             const std::string& value);
+
+    template 
+    void
+    element (const std::string& namespace_,
+             const std::string& name,
+             const T& value);
+
+    // Attributes.
+    //
+    void
+    start_attribute (const qname_type& qname);
+
+    void
+    start_attribute (const std::string& name);
+
+    void
+    start_attribute (const std::string& ns, const std::string& name);
+
+    void
+    end_attribute ();
+
+    void
+    attribute (const qname_type& qname, const std::string& value);
+
+    template 
+    void
+    attribute (const qname_type& qname, const T& value);
+
+    void
+    attribute (const std::string& name, const std::string& value);
+
+    template 
+    void
+    attribute (const std::string& name, const T& value);
+
+    void
+    attribute (const std::string& ns,
+               const std::string& name,
+               const std::string& value);
+
+    template 
+    void
+    attribute (const std::string& ns,
+               const std::string& name,
+               const T& value);
+
+    // Characters.
+    //
+    void
+    characters (const std::string& value);
+
+    template 
+    void
+    characters (const T& value);
+
+    // Namespaces declaration. If prefix is empty, then the default
+    // namespace is declared. If both prefix and namespace are empty,
+    // then the default namespace declaration is cleared (xmlns="").
+    //
+    void
+    namespace_decl (const std::string& ns, const std::string& prefix);
+
+    // XML declaration. If encoding or standalone are not specified,
+    // then these attributes are omitted from the output.
+    //
+    void
+    xml_decl (const std::string& version = "1.0",
+              const std::string& encoding = "UTF-8",
+              const std::string& standalone = "");
+
+    // Utility functions.
+    //
+  public:
+    // Return true if there is a mapping. In this case, prefix contains
+    // the mapped prefix.
+    //
+    bool
+    lookup_namespace_prefix (const std::string& ns, std::string& prefix);
+
+  private:
+    void
+    handle_error (genxStatus);
+
+  private:
+    std::ostream& os_;
+    std::ostream::iostate os_state_; // Original exception state.
+    const std::string oname_;
+
+    genxWriter s_;
+    genxSender sender_;
+    std::size_t depth_;
+  };
+}
+
+#include 
+
+#include 
+
+#endif // XML_SERIALIZER
diff --git a/xml/serializer.cxx b/xml/serializer.cxx
index a6afcca..4d1da5b 100644
--- a/xml/serializer.cxx
+++ b/xml/serializer.cxx
@@ -5,7 +5,7 @@
 #include      // std::bad_alloc
 #include  // std::strlen
 
-#include 
+#include 
 
 using namespace std;
 
diff --git a/xml/serializer.hxx b/xml/serializer.hxx
deleted file mode 100644
index 4f57e48..0000000
--- a/xml/serializer.hxx
+++ /dev/null
@@ -1,227 +0,0 @@
-// file      : xml/serializer.hxx
-// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
-// license   : MIT; see accompanying LICENSE file
-
-#ifndef XML_SERIALIZER_HXX
-#define XML_SERIALIZER_HXX
-
-#include 
-
-#include 
-#include 
-#include  // std::size_t
-
-#include 
-
-#include 
-#include 
-#include 
-
-#include 
-
-namespace xml
-{
-  class serializer;
-
-  struct LIBSTUDXML_EXPORT serialization: exception
-  {
-    virtual
-    ~serialization () throw ();
-
-    serialization (const std::string& name,
-                   const std::string& description);
-
-    serialization (const serializer&, const std::string& description);
-
-    const std::string&
-    name () const {return name_;}
-
-    const std::string&
-    description () const {return description_;}
-
-    virtual const char*
-    what () const throw ();
-
-  private:
-    void
-    init ();
-
-  private:
-    std::string name_;
-    std::string description_;
-    std::string what_;
-  };
-
-  class LIBSTUDXML_EXPORT serializer
-  {
-  public:
-    typedef xml::qname qname_type;
-
-    // Serialize to std::ostream. Output name is used in diagnostics to
-    // identify the document being serialized. The indentation argument
-    // specifies the number of indentation spaces that should be used for
-    // pretty-printing. If 0 is passed, no pretty-printing is performed.
-    //
-    // If stream exceptions are enabled then std::ios_base::failure
-    // exception is used to report io errors (badbit and failbit).
-    // Otherwise, those are reported as the serialization exception.
-    //
-    serializer (std::ostream&,
-                const std::string& output_name,
-                unsigned short indentation = 2);
-
-    const std::string&
-    output_name () const {return oname_;}
-
-    ~serializer ();
-
-  private:
-    serializer (const serializer&);
-    serializer& operator= (const serializer&);
-
-    // Serialization functions.
-    //
-  public:
-
-    // Elements.
-    //
-    void
-    start_element (const qname_type& qname);
-
-    void
-    start_element (const std::string& name);
-
-    void
-    start_element (const std::string& ns, const std::string& name);
-
-    void
-    end_element ();
-
-    // Helpers for serializing elements with simple content. The first two
-    // functions assume that start_element() has already been called. The
-    // other two serialize the complete element, from start to end.
-    //
-    void
-    element (const std::string& value);
-
-    template 
-    void
-    element (const T& value);
-
-    void
-    element (const std::string& name, const std::string& value);
-
-    template 
-    void
-    element (const std::string& name, const T& value);
-
-    void
-    element (const qname_type& qname, const std::string& value);
-
-    template 
-    void
-    element (const qname_type& qname, const T& value);
-
-    void
-    element (const std::string& namespace_,
-             const std::string& name,
-             const std::string& value);
-
-    template 
-    void
-    element (const std::string& namespace_,
-             const std::string& name,
-             const T& value);
-
-    // Attributes.
-    //
-    void
-    start_attribute (const qname_type& qname);
-
-    void
-    start_attribute (const std::string& name);
-
-    void
-    start_attribute (const std::string& ns, const std::string& name);
-
-    void
-    end_attribute ();
-
-    void
-    attribute (const qname_type& qname, const std::string& value);
-
-    template 
-    void
-    attribute (const qname_type& qname, const T& value);
-
-    void
-    attribute (const std::string& name, const std::string& value);
-
-    template 
-    void
-    attribute (const std::string& name, const T& value);
-
-    void
-    attribute (const std::string& ns,
-               const std::string& name,
-               const std::string& value);
-
-    template 
-    void
-    attribute (const std::string& ns,
-               const std::string& name,
-               const T& value);
-
-    // Characters.
-    //
-    void
-    characters (const std::string& value);
-
-    template 
-    void
-    characters (const T& value);
-
-    // Namespaces declaration. If prefix is empty, then the default
-    // namespace is declared. If both prefix and namespace are empty,
-    // then the default namespace declaration is cleared (xmlns="").
-    //
-    void
-    namespace_decl (const std::string& ns, const std::string& prefix);
-
-    // XML declaration. If encoding or standalone are not specified,
-    // then these attributes are omitted from the output.
-    //
-    void
-    xml_decl (const std::string& version = "1.0",
-              const std::string& encoding = "UTF-8",
-              const std::string& standalone = "");
-
-    // Utility functions.
-    //
-  public:
-    // Return true if there is a mapping. In this case, prefix contains
-    // the mapped prefix.
-    //
-    bool
-    lookup_namespace_prefix (const std::string& ns, std::string& prefix);
-
-  private:
-    void
-    handle_error (genxStatus);
-
-  private:
-    std::ostream& os_;
-    std::ostream::iostate os_state_; // Original exception state.
-    const std::string oname_;
-
-    genxWriter s_;
-    genxSender sender_;
-    std::size_t depth_;
-  };
-}
-
-#include 
-
-#include 
-
-#endif // XML_SERIALIZER_HXX
diff --git a/xml/serializer.ixx b/xml/serializer.ixx
index 81631f2..ea3dcf0 100644
--- a/xml/serializer.ixx
+++ b/xml/serializer.ixx
@@ -2,7 +2,7 @@
 // copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
 // license   : MIT; see accompanying LICENSE file
 
-#include 
+#include 
 
 namespace xml
 {
diff --git a/xml/value-traits b/xml/value-traits
new file mode 100644
index 0000000..3bf10e0
--- /dev/null
+++ b/xml/value-traits
@@ -0,0 +1,53 @@
+// file      : xml/value-traits -*- C++ -*-
+// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
+// license   : MIT; see accompanying LICENSE file
+
+#ifndef XML_VALUE_TRAITS
+#define XML_VALUE_TRAITS
+
+#include 
+
+#include 
+#include  // std::size_t
+
+#include 
+
+#include 
+
+namespace xml
+{
+  template 
+  struct default_value_traits
+  {
+    static T
+    parse (std::string, const parser&);
+
+    static std::string
+    serialize (const T&, const serializer&);
+  };
+
+  template <>
+  struct LIBSTUDXML_EXPORT default_value_traits
+  {
+    static bool
+    parse (std::string, const parser&);
+
+    static std::string
+    serialize (bool v, const serializer&)
+    {
+      return v ? "true" : "false";
+    }
+  };
+
+  template 
+  struct value_traits: default_value_traits {};
+
+  template 
+  struct value_traits: default_value_traits {};
+}
+
+#include 
+
+#include 
+
+#endif // XML_VALUE_TRAITS
diff --git a/xml/value-traits.cxx b/xml/value-traits.cxx
index 65aa1b6..3530c91 100644
--- a/xml/value-traits.cxx
+++ b/xml/value-traits.cxx
@@ -2,7 +2,7 @@
 // copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
 // license   : MIT; see accompanying LICENSE file
 
-#include 
+#include 
 
 using namespace std;
 
diff --git a/xml/value-traits.hxx b/xml/value-traits.hxx
deleted file mode 100644
index ca86382..0000000
--- a/xml/value-traits.hxx
+++ /dev/null
@@ -1,53 +0,0 @@
-// file      : xml/value-traits.hxx
-// copyright : Copyright (c) 2013-2014 Code Synthesis Tools CC
-// license   : MIT; see accompanying LICENSE file
-
-#ifndef XML_VALUE_TRAITS_HXX
-#define XML_VALUE_TRAITS_HXX
-
-#include 
-
-#include 
-#include  // std::size_t
-
-#include 
-
-#include 
-
-namespace xml
-{
-  template 
-  struct default_value_traits
-  {
-    static T
-    parse (std::string, const parser&);
-
-    static std::string
-    serialize (const T&, const serializer&);
-  };
-
-  template <>
-  struct LIBSTUDXML_EXPORT default_value_traits
-  {
-    static bool
-    parse (std::string, const parser&);
-
-    static std::string
-    serialize (bool v, const serializer&)
-    {
-      return v ? "true" : "false";
-    }
-  };
-
-  template 
-  struct value_traits: default_value_traits {};
-
-  template 
-  struct value_traits: default_value_traits {};
-}
-
-#include 
-
-#include 
-
-#endif // XML_VALUE_TRAITS_HXX
diff --git a/xml/value-traits.txx b/xml/value-traits.txx
index b76b8a3..3947a99 100644
--- a/xml/value-traits.txx
+++ b/xml/value-traits.txx
@@ -4,8 +4,8 @@
 
 #include 
 
-#include 
-#include 
+#include 
+#include 
 
 namespace xml
 {
-- 
cgit v1.1