include/relpipe/xmlwriter/XMLWriter.h
author František Kučera <franta-hg@frantovo.cz>
Mon, 08 Apr 2019 13:37:14 +0200
branchv_0
changeset 8 60183af4604e
parent 3 edbebc6163e3
child 11 56c84049698d
permissions -rw-r--r--
Added tag v0.11 for changeset 5201d93f8bdd
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
     1
/**
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
     2
 * Relational pipes
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
     3
 * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info)
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
     4
 *
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
     5
 * This program is free software: you can redistribute it and/or modify
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
     6
 * it under the terms of the GNU General Public License as published by
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
     7
 * the Free Software Foundation, either version 3 of the License, or
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
     8
 * (at your option) any later version.
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
     9
 *
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    10
 * This program is distributed in the hope that it will be useful,
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    13
 * GNU General Public License for more details.
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    14
 *
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    15
 * You should have received a copy of the GNU General Public License
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    16
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    17
 */
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    18
#pragma once
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    19
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    20
#include <iostream>
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    21
#include <sstream>
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    22
#include <string>
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    23
#include <vector>
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    24
#include <codecvt>
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    25
#include <locale>
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    26
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    27
#include "RelpipeXMLWriterException.h"
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    28
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    29
using namespace std;
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    30
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    31
namespace relpipe {
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    32
namespace xmlwriter {
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    33
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    34
/**
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    35
 * A simple library for writing XML streams.
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    36
 * 
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    37
 * Does:
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    38
 *  - convert wstring values to UTF-8
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    39
 *  - escape values of text nodes and attributes
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    40
 *  - indent elements
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    41
 *  - preserve whitespace of text nodes
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    42
 *  - in comments: replace - with –
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    43
 * Does not:
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    44
 *  - understand XML namespaces:
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    45
 *     - handles xmlns:x="y" as ordinary attributes
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    46
 *     - thus can not check whether elements/attributes belong to an declared namespace
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    47
 *     - thus can generate invalid XML – namespaces and their prefixes must be checked on the caller side
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    48
 */
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    49
class XMLWriter {
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    50
private:
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    51
	const char* INDENT = "\t";
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    52
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    53
	ostream& output;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    54
	wstring_convert<codecvt_utf8<wchar_t>> convertor; // XML output will be always in UTF-8
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    55
	vector<wstring> treePosition;
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    56
	bool lastWasTextNode = false;
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    57
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    58
	const string escapeXmlText(const wstring& value) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    59
		// TODO: really bad performance → rewrite
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    60
		// 72 % of whole relpipe-out-xml according to valgrind/callgrind
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    61
		// Moved here from XmlHandler.h (relpipe-out-xml).
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    62
		std::wstringstream result;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    63
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    64
		for (auto & ch : value) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    65
			switch (ch) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    66
				case L'&': result << L"&amp;";
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    67
					break;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    68
				case L'<': result << L"&lt;";
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    69
					break;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    70
				case L'>': result << L"&gt;";
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    71
					break;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    72
				case L'\'': result << L"&apos;"; // TODO: escape ' and " only in attributes
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    73
					break;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    74
				case L'"': result << L"&quot;"; // TODO: escape ' and " only in attributes
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    75
					break;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    76
				default: result << ch;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    77
			}
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    78
		}
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    79
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    80
		return convertor.to_bytes(result.str());
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    81
	}
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    82
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    83
	const string escapeXmlAttribute(const wstring& value) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    84
		// TODO: escaping of ' is not necessary.
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    85
		return escapeXmlText(value);
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    86
	}
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    87
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    88
	const string escapeComment(const wstring& value) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    89
		// TODO: really bad performance → rewrite
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    90
		// 72 % of whole relpipe-out-xml according to valgrind/callgrind
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    91
		std::wstringstream result;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    92
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    93
		for (auto & ch : value) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    94
			switch (ch) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    95
				case L'-': result << L"–";
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    96
					break;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    97
				default: result << ch;
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    98
			}
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    99
		}
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   100
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   101
		return convertor.to_bytes(result.str());
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   102
	}
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   103
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   104
	void checkName(const wstring& name) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   105
		// FIXME: throw exception on invalid names
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   106
	}
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   107
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   108
	void writeAttributes(const vector<wstring>& attributes) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   109
		if (attributes.size() % 2) throw RelpipeXMLWriterException(L"attributes vector must contain name/value pairs (even number of elements)");
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   110
		for (int i = 0; i < attributes.size(); i = i + 2) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   111
			wstring name = attributes[i];
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   112
			wstring value = attributes[i + 1];
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   113
			checkName(name);
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   114
			output << " " << convertor.to_bytes(name) << "=\"" << escapeXmlAttribute(value) << "\"";
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   115
		}
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   116
	}
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   117
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   118
	void writeIndentation(bool resetState = true) {
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   119
		if (lastWasTextNode) {
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   120
			if (resetState) lastWasTextNode = false;
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   121
		} else {
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   122
			output << endl;
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   123
			for (int i = 0; i < treePosition.size(); i++) {
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   124
				output << INDENT;
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   125
			}
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   126
		}
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   127
	}
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   128
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   129
public:
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   130
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   131
	XMLWriter(std::ostream& output) : output(output) {
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   132
		output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   133
	}
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   134
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   135
	virtual ~XMLWriter() {
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   136
		output << endl;
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   137
		output.flush();
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   138
	}
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   139
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   140
	void writeStartElement(const wstring& name, const vector<wstring>& attributes = {}) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   141
		checkName(name);
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   142
		writeIndentation();
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   143
		treePosition.push_back(name);
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   144
		output << "<" << convertor.to_bytes(name);
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   145
		writeAttributes(attributes);
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   146
		output << ">";
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   147
	}
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   148
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   149
	void writeEndElement() {
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   150
		if (treePosition.empty()) throw RelpipeXMLWriterException(L"unable to close element – all elements are already closed");
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   151
		wstring name = treePosition.back();
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   152
		treePosition.pop_back();
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   153
		writeIndentation();
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   154
		output << "</" << convertor.to_bytes(name) << ">";
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   155
	}
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   156
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   157
	void writeEmptyElement(const wstring& name, const vector<wstring>& attributes = {}) {
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   158
		checkName(name);
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   159
		writeIndentation();
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   160
		output << "<" << convertor.to_bytes(name);
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   161
		writeAttributes(attributes);
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   162
		output << "/>";
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   163
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   164
	}
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   165
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   166
	void writeTextElement(const wstring& name, const vector<wstring>& attributes, const wstring& text) {
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   167
		writeStartElement(name, attributes);
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   168
		writeCharacters(text);
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   169
		writeEndElement();
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   170
	}
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   171
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   172
	void writeCharacters(const wstring& text) {
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   173
		output << escapeXmlText(text);
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   174
		lastWasTextNode = true;
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   175
	}
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   176
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   177
	void writeComment(const wstring& text, bool addSpaces = true) {
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   178
		writeIndentation(false);
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   179
		output << (addSpaces ? "<!-- " : "<!--");
2
f21d6ae71bf0 move common XML code to relpipe-lib-xmlwriter (a header-only library)
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   180
		output << escapeComment(text);
3
edbebc6163e3 indentation
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   181
		output << (addSpaces ? " -->" : "-->");
1
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   182
	}
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   183
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   184
};
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   185
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   186
}
7d3081e51970 class skeleton
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   187
}