00001
00002
00003 #include "cheprep/config.h"
00004
00005 #include <cstdio>
00006
00007 #include "cheprep/DefaultHepRepAttValue.h"
00008 #include "cheprep/XMLWriter.h"
00009
00010 using namespace std;
00011
00016 namespace cheprep {
00017
00018 XMLWriter::XMLWriter(ostream* out, string indentString, string aDefaultNameSpace)
00019 : AbstractXMLWriter(aDefaultNameSpace) {
00020 writer = new IndentPrintWriter(out);
00021 writer->setIndentString(indentString);
00022 closed = false;
00023 dtdName = "";
00024 }
00025
00026 XMLWriter::~XMLWriter() {
00027 writer->close();
00028 delete writer;
00029 }
00030
00031 void XMLWriter::close() {
00032 closeDoc();
00033 writer->close();
00034 }
00035
00036 void XMLWriter::openDoc(string version, string encoding, bool standalone) {
00037 string indentString = writer->getIndentString();
00038 writer->setIndentString(indentString);
00039
00040
00041 *writer << "<?xml version=\"" << version.c_str() << "\" ";
00042 if (encoding.compare("") != 0) {
00043
00044 *writer << "encoding=\"" << encoding.c_str() << "\" ";
00045 }
00046 if (standalone) {
00047 *writer << "standalone=\"yes\" ";
00048 }
00049 *writer << "?>";
00050 *writer << endl;
00051 writer->setIndentString(indentString);
00052 }
00053
00054 void XMLWriter::referToDTD(string name, string pid, string ref) {
00055 if (dtdName != "") {
00056 cerr << "XMLWriter::ReferToDTD cannot be called twice" << endl;
00057 }
00058 dtdName = name;
00059 *writer << "<!DOCTYPE " << name.c_str() << " PUBLIC \"" << pid.c_str() << "\" \"" << ref.c_str() << "\">" << endl;
00060 }
00061
00062 void XMLWriter::referToDTD(string name, string system) {
00063 if (dtdName != "") {
00064 cerr << "XMLWriter::ReferToDTD cannot be called twice";
00065 }
00066 dtdName = name;
00067 *writer << "<!DOCTYPE " << name.c_str() << " SYSTEM \"" << system.c_str() << "\">" << endl;
00068 }
00069
00070 void XMLWriter::closeDoc(bool force) {
00071 if (!closed) {
00072 if (!openTags.empty()) {
00073 if (!force) cerr << "Not all tags were closed before closing XML document:" << endl;
00074 while (!openTags.empty()) {
00075 if (force) {
00076 closeTag();
00077 } else {
00078 cerr << " </" << openTags.top().c_str() << ">" << endl;
00079 openTags.pop();
00080 }
00081 }
00082 }
00083 closed = true;
00084 }
00085 }
00086
00087 void XMLWriter::printComment(string comment) {
00088 if (comment.find("--") != string::npos) {
00089 cerr << "XMLWriter::printComment '--' sequence not allowed in comment" << endl;
00090 }
00091 *writer << "<!--" << normalizeText(comment).c_str() << "-->" << endl;
00092 }
00093
00094 void XMLWriter::printPlain(string text) {
00095 *writer << text.c_str();
00096 }
00097
00098 void XMLWriter::print(string text) {
00099 *writer << normalizeText(text).c_str();
00100 }
00101
00102 void XMLWriter::println(string text) {
00103 print(text);
00104 *writer << endl;
00105 }
00106
00107 void XMLWriter::openTag(string name) {
00108 checkNameValid(name);
00109 if (openTags.empty() && dtdName.compare("") && dtdName.compare(name)) {
00110 cerr << "XMLWriter::openTag(), First tag: '" << name << "' not equal to DTD id: '" << dtdName << "'" << endl;
00111 }
00112 *writer << "<" << name.c_str();
00113 printAttributes(name.length());
00114 *writer << ">" << endl;
00115 writer->indent();
00116 openTags.push(name);
00117 }
00118
00119 void XMLWriter::closeTag() {
00120 if (openTags.empty()) {
00121 writer->close();
00122 cerr << "XMLWriter::closeTag(), No open tags" << endl;
00123 }
00124 string name = openTags.top();
00125 openTags.pop();
00126 writer->outdent();
00127 *writer << "</" << name.c_str() << ">" << endl;
00128 }
00129
00130 void XMLWriter::printTag(string name) {
00131 checkNameValid(name);
00132 *writer << "<" << name.c_str();
00133 printAttributes(name.length());
00134 *writer << "/>" << endl;
00135 }
00136
00137 void XMLWriter::setAttribute(string name, char* value) {
00138 setAttribute(name, (string)value);
00139 }
00140
00141 void XMLWriter::setAttribute(string name, string value) {
00142 attributes[name] = value;
00143
00144 }
00145
00146 void XMLWriter::setAttribute(std::string name, std::vector<double> value) {
00147 if (name == "value") setAttribute("type", (std::string)"Color");
00148 setAttribute(name, DefaultHepRepAttValue::getAsString(value));
00149 }
00150
00151 void XMLWriter::setAttribute(std::string name, int64 value) {
00152 if (name == "value") setAttribute("type", (std::string)"long");
00153 setAttribute(name, DefaultHepRepAttValue::getAsString(value));
00154 }
00155
00156 void XMLWriter::setAttribute(std::string name, int value) {
00157 if (name == "showlabel") {
00158 string label = DefaultHepRepAttValue::toShowLabel(value);
00159 setAttribute("showlabel", label);
00160 } else {
00161 if (name == "value") setAttribute("type", (std::string)"int");
00162 setAttribute(name, DefaultHepRepAttValue::getAsString(value));
00163 }
00164 }
00165
00166 void XMLWriter::setAttribute(std::string name, bool value) {
00167 if (name == "value") setAttribute("type", (std::string)"boolean");
00168 setAttribute(name, DefaultHepRepAttValue::getAsString(value));
00169 }
00170
00171 void XMLWriter::setAttribute(string name, double value) {
00172 if (name == "value") setAttribute("type", (std::string)"double");
00173 setAttribute(name, DefaultHepRepAttValue::getAsString(value));
00174 }
00175
00176 void XMLWriter::printAttributes(int tagLength) {
00177 int width = tagLength + 1;
00178 bool extraIndent = false;
00179 for (map<string,string>::iterator i = attributes.begin(); i != attributes.end(); i++) {
00180 string key = i->first;
00181 checkNameValid(key);
00182 string value = normalize(i->second);
00183 int length = key.length() + value.length() + 3;
00184 if (width > 0 && width + length + 2*writer->getIndent() > 60) {
00185 width = 0;
00186 *writer << endl;
00187 if (!extraIndent) {
00188 writer->indent();
00189 extraIndent = true;
00190 }
00191 } else {
00192 width += length;
00193 *writer << " ";
00194 }
00195 *writer << key.c_str() << "=\"" << value.c_str() << "\"";
00196 }
00197 attributes.clear();
00198 if (extraIndent) writer->outdent();
00199 }
00200
00201 string XMLWriter::normalize(string s) {
00202 string str = "";
00203 char buffer[20];
00204
00205 int len = s.length();
00206 for (int i = 0; i < len; i++) {
00207 char ch = s[i];
00208 switch (ch) {
00209 case '<': {
00210 str.append("<");
00211 break;
00212 }
00213 case '>': {
00214 str.append(">");
00215 break;
00216 }
00217 case '&': {
00218 str.append("&");
00219 break;
00220 }
00221 case '"': {
00222 str.append(""");
00223 break;
00224 }
00225 case '\r':
00226 case '\n': {
00227 sprintf(buffer, "&#%ud", ch);
00228 str.append(buffer);
00229 str.append(";");
00230 break;
00231 }
00232 default: {
00233
00234
00235
00236
00237
00238 str.append(&ch, 1);
00239
00240 }
00241 }
00242 }
00243
00244 return str;
00245 }
00246
00247 string XMLWriter::normalizeText(string s) {
00248 string str = "";
00249
00250 int len = s.length();
00251 for (int i = 0; i < len; i++) {
00252 char ch = s[i];
00253 switch (ch) {
00254 case '<': {
00255 str.append("<");
00256 break;
00257 }
00258 case '>': {
00259 str.append(">");
00260 break;
00261 }
00262 case '&': {
00263 str.append("&");
00264 break;
00265 }
00266 default: {
00267
00268
00269
00270
00271
00272 str.append(&ch, 1);
00273
00274 }
00275 }
00276 }
00277 return str;
00278 }
00279
00280 void XMLWriter::checkNameValid(string) {
00281
00282
00283 }
00284
00285
00286 }