blob: 11cd632399ad117df3bb62618b75aeb07dbb9e65 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
#include "xml-writer.hh"
#include <cassert>
namespace nix {
XMLWriter::XMLWriter(bool indent, std::ostream& output)
: output(output), indent(indent) {
output << "<?xml version='1.0' encoding='utf-8'?>" << std::endl;
closed = false;
}
XMLWriter::~XMLWriter() { close(); }
void XMLWriter::close() {
if (closed) {
return;
}
while (!pendingElems.empty()) {
closeElement();
}
closed = true;
}
void XMLWriter::indent_(size_t depth) {
if (!indent) {
return;
}
output << string(depth * 2, ' ');
}
void XMLWriter::openElement(const string& name, const XMLAttrs& attrs) {
assert(!closed);
indent_(pendingElems.size());
output << "<" << name;
writeAttrs(attrs);
output << ">";
if (indent) {
output << std::endl;
}
pendingElems.push_back(name);
}
void XMLWriter::closeElement() {
assert(!pendingElems.empty());
indent_(pendingElems.size() - 1);
output << "</" << pendingElems.back() << ">";
if (indent) {
output << std::endl;
}
pendingElems.pop_back();
if (pendingElems.empty()) {
closed = true;
}
}
void XMLWriter::writeEmptyElement(const string& name, const XMLAttrs& attrs) {
assert(!closed);
indent_(pendingElems.size());
output << "<" << name;
writeAttrs(attrs);
output << " />";
if (indent) {
output << std::endl;
}
}
void XMLWriter::writeAttrs(const XMLAttrs& attrs) {
for (auto& i : attrs) {
output << " " << i.first << "=\"";
for (char c : i.second) {
if (c == '"') {
output << """;
} else if (c == '<') {
output << "<";
} else if (c == '>') {
output << ">";
} else if (c == '&') {
output << "&";
/* Escape newlines to prevent attribute normalisation (see
XML spec, section 3.3.3. */
} else if (c == '\n') {
output << "
";
} else {
output << c;
}
}
output << "\"";
}
}
} // namespace nix
|