1 : #include <assert.h>
2 :
3 : #include "xml-writer.hh"
4 :
5 :
6 : namespace nix {
7 :
8 :
9 : XMLWriter::XMLWriter(bool indent, std::ostream & output)
10 27 : : output(output), indent(indent)
11 27 : {
12 27 : output << "<?xml version='1.0' encoding='utf-8'?>\n";
13 27 : closed = false;
14 : }
15 :
16 :
17 : XMLWriter::~XMLWriter()
18 54 : {
19 27 : close();
20 : }
21 :
22 :
23 : void XMLWriter::close()
24 27 : {
25 27 : if (closed) return;
26 0 : while (!pendingElems.empty()) closeElement();
27 0 : closed = true;
28 : }
29 :
30 :
31 : void XMLWriter::indent_(unsigned int depth)
32 105 : {
33 105 : if (!indent) return;
34 105 : output << string(depth * 2, ' ');
35 : }
36 :
37 :
38 : void XMLWriter::openElement(const string & name,
39 : const XMLAttrs & attrs)
40 46 : {
41 46 : assert(!closed);
42 46 : indent_(pendingElems.size());
43 46 : output << "<" << name;
44 46 : writeAttrs(attrs);
45 46 : output << ">";
46 46 : if (indent) output << "\n";
47 46 : pendingElems.push_back(name);
48 : }
49 :
50 :
51 : void XMLWriter::closeElement()
52 46 : {
53 46 : assert(!pendingElems.empty());
54 46 : indent_(pendingElems.size() - 1);
55 46 : output << "</" << pendingElems.back() << ">";
56 46 : if (indent) output << "\n";
57 46 : pendingElems.pop_back();
58 46 : if (pendingElems.empty()) closed = true;
59 : }
60 :
61 :
62 : void XMLWriter::writeEmptyElement(const string & name,
63 : const XMLAttrs & attrs)
64 13 : {
65 13 : assert(!closed);
66 13 : indent_(pendingElems.size());
67 13 : output << "<" << name;
68 13 : writeAttrs(attrs);
69 13 : output << " />";
70 13 : if (indent) output << "\n";
71 : }
72 :
73 :
74 : void XMLWriter::writeCharData(const string & data)
75 0 : {
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 : }
84 :
85 :
86 : void XMLWriter::writeAttrs(const XMLAttrs & attrs)
87 59 : {
88 82 : for (XMLAttrs::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
89 23 : output << " " << i->first << "=\"";
90 67 : for (unsigned int j = 0; j < i->second.size(); ++j) {
91 44 : char c = i->second[j];
92 44 : if (c == '"') output << """;
93 44 : else if (c == '<') output << "<";
94 44 : else if (c == '&') output << "&";
95 : /* Escape newlines to prevent attribute normalisation (see
96 : XML spec, section 3.3.3. */
97 44 : else if (c == '\n') output << "
";
98 44 : else output << c;
99 : }
100 23 : output << "\"";
101 : }
102 : }
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 121 : }
|