include/relpipe/xmlwriter/XMLWriter.h
branchv_0
changeset 3 edbebc6163e3
parent 2 f21d6ae71bf0
child 11 56c84049698d
equal deleted inserted replaced
2:f21d6ae71bf0 3:edbebc6163e3
    51 	const char* INDENT = "\t";
    51 	const char* INDENT = "\t";
    52 
    52 
    53 	ostream& output;
    53 	ostream& output;
    54 	wstring_convert<codecvt_utf8<wchar_t>> convertor; // XML output will be always in UTF-8
    54 	wstring_convert<codecvt_utf8<wchar_t>> convertor; // XML output will be always in UTF-8
    55 	vector<wstring> treePosition;
    55 	vector<wstring> treePosition;
       
    56 	bool lastWasTextNode = false;
    56 
    57 
    57 	const string escapeXmlText(const wstring& value) {
    58 	const string escapeXmlText(const wstring& value) {
    58 		// TODO: really bad performance → rewrite
    59 		// TODO: really bad performance → rewrite
    59 		// 72 % of whole relpipe-out-xml according to valgrind/callgrind
    60 		// 72 % of whole relpipe-out-xml according to valgrind/callgrind
    60 		// Moved here from XmlHandler.h (relpipe-out-xml).
    61 		// Moved here from XmlHandler.h (relpipe-out-xml).
   112 			checkName(name);
   113 			checkName(name);
   113 			output << " " << convertor.to_bytes(name) << "=\"" << escapeXmlAttribute(value) << "\"";
   114 			output << " " << convertor.to_bytes(name) << "=\"" << escapeXmlAttribute(value) << "\"";
   114 		}
   115 		}
   115 	}
   116 	}
   116 
   117 
       
   118 	void writeIndentation(bool resetState = true) {
       
   119 		if (lastWasTextNode) {
       
   120 			if (resetState) lastWasTextNode = false;
       
   121 		} else {
       
   122 			output << endl;
       
   123 			for (int i = 0; i < treePosition.size(); i++) {
       
   124 				output << INDENT;
       
   125 			}
       
   126 		}
       
   127 	}
       
   128 
   117 public:
   129 public:
   118 
   130 
   119 	XMLWriter(std::ostream& output) : output(output) {
   131 	XMLWriter(std::ostream& output) : output(output) {
   120 		output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
   132 		output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
   121 	}
   133 	}
   122 
   134 
   123 	virtual ~XMLWriter() {
   135 	virtual ~XMLWriter() {
       
   136 		output << endl;
   124 		output.flush();
   137 		output.flush();
   125 	}
   138 	}
   126 
   139 
   127 	void writeStartElement(const wstring& name, const vector<wstring>& attributes = {}) {
   140 	void writeStartElement(const wstring& name, const vector<wstring>& attributes = {}) {
   128 		// FIXME: indentation
       
   129 		checkName(name);
   141 		checkName(name);
       
   142 		writeIndentation();
   130 		treePosition.push_back(name);
   143 		treePosition.push_back(name);
   131 		output << "<" << convertor.to_bytes(name);
   144 		output << "<" << convertor.to_bytes(name);
   132 		writeAttributes(attributes);
   145 		writeAttributes(attributes);
   133 		output << ">";
   146 		output << ">";
   134 	}
   147 	}
   135 
   148 
   136 	void writeEndElement() {
   149 	void writeEndElement() {
   137 		// FIXME: indentation
       
   138 		if (treePosition.empty()) throw RelpipeXMLWriterException(L"unable to close element – all elements are already closed");
   150 		if (treePosition.empty()) throw RelpipeXMLWriterException(L"unable to close element – all elements are already closed");
   139 		output << "</" << convertor.to_bytes(treePosition.back()) << ">";
   151 		wstring name = treePosition.back();
   140 		treePosition.pop_back();
   152 		treePosition.pop_back();
       
   153 		writeIndentation();
       
   154 		output << "</" << convertor.to_bytes(name) << ">";
   141 	}
   155 	}
   142 
   156 
   143 	void writeEmptyElement(const wstring& name, const vector<wstring>& attributes = {}) {
   157 	void writeEmptyElement(const wstring& name, const vector<wstring>& attributes = {}) {
   144 		// FIXME: indentation
       
   145 		checkName(name);
   158 		checkName(name);
       
   159 		writeIndentation();
   146 		output << "<" << convertor.to_bytes(name);
   160 		output << "<" << convertor.to_bytes(name);
   147 		writeAttributes(attributes);
   161 		writeAttributes(attributes);
   148 		output << "/>";
   162 		output << "/>";
   149 
   163 
   150 	}
   164 	}
   155 		writeEndElement();
   169 		writeEndElement();
   156 	}
   170 	}
   157 
   171 
   158 	void writeCharacters(const wstring& text) {
   172 	void writeCharacters(const wstring& text) {
   159 		output << escapeXmlText(text);
   173 		output << escapeXmlText(text);
       
   174 		lastWasTextNode = true;
   160 	}
   175 	}
   161 
   176 
   162 	void writeComment(const wstring& text, bool addSpaces = true) {
   177 	void writeComment(const wstring& text, bool addSpaces = true) {
   163 		output << addSpaces ? "<!-- " : "<!--";
   178 		writeIndentation(false);
       
   179 		output << (addSpaces ? "<!-- " : "<!--");
   164 		output << escapeComment(text);
   180 		output << escapeComment(text);
   165 		output << addSpaces ? " -->" : "-->";
   181 		output << (addSpaces ? " -->" : "-->");
   166 	}
   182 	}
   167 
   183 
   168 };
   184 };
   169 
   185 
   170 }
   186 }