// // FILE: XMLWriter.cpp // AUTHOR: Rob Tillaart // VERSION: 0.1.06 // DATE: 2013-11-06 // PURPOSE: Simple XML library // // HISTORY: // 0.1.00 - 2013-11-06 initial version // 0.1.01 - 2013-11-07 rework interfaces // 0.1.02 - 2013-11-07 +setIndentSize(), corrected history, +escape support // 0.1.03 - 2015-03-07 refactored - footprint + interface // 0.1.04 - 2015-05-21 refactored - reduce RAM -> used F() macro etc. // 0.1.05 - 2015-05-23 added XMLWRITER_MAXTAGSIZE 15 (to support KML coordinates tag) // 0.1.06 - 2016-03-16 added incrIndent(), decrIndent(), indent(), raw(); // // Released to the public domain // #include XMLWriter::XMLWriter(Print* stream) { _stream = stream; reset(); } void XMLWriter::reset() { _indent = 0; _indentStep = 2; _idx = 0; } void XMLWriter::header() { _stream->println(F("")); } void XMLWriter::comment(char* text, bool multiLine) { _stream->println(); if (!multiLine) indent(); _stream->print(F("")); } void XMLWriter::tagOpen(char* tag, bool newline) { tagOpen(tag, "", newline); } void XMLWriter::tagOpen(char* tag, char* name, bool newline) { // TODO STACK GUARD strncpy(tagStack[_idx++], tag, XMLWRITER_MAXTAGSIZE); tagStart(tag); if (name[0] != 0) tagField("name", name); tagEnd(newline, NOSLASH); _indent += _indentStep; } void XMLWriter::tagClose(bool ind) { _indent -= _indentStep; if (ind) indent(); _stream->print(F("print(tagStack[--_idx]); _stream->println(F(">")); } void XMLWriter::tagStart(char *tag) { indent(); _stream->print('<'); _stream->print(tag); } void XMLWriter::tagField(char *field, char* str) { _stream->print(' '); _stream->print(field); _stream->print(F("=\"")); #ifdef XMLWRITER_ESCAPE_SUPPORT escape(str); #else _stream->print(str); #endif _stream->print('"'); } void XMLWriter::tagEnd(bool newline, bool addSlash) { if (addSlash) _stream->print('/'); _stream->print('>'); if (newline) _stream->println(); } void XMLWriter::writeNode(char* tag, char* str) { tagOpen(tag, "", NONEWLINE); #ifdef XMLWRITER_ESCAPE_SUPPORT escape(str); #else _stream->print(str); #endif tagClose(NOINDENT); } void XMLWriter::setIndentSize(uint8_t size) { _indentStep = size; } void XMLWriter::tagField(char *field, uint8_t value, uint8_t base) { tagField(field, (uint32_t) value, base); } void XMLWriter::tagField(char *field, uint16_t value, uint8_t base) { tagField(field, (uint32_t) value, base); } void XMLWriter::tagField(char *field, uint32_t value, uint8_t base) { _stream->print(' '); _stream->print(field); _stream->print(F("=\"")); _stream->print(value, base); _stream->print('"'); } void XMLWriter::tagField(char *field, int8_t value, uint8_t base) { tagField(field, (long) value, base); } void XMLWriter::tagField(char *field, int16_t value, uint8_t base) { tagField(field, (long) value, base); } void XMLWriter::tagField(char *field, int32_t value, uint8_t base) { _stream->print(' '); _stream->print(field); _stream->print(F("=\"")); _stream->print(value, base); _stream->print('"'); } void XMLWriter::tagField(char *field, bool value) { _stream->print(' '); _stream->print(field); _stream->print(F("=\"")); _stream->print(value?F("true"):F("false")); _stream->print('"'); } void XMLWriter::tagField(char *field, double value, uint8_t decimals) { _stream->print(' '); _stream->print(field); _stream->print(F("=\"")); _stream->print(value, decimals); _stream->print('"'); } void XMLWriter::writeNode(char* tag, uint8_t value, uint8_t base) { writeNode(tag, (uint32_t) value, base); } void XMLWriter::writeNode(char* tag, uint16_t value, uint8_t base) { writeNode(tag, (uint32_t) value, base); } void XMLWriter::writeNode(char* tag, uint32_t value, uint8_t base) { tagOpen(tag, "", NONEWLINE); _stream->print(value, base); // todo: leading zero's tagClose(NOINDENT); } void XMLWriter::writeNode(char* tag, int8_t value, uint8_t base) { writeNode(tag, (int32_t) value, base); } void XMLWriter::writeNode(char* tag, int16_t value, uint8_t base) { writeNode(tag, (int32_t) value, base); } void XMLWriter::writeNode(char* tag, int32_t value, uint8_t base) { tagOpen(tag, "", NONEWLINE); _stream->print(value, base); // todo: leading zero's tagClose(NOINDENT); } void XMLWriter::writeNode(char* tag, bool value) { tagOpen(tag, "", NONEWLINE); _stream->print(value?F("true"):F("false")); tagClose(NOINDENT); } void XMLWriter::writeNode(char* tag, double value, uint8_t decimals) { tagOpen(tag, "", NONEWLINE); _stream->print(value, decimals); tagClose(NOINDENT); } void XMLWriter::indent() { for (uint8_t i=_indent; i>0; i--) _stream->print(' '); } //////////////////////////////////////////////////////////////////// #ifdef XMLWRITER_ESCAPE_SUPPORT char c[6] = "\"\'<>&"; char expanded[][7] = { """, "'","<",">","&"}; // todo in flash void XMLWriter::escape(char* str) { char* p = str; while(*p != 0) { char* q = strchr(c, *p); if (q == NULL) _stream->print(*p); else _stream->print(expanded[q - c]); // uint8_t idx = q-c; p++; } } #endif // END OF FILE