diff --git a/contrib/html5-printer.cpp b/contrib/html5-printer.cpp
new file mode 100644
index 0000000..4ad63bb
--- /dev/null
+++ b/contrib/html5-printer.cpp
@@ -0,0 +1,87 @@
+// g++ -Wall -O2 contrib/html5-printer.cpp -o html5-printer -ltinyxml2
+
+// This program demonstrates how to use "tinyxml2" to generate conformant HTML5
+// by deriving from the "tinyxml2::XMLPrinter" class.
+
+// http://dev.w3.org/html5/markup/syntax.html
+
+// In HTML5, there are 16 so-called "void" elements. "void elements" NEVER have
+// inner content (but they MAY have attributes), and are assumed to be self-closing.
+// An example of a self-closig HTML5 element is "
" (line break)
+// All other elements are called "non-void" and MUST never self-close.
+// Examples: "
".
+
+// tinyxml2::XMLPrinter will emit _ALL_ XML elements with no inner content as
+// self-closing. This behavior produces space-effeceint XML, but incorrect HTML5.
+
+// Author: Dennis Jenkins, dennis (dot) jenkins (dot) 75 (at) gmail (dot) com.
+// License: Same as tinyxml2 (zlib)
+// This example is a small contribution to the world! Enjoy it!
+
+
+#include
+#include
+
+#if defined (_MSC_VER)
+#define strcasecmp stricmp
+#endif
+
+using namespace tinyxml2;
+
+// Contrived input containing a mix of void and non-void HTML5 elements.
+// When printed via XMLPrinter, some non-void elements will self-close (not valid HTML5).
+static const char input[] =
+"
©";
+
+// XMLPrinterHTML5 is small enough, just put the entire implementation inline.
+class XMLPrinterHTML5 : public XMLPrinter
+{
+public:
+ XMLPrinterHTML5 (FILE* file=0, bool compact = false, int depth = 0) :
+ XMLPrinter (file, compact, depth)
+ {}
+
+protected:
+ virtual void CloseElement () {
+ if (_elementJustOpened && !isVoidElement (_stack.PeekTop())) {
+ SealElement();
+ }
+ XMLPrinter::CloseElement();
+ }
+
+ virtual bool isVoidElement (const char *name) {
+// Complete list of all HTML5 "void elements",
+// http://dev.w3.org/html5/markup/syntax.html
+ static const char *list[] = {
+ "area", "base", "br", "col", "command", "embed", "hr", "img",
+ "input", "keygen", "link", "meta", "param", "source", "track", "wbr",
+ NULL
+ };
+
+// I could use 'bsearch', but I don't have MSVC to test on (it would work with gcc/libc).
+ for (const char **p = list; *p; ++p) {
+ if (!strcasecmp (name, *p)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+};
+
+int main (void) {
+ XMLDocument doc (false);
+ doc.Parse (input);
+
+ std::cout << "INPUT:\n" << input << "\n\n";
+
+ XMLPrinter prn (NULL, true);
+ doc.Print (&prn);
+ std::cout << "XMLPrinter (not valid HTML5):\n" << prn.CStr() << "\n\n";
+
+ XMLPrinterHTML5 html5 (NULL, true);
+ doc.Print (&html5);
+ std::cout << "XMLPrinterHTML5:\n" << html5.CStr() << "\n";
+
+ return 0;
+}