cmXMLWriter.cxx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2015 Daniel Pfeifer <[email protected]>
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmXMLWriter.h"
  11. #include "cmXMLSafe.h"
  12. #include <cassert>
  13. #include <fstream>
  14. cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)
  15. : Output(output)
  16. , Level(level)
  17. , ElementOpen(false)
  18. , BreakAttrib(false)
  19. , IsContent(false)
  20. {
  21. }
  22. cmXMLWriter::~cmXMLWriter()
  23. {
  24. assert(this->Elements.empty());
  25. }
  26. void cmXMLWriter::StartDocument(const char* encoding)
  27. {
  28. this->Output << "<?xml version=\"1.0\" encoding=\"" << encoding << "\"?>";
  29. }
  30. void cmXMLWriter::EndDocument()
  31. {
  32. assert(this->Elements.empty());
  33. this->Output << '\n';
  34. }
  35. void cmXMLWriter::StartElement(std::string const& name)
  36. {
  37. this->CloseStartElement();
  38. this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
  39. this->Output << '<' << name;
  40. this->Elements.push(name);
  41. this->ElementOpen = true;
  42. this->BreakAttrib = false;
  43. }
  44. void cmXMLWriter::EndElement()
  45. {
  46. assert(!this->Elements.empty());
  47. if (this->ElementOpen)
  48. {
  49. this->Output << "/>";
  50. }
  51. else
  52. {
  53. this->ConditionalLineBreak(!this->IsContent, this->Elements.size() - 1);
  54. this->IsContent = false;
  55. this->Output << "</" << this->Elements.top() << '>';
  56. }
  57. this->Elements.pop();
  58. this->ElementOpen = false;
  59. }
  60. void cmXMLWriter::Element(const char* name)
  61. {
  62. this->CloseStartElement();
  63. this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
  64. this->Output << '<' << name << "/>";
  65. }
  66. void cmXMLWriter::BreakAttributes()
  67. {
  68. this->BreakAttrib = true;
  69. }
  70. void cmXMLWriter::Comment(const char* comment)
  71. {
  72. this->CloseStartElement();
  73. this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
  74. this->Output << "<!-- " << comment << " -->";
  75. }
  76. void cmXMLWriter::CData(std::string const& data)
  77. {
  78. this->PreContent();
  79. this->Output << "<![CDATA[" << data << "]]>";
  80. }
  81. void cmXMLWriter::Doctype(const char* doctype)
  82. {
  83. this->CloseStartElement();
  84. this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
  85. this->Output << "<!DOCTYPE " << doctype << ">";
  86. }
  87. void cmXMLWriter::ProcessingInstruction(const char* target, const char* data)
  88. {
  89. this->CloseStartElement();
  90. this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
  91. this->Output << "<?" << target << ' ' << data << "?>";
  92. }
  93. void cmXMLWriter::FragmentFile(const char* fname)
  94. {
  95. this->CloseStartElement();
  96. std::ifstream fin(fname, std::ios::in | std::ios::binary);
  97. this->Output << fin.rdbuf();
  98. }
  99. void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent)
  100. {
  101. if (condition)
  102. {
  103. this->Output << '\n' << std::string(indent + this->Level, '\t');
  104. }
  105. }
  106. void cmXMLWriter::PreAttribute()
  107. {
  108. assert(this->ElementOpen);
  109. this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
  110. if (!this->BreakAttrib)
  111. {
  112. this->Output << ' ';
  113. }
  114. }
  115. void cmXMLWriter::PreContent()
  116. {
  117. this->CloseStartElement();
  118. this->IsContent = true;
  119. }
  120. void cmXMLWriter::CloseStartElement()
  121. {
  122. if (this->ElementOpen)
  123. {
  124. this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
  125. this->Output << '>';
  126. this->ElementOpen = false;
  127. }
  128. }