/*! \brief Main insertion operator which changes the state of the * XmlStream. */ inline XmlStream& operator<<(const Controller& controller) { switch (controller._type) { case Controller::Prolog: if (!prologWritten && stateNone == state) { s << "<?xml version=\"" << versionMajor << '.' << versionMinor << "\"?>\n"; prologWritten = true; } break; case Controller::Tag: closeTagStart(); for (size_t i(0); i < tags.size(); ++i) s << " "; s << '<' << controller.str; tags.push(controller.str); state = stateTag; break; case Controller::TagEnd: endTag(controller.str); break; case Controller::Attribute: switch (state) { case stateTagName: tags.push(tagName.str()); break; case stateAttribute: s << '\"'; default: break; } if (stateNone != state) { s << ' ' << controller.str << "=\""; state = stateAttribute; } break;//Controller::whatAttribute case Controller::CharData: closeTagStart(); state = stateNone; break;//Controller::whatCharData } return *this; }
// Close tag (may be with closing all of its children) void XmlStream::endTag(const string_type& tag) { bool brk = false; while (tags.size() > 0 && !brk) { if (stateNone == state) { startTagging(); s << "</" << tags.top() << '>'; endTagging(); } else { closeTagStart(true); state = stateNone; } brk = tag.empty() || tag == tags.top(); tags.pop(); } }
//! \brief Closes the named tag and may close all of its children. inline void endTag(const std::string& tag) { bool brk = false; while (tags.size() > 0 && !brk) { if (stateNone == state) { for (size_t i(1); i < tags.size(); ++i) s << " "; s << "</" << tags.top() << ">\n"; } else { closeTagStart(true); state = stateNone; } brk = tag.empty() || tag == tags.top(); tags.pop(); } }
// this is the main working horse // and it's long a little XmlStream& XmlStream::operator<<(const Controller& controller) { switch (controller.what) { case Controller::whatProlog: if (!prologWritten && stateNone == state) { startTagging(); s << "<?xml version=\"" << versionMajor << '.' << versionMinor; if (!encoding.empty()) s << "\" encoding=\"" << encoding; s << "\"?>\n"; endTagging(); prologWritten = true; } break; // Controller::whatProlog case Controller::whatTag: closeTagStart(); startTagging(); s << '<'; if (controller.str.empty()) { clearTagName(); state = stateTagName; } else { s << controller.str; tags.push(controller.str); state = stateTag; } endTagging(); break; // Controller::whatTag case Controller::whatTagEnd: endTag(controller.str); break; // Controller::whatTagEnd case Controller::whatAttribute: switch (state) { case stateTagName: tags.push(tagName.str()); break; case stateAttribute: startTagging(); s << '\"'; endTagging(); default: break; } if (stateNone != state) { startTagging(); s << ' ' << controller.str << "=\""; endTagging(); state = stateAttribute; } // else throw some error - unexpected attribute (out of any tag) break; // Controller::whatAttribute case Controller::whatCharData: closeTagStart(); state = stateNone; break; // Controller::whatCharData default: break; } return *this; }