html5-printer.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // g++ -Wall -O2 contrib/html5-printer.cpp -o html5-printer -ltinyxml2
  2. // This program demonstrates how to use "tinyxml2" to generate conformant HTML5
  3. // by deriving from the "tinyxml2::XMLPrinter" class.
  4. // http://dev.w3.org/html5/markup/syntax.html
  5. // In HTML5, there are 16 so-called "void" elements. "void elements" NEVER have
  6. // inner content (but they MAY have attributes), and are assumed to be self-closing.
  7. // An example of a self-closig HTML5 element is "<br/>" (line break)
  8. // All other elements are called "non-void" and MUST never self-close.
  9. // Examples: "<div class='lolcats'></div>".
  10. // tinyxml2::XMLPrinter will emit _ALL_ XML elements with no inner content as
  11. // self-closing. This behavior produces space-effeceint XML, but incorrect HTML5.
  12. // Author: Dennis Jenkins, dennis (dot) jenkins (dot) 75 (at) gmail (dot) com.
  13. // License: Same as tinyxml2 (zlib)
  14. // This example is a small contribution to the world! Enjoy it!
  15. #include <tinyxml2.h>
  16. #include <iostream>
  17. #if defined (_MSC_VER)
  18. #define strcasecmp stricmp
  19. #endif
  20. using namespace tinyxml2;
  21. // Contrived input containing a mix of void and non-void HTML5 elements.
  22. // When printed via XMLPrinter, some non-void elements will self-close (not valid HTML5).
  23. static const char input[] =
  24. "<html><body><p style='a'></p><br/>&copy;<col a='1' b='2'/><div a='1'></div></body></html>";
  25. // XMLPrinterHTML5 is small enough, just put the entire implementation inline.
  26. class XMLPrinterHTML5 : public XMLPrinter
  27. {
  28. public:
  29. XMLPrinterHTML5 (FILE* file=0, bool compact = false, int depth = 0) :
  30. XMLPrinter (file, compact, depth)
  31. {}
  32. protected:
  33. virtual void CloseElement () {
  34. if (_elementJustOpened && !isVoidElement (_stack.PeekTop())) {
  35. SealElement();
  36. }
  37. XMLPrinter::CloseElement();
  38. }
  39. virtual bool isVoidElement (const char *name) {
  40. // Complete list of all HTML5 "void elements",
  41. // http://dev.w3.org/html5/markup/syntax.html
  42. static const char *list[] = {
  43. "area", "base", "br", "col", "command", "embed", "hr", "img",
  44. "input", "keygen", "link", "meta", "param", "source", "track", "wbr",
  45. NULL
  46. };
  47. // I could use 'bsearch', but I don't have MSVC to test on (it would work with gcc/libc).
  48. for (const char **p = list; *p; ++p) {
  49. if (!strcasecmp (name, *p)) {
  50. return true;
  51. }
  52. }
  53. return false;
  54. }
  55. };
  56. int main (void) {
  57. XMLDocument doc (false);
  58. doc.Parse (input);
  59. std::cout << "INPUT:\n" << input << "\n\n";
  60. XMLPrinter prn (NULL, true);
  61. doc.Print (&prn);
  62. std::cout << "XMLPrinter (not valid HTML5):\n" << prn.CStr() << "\n\n";
  63. XMLPrinterHTML5 html5 (NULL, true);
  64. doc.Print (&html5);
  65. std::cout << "XMLPrinterHTML5:\n" << html5.CStr() << "\n";
  66. return 0;
  67. }