// 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; }