source: trunk/source/visualization/HepRep/src/XMLWriter.cc @ 1098

Last change on this file since 1098 was 834, checked in by garnier, 16 years ago

import all except CVS

File size: 8.1 KB
Line 
1// Copyright FreeHEP, 2005.
2
3#include "cheprep/config.h"
4
5#include <cstdio>
6
7#include "cheprep/DefaultHepRepAttValue.h"
8#include "cheprep/XMLWriter.h"
9
10using namespace std;
11
12/**
13 * @author Mark Donszelmann
14 * @version $Id: XMLWriter.cc,v 1.12 2005/06/02 21:28:45 duns Exp $
15 */
16namespace cheprep {
17
18XMLWriter::XMLWriter(ostream* out, string indentString, string defaultNameSpace)
19    : AbstractXMLWriter(defaultNameSpace) {
20    writer = new IndentPrintWriter(out);
21    writer->setIndentString(indentString);
22    closed = false;
23    dtdName = "";
24}
25
26XMLWriter::~XMLWriter() {
27    writer->close();
28    delete writer;
29}
30
31void XMLWriter::close() {
32    closeDoc();
33    writer->close();
34}
35
36void XMLWriter::openDoc(string version, string encoding, bool standalone) {
37    string indentString = writer->getIndentString();
38    writer->setIndentString(indentString);
39
40//    if (!XMLCharacterProperties.validVersionNum(version)) throw new RuntimeException("Invalid version number: "+version);
41    *writer << "<?xml version=\"" << version.c_str() << "\" ";
42    if (encoding.compare("") != 0) {
43//        if (!XMLCharacterProperties.validEncName(encoding)) throw new RuntimeException("Invalid encoding name: "+encoding);
44        *writer << "encoding=\"" << encoding.c_str() << "\" ";
45    }
46    if (standalone) {
47        *writer << "standalone=\"yes\" ";
48    }
49    *writer << "?>";
50    *writer << endl;
51    writer->setIndentString(indentString);
52}
53
54void XMLWriter::referToDTD(string name, string pid, string ref) {
55    if (dtdName != "") {
56        cerr << "XMLWriter::ReferToDTD cannot be called twice" << endl;
57    }
58    dtdName = name;
59    *writer << "<!DOCTYPE " << name.c_str() << " PUBLIC \"" << pid.c_str() << "\" \"" << ref.c_str() << "\">" << endl;
60}
61
62void XMLWriter::referToDTD(string name, string system) {
63    if (dtdName != "") {
64        cerr << "XMLWriter::ReferToDTD cannot be called twice";
65    }
66    dtdName = name;
67    *writer << "<!DOCTYPE " << name.c_str() << " SYSTEM \"" << system.c_str() << "\">" << endl;
68}
69
70void XMLWriter::closeDoc(bool force) {
71    if (!closed) {
72        if (!openTags.empty()) {
73            if (!force) cerr << "Not all tags were closed before closing XML document:" << endl;
74            while (!openTags.empty()) {
75                if (force) {
76                    closeTag();
77                } else {
78                    cerr << "   </" << openTags.top().c_str() << ">" << endl;
79                    openTags.pop();
80                }
81            }
82        }
83        closed = true;
84    }
85}
86
87void XMLWriter::printComment(string comment) {
88    if (comment.find("--") != string::npos) {
89        cerr << "XMLWriter::printComment '--' sequence not allowed in comment" << endl;
90    }
91    *writer << "<!--" << normalizeText(comment).c_str() << "-->" << endl;
92}
93
94void XMLWriter::printPlain(string text) {
95    *writer << text.c_str();
96}
97
98void XMLWriter::print(string text) {
99    *writer << normalizeText(text).c_str();
100}
101
102void XMLWriter::println(string text) {
103    print(text);
104    *writer << endl;
105}
106
107void XMLWriter::openTag(string name) {
108    checkNameValid(name);
109    if (openTags.empty() && dtdName.compare("") && dtdName.compare(name)) {
110        cerr << "XMLWriter::openTag(), First tag: '" << name << "' not equal to DTD id: '" << dtdName << "'" << endl;
111    }
112    *writer << "<" << name.c_str();
113    printAttributes(name.length());
114    *writer << ">" << endl;
115    writer->indent();
116    openTags.push(name);
117}
118
119void XMLWriter::closeTag() {
120    if (openTags.empty()) {
121        writer->close();
122        cerr << "XMLWriter::closeTag(), No open tags" << endl;
123    }
124    string name = openTags.top();
125    openTags.pop();
126    writer->outdent();
127    *writer << "</" << name.c_str() << ">" << endl;
128}
129
130void XMLWriter::printTag(string name) {
131    checkNameValid(name);
132    *writer << "<" << name.c_str();
133    printAttributes(name.length());
134    *writer << "/>" << endl;
135}
136
137void XMLWriter::setAttribute(string name, char* value) {
138    setAttribute(name, (string)value);
139}
140
141void XMLWriter::setAttribute(string name, string value) {
142    attributes[name] = value;
143    // NOTE: never set type here
144}
145
146void XMLWriter::setAttribute(std::string name, std::vector<double> value) {
147    if (name == "value") setAttribute("type", (std::string)"Color");
148    setAttribute(name, DefaultHepRepAttValue::getAsString(value));
149}
150
151void XMLWriter::setAttribute(std::string name, int64 value) {
152    if (name == "value") setAttribute("type", (std::string)"long");
153    setAttribute(name, DefaultHepRepAttValue::getAsString(value));
154}
155
156void XMLWriter::setAttribute(std::string name, int value) {
157    if (name == "showlabel") {
158        string label = DefaultHepRepAttValue::toShowLabel(value);
159        setAttribute("showlabel", label);
160    } else {
161        if (name == "value") setAttribute("type", (std::string)"int");
162        setAttribute(name, DefaultHepRepAttValue::getAsString(value));
163    }
164}
165
166void XMLWriter::setAttribute(std::string name, bool value) {
167    if (name == "value") setAttribute("type", (std::string)"boolean");
168    setAttribute(name, DefaultHepRepAttValue::getAsString(value));
169}
170
171void XMLWriter::setAttribute(string name, double value) {
172    if (name == "value") setAttribute("type", (std::string)"double");
173    setAttribute(name, DefaultHepRepAttValue::getAsString(value));
174}
175
176void XMLWriter::printAttributes(int tagLength) {
177        int width = tagLength + 1;
178        bool extraIndent = false;
179        for (map<string,string>::iterator i = attributes.begin(); i != attributes.end(); i++) {
180                string key = i->first;
181                checkNameValid(key);
182                string value = normalize(i->second);
183                int length = key.length() + value.length() + 3;
184                if (width > 0 && width + length + 2*writer->getIndent() > 60) {
185                        width = 0;
186                        *writer << endl;
187                        if (!extraIndent) {
188                                writer->indent();
189                                extraIndent = true;
190                        }
191                } else {
192                        width += length;
193                        *writer << " ";
194                }
195                *writer << key.c_str() << "=\"" << value.c_str() << "\"";
196        }
197        attributes.clear();
198        if (extraIndent) writer->outdent();
199}
200
201string XMLWriter::normalize(string s) {
202    string str = "";
203    char buffer[20];
204
205    int len = s.length();
206    for (int i = 0; i < len; i++) {
207        char ch = s[i];
208        switch (ch) {
209            case '<': {
210                str.append("&lt;");
211                break;
212            }
213            case '>': {
214                str.append("&gt;");
215                break;
216            }
217            case '&': {
218                str.append("&amp;");
219                break;
220            }
221            case '"': {
222                str.append("&quot;");
223                break;
224            }
225            case '\r':
226            case '\n': {
227                sprintf(buffer, "&#%ud", ch);
228                str.append(buffer);
229                str.append(";");
230                break;
231            }
232            default: {
233//                if (ch > 0x00FF) {
234//                    sprintf(buffer, "&#x%4.4x", ch);
235//                    str.append(buffer);
236//                    str.append(";");
237//                } else {
238                    str.append(&ch, 1);
239//                }
240            }
241        }
242    }
243
244    return str;
245}
246
247string XMLWriter::normalizeText(string s) {
248    string str = "";
249
250    int len = s.length();
251    for (int i = 0; i < len; i++) {
252        char ch = s[i];
253        switch (ch) {
254            case '<': {
255                str.append("&lt;");
256                break;
257            }
258            case '>': {
259                str.append("&gt;");
260                break;
261            }
262            case '&': {
263                str.append("&amp;");
264                break;
265            }
266            default: {
267//                if (ch > 0x00FF) {
268//                    sprintf(buffer, "&#x%4.4x", ch);
269//                    str.append(buffer);
270//                    str.append(";");
271//                } else {
272                    str.append(&ch, 1);
273//                }
274            }
275        }
276    }
277    return str;
278}
279
280void XMLWriter::checkNameValid(string) {
281// Could be added.
282//    if (!XMLCharacterProperties.validName(s)) throw new RuntimeException("Invalid name: "+s);
283}
284
285
286} // cheprep
Note: See TracBrowser for help on using the repository browser.