cmXMLWriter.cxx 3.3 KB

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