1 : #include <assert.h>
2 :
3 : #include "xml-writer.hh"
4 :
5 :
6 : namespace nix {
7 :
8 :
9 84 : XMLWriter::XMLWriter(bool indent, std::ostream & output)
10 84 : : output(output), indent(indent)
11 : {
12 84 : output << "<?xml version='1.0' encoding='utf-8'?>\n";
13 84 : closed = false;
14 84 : }
15 :
16 :
17 84 : XMLWriter::~XMLWriter()
18 : {
19 84 : close();
20 84 : }
21 :
22 :
23 84 : void XMLWriter::close()
24 : {
25 84 : if (closed) return;
26 0 : while (!pendingElems.empty()) closeElement();
27 0 : closed = true;
28 : }
29 :
30 :
31 570 : void XMLWriter::indent_(unsigned int depth)
32 : {
33 570 : if (!indent) return;
34 570 : output << string(depth * 2, ' ');
35 : }
36 :
37 :
38 : void XMLWriter::openElement(const string & name,
39 234 : const XMLAttrs & attrs)
40 : {
41 234 : assert(!closed);
42 234 : indent_(pendingElems.size());
43 234 : output << "<" << name;
44 234 : writeAttrs(attrs);
45 234 : output << ">";
46 234 : if (indent) output << "\n";
47 234 : pendingElems.push_back(name);
48 234 : }
49 :
50 :
51 234 : void XMLWriter::closeElement()
52 : {
53 234 : assert(!pendingElems.empty());
54 234 : indent_(pendingElems.size() - 1);
55 234 : output << "</" << pendingElems.back() << ">";
56 234 : if (indent) output << "\n";
57 234 : pendingElems.pop_back();
58 234 : if (pendingElems.empty()) closed = true;
59 234 : }
60 :
61 :
62 : void XMLWriter::writeEmptyElement(const string & name,
63 102 : const XMLAttrs & attrs)
64 : {
65 102 : assert(!closed);
66 102 : indent_(pendingElems.size());
67 102 : output << "<" << name;
68 102 : writeAttrs(attrs);
69 102 : output << " />";
70 102 : if (indent) output << "\n";
71 102 : }
72 :
73 :
74 0 : void XMLWriter::writeCharData(const string & data)
75 : {
76 0 : assert(!pendingElems.empty());
77 0 : for (unsigned int i = 0; i < data.size(); ++i) {
78 0 : char c = data[i];
79 0 : if (c == '<') output << "<";
80 0 : else if (c == '&') output << "&";
81 0 : else output << c;
82 : }
83 0 : }
84 :
85 :
86 336 : void XMLWriter::writeAttrs(const XMLAttrs & attrs)
87 : {
88 529 : for (XMLAttrs::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
89 193 : output << " " << i->first << "=\"";
90 724 : for (unsigned int j = 0; j < i->second.size(); ++j) {
91 531 : char c = i->second[j];
92 531 : if (c == '"') output << """;
93 531 : else if (c == '<') output << "<";
94 531 : else if (c == '&') output << "&";
95 : /* Escape newlines to prevent attribute normalisation (see
96 : XML spec, section 3.3.3. */
97 531 : else if (c == '\n') output << "
";
98 531 : else output << c;
99 : }
100 193 : output << "\"";
101 : }
102 336 : }
103 :
104 :
105 : #if 0
106 : int main(int argc, char * * argv)
107 : {
108 : XMLWriter doc(cout);
109 :
110 : // OpenElement e(doc, "foo");
111 :
112 : doc.openElement("foo");
113 :
114 : doc.writeCharData("dit is een test &\n");
115 : doc.writeCharData("<foo>\n");
116 :
117 : for (int i = 0; i < 5; ++i) {
118 : XMLAttrs attrs;
119 : attrs["a"] = "b";
120 : attrs["bla"] = "<foo>'&\">";
121 : XMLOpenElement e(doc, "item", attrs);
122 : doc.writeCharData("x");
123 : }
124 :
125 : return 0;
126 : }
127 : #endif
128 :
129 :
130 478 : }
|