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