Blame view

src/TimeTableCatalog/XMLWriter.cc 5.24 KB
fbe3c2bb   Benjamin Renard   First commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
 * XMLWriter.cc
 *
 *  Created on: 7 août 2013
 *      Author: CS
 */

#include "XMLWriter.hh"
#include <libxml/encoding.h>
#include <cstring>

namespace TimeTableCatalog {

XMLWriter::XMLWriter(const std::string& pPath, const std::string& pName) :
		AbstractWriter(pPath, pName) {
}

XMLWriter::~XMLWriter() {
}
// ----------------- PUBLIC --------------------------

std::string XMLWriter::write(const TimeTable& pTT, const char* pEncoding) {

	/*
	 * this initialize the library and check potential ABI mismatches
	 * between the version it was compiled for and the actual shared
	 * library used.
	 */
	LIBXML_TEST_VERSION

	xmlTextWriterPtr writer;

	// -- create a new XmlWriter for uri, with no compression.
	std::string filePath = getFile(pTT);
	writer = xmlNewTextWriterFilename(filePath.c_str(), 0);
	if (writer == NULL) {
		LOG4CXX_WARN(logger, "Error creating the xml writer");
		return "";
	}

	// -- write <?xml ... line
	writeHeader(pTT, writer, pEncoding);

	writeContent(pTT, writer);

	xmlFreeTextWriter(writer);

	// -- cleanup function for the XML library.
	//cf. http://xmlsoft.org/html/libxml-parser.html#xmlCleanupParser
	//xmlCleanupParser();

	return filePath;
}

// -------------------- PROTECTED --------------------------

void XMLWriter::writeHeader(const TimeTable& pTT, xmlTextWriterPtr& writer,
		const char* pEncoding) {
	int rc;
	/* Start the document with the xml default for the version,
	 * encoding UTF-8 and the default for the standalone
	 * declaration. */
	rc = xmlTextWriterStartDocument(writer, "1.0", pEncoding, NULL);
	if (rc < 0) {
		LOG4CXX_WARN(logger, "Error while writing header for " + getFile(pTT));
		return;
	}
}

void XMLWriter::writeElement(const TimeTable& pTT, xmlTextWriterPtr& pWriter,
		std::string pTag, const std::string & pValue, const char* pEncoding) {
	int rc;
	xmlChar *tmp = convertInput(pTT, pValue.c_str(), pEncoding);

	// -- add element named "name" as child of timetable
	rc = xmlTextWriterWriteElement(pWriter, BAD_CAST pTag.c_str(), tmp);
	if (rc < 0) {
		logTagError(pTag, getFile(pTT));
		return;
	}
	if (tmp != NULL)
		xmlFree(tmp);
}

/**
 * Writes a start tag.
 */
void XMLWriter::openTag(const TimeTable& pTT, xmlTextWriterPtr& pWriter, std::string pTag) {
	int rc = xmlTextWriterStartElement(pWriter, BAD_CAST pTag.c_str());
	if (rc < 0) {
		logStartTagError(pTag, getFile(pTT));
		return;
	}
}

/**
 * Adds an attribute to the current tag.
 */
void XMLWriter::addAttribute(const TimeTable& pTT, xmlTextWriterPtr& pWriter,
		std::string pAttribute, const std::string &pValue,
		const char* pEncoding) {

	xmlChar *tmp = convertInput(pTT, pValue.c_str(), pEncoding);
	int rc = xmlTextWriterWriteAttribute(pWriter, BAD_CAST pAttribute.c_str(),
			tmp);
	if (rc < 0) {
		logAttributeError(pAttribute, getFile(pTT));
		return;
	}
	if (tmp != NULL)
		xmlFree(tmp);
}

/**
 * Writes a stop tag.
 */
void XMLWriter::closeTag(const TimeTable& pTT, xmlTextWriterPtr& pWriter, std::string pTag) {
	int rc = xmlTextWriterEndElement(pWriter);
	if (rc < 0) {
c6a67968   Benjamin Renard   Fix some violatio...
120
		logEndTagError(pTag, getFile(pTT));
fbe3c2bb   Benjamin Renard   First commit
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
		return;
	}
}

/**
 * ConvertInput:
 * @in: string in a given encoding
 * @encoding: the encoding used
 *
 * Converts @in into UTF-8 for processing with libxml2 APIs
 *
 * Returns the converted UTF-8 string, or NULL in case of error.
 */
xmlChar * XMLWriter::convertInput(const TimeTable& pTT, const char *in,
		const char *encoding) {
	xmlChar *out;
	int size;
	int out_size;
	int temp;
	xmlCharEncodingHandlerPtr handler;

	if (in == 0)
		return 0;

	handler = xmlFindCharEncodingHandler(encoding);

	if (!handler) {
		LOG4CXX_WARN(logger,
				"Error while converting : no encoding handler found for "
						+ std::string(encoding) + " for " + getFile(pTT));
		return 0;
	}

	size = (int) strlen(in) + 1;
	out_size = size * 2 - 1;
	out = (unsigned char *) xmlMalloc((size_t) out_size);

	if (out != 0) {
		temp = size - 1;
		int ret = handler->input(out, &out_size, (const xmlChar *) in, &temp);
		if ((ret < 0) || (temp - size + 1)) {
			if (ret < 0) {
				LOG4CXX_WARN(logger,
						"Error while converting : converting failed for "
								+ getFile(pTT));
			} else {
				std::ostringstream os;
				os << temp;
				LOG4CXX_WARN(logger,
						"Error while converting : converting failed ("
								+ os.str() + " octets) for " + getFile(pTT));
			}

			xmlFree(out);
			out = 0;
		} else {
			out = (unsigned char *) xmlRealloc(out, out_size + 1);
			out[out_size] = 0; /*null terminating out */
		}
	} else {
		LOG4CXX_WARN(logger, "Error while converting : no mem for " + getFile(pTT));
	}

	return out;
}

void XMLWriter::logEndTagError(const std::string& pTag,
		const std::string& pTTPath) {
	LOG4CXX_WARN(logger,
			"Error while writing end of " + pTag + " element for " + pTTPath);
}
void XMLWriter::logStartTagError(const std::string& pTag,
		const std::string& pTTPath) {
	LOG4CXX_WARN(logger,
			"Error while writing start of " + pTag + "element for " + pTTPath);
}
void XMLWriter::logTagError(const std::string& pTag,
		const std::string& pTTPath) {
	LOG4CXX_WARN(logger,
			"Error while writing tag " + pTag + "element for " + pTTPath);
}
void XMLWriter::logAttributeError(const std::string& pAttribute,
		const std::string& pTTPath) {
	LOG4CXX_WARN(logger,
			"Error while writing attribute " + pAttribute + "element for "
					+ pTTPath);
}

} /* namespace TimeTableCatalog */