#include #define APPEND_NEWLINE \ if (_useNewlines) { \ ZStringAlgo::Append(_output, LINE_TERMINATOR); \ } \ const ZString& ZXMLWriter::GetErrorString() { return ErrorMessage; } bool ZXMLWriter::writeAttributes(ZString& _output, const ZKVTree::Iterator& _itr) { bool found_sub = false; // indicates we have sub-elements for (size_t i = 0; i < _itr.GetChildCount(); i++) { const ZKVTree::Iterator itr = _itr.ChildItr(i); if (itr.GetChildCount() > 0) { // attributes have no children found_sub = true; continue; } const ZString& name = itr.GetName(); // attrib name const ZString& val = itr.GetValue(); // attrib value _output.PushBack(' '); // start with a space ZStringAlgo::Append(_output, name); // append attribute name _output.PushBack('='); // equals _output.PushBack('\"'); // escaped quote ZStringAlgo::Append(_output, val); // attribute value _output.PushBack('\"'); // escaped quote } return found_sub; } bool ZXMLWriter::writeElements(ZString& _output, bool _useNewlines, const ZKVTree::Iterator& _itr) { if (_itr.GetChildCount() == 0) { // indicates an attribute return true; } const ZString& name = _itr.GetName(); // element name const ZString& val = _itr.GetValue(); // element value _output.PushBack('<'); // open tag ZStringAlgo::Append(_output, name); // element name bool found_sub = writeAttributes(_output, _itr); // write all attributes if (val.Empty() && !found_sub) { // close the tag, no body, no sub-elements _output.PushBack('/'); _output.PushBack('>'); APPEND_NEWLINE; } else { // keep tag open for sub-elements and body _output.PushBack('>'); APPEND_NEWLINE; // write all sub-elements (this does nothing on an attribute) for (size_t i = 0; i < _itr.GetChildCount(); i++) { writeElements(_output, _useNewlines, _itr.ChildItr(i)); } if (!val.Empty()) { ZStringAlgo::Append(_output, val); // write element body APPEND_NEWLINE; } _output.PushBack('<'); // closing tag begin _output.PushBack('/'); ZStringAlgo::Append(_output, name); _output.PushBack('>'); // closing tag end APPEND_NEWLINE; } return true; } bool ZXMLWriter::Write( const ZKVTree& _input, ZString& _output, bool _useNewlines ) { ZKVTree::Iterator itr = _input.Begin(); if (itr == _input.End()) { ErrorMessage = "ZXMLWriter: key value tree has no data!"; return false; } return writeElements(_output, _useNewlines, itr); }