#include "image_io/xml/xml_writer.h" #include #include namespace photos_editing_formats { namespace image_io { using std::ostream; using std::string; using std::vector; namespace { const char kXmlnsColon[] = "xmlns:"; } // namespace XmlWriter::XmlWriter(std::ostream& os) : os_(os), element_count_(0), quote_mark_('"') {} void XmlWriter::WriteXmlns(const string& prefix, const string& uri) { string name = string(kXmlnsColon) + prefix; WriteAttributeNameAndValue(name, uri, true); } size_t XmlWriter::StartWritingElement(const string& element_name) { MaybeWriteCloseBracket(true); size_t current_depth = element_data_.size(); if (current_depth > 0) { element_data_.back().has_children = true; } element_data_.emplace_back(element_name); os_ << indent_ << "<" << element_name; indent_ += " "; element_count_ += 1; return current_depth; } void XmlWriter::FinishWritingElement() { if (!element_data_.empty()) { if (indent_.size() >= 2) { indent_.resize(indent_.size() - 2); } auto& data = element_data_.back(); if (!data.has_content && !data.has_children) { if (!data.has_attributes || data.has_children) { os_ << indent_; } os_ << "/>" << std::endl; } else { if (!data.has_content) { os_ << indent_; } os_ << "" << std::endl; } element_data_.pop_back(); } } void XmlWriter::FinishWritingElementsToDepth(size_t depth) { if (!element_data_.empty()) { for (size_t index = element_data_.size(); index > depth; --index) { FinishWritingElement(); } } } size_t XmlWriter::StartWritingElements(const vector& element_names) { size_t current_depth = element_data_.size(); for (const auto& element_name : element_names) { StartWritingElement(element_name); } return current_depth; } void XmlWriter::WriteElementAndContent(const string& element_name, const string& content) { StartWritingElement(element_name); WriteContent(content); FinishWritingElement(); } void XmlWriter::WriteContent(const string& content) { MaybeWriteCloseBracket(false); if (!element_data_.empty()) { auto& data = element_data_.back(); data.has_content = true; os_ << content; } } void XmlWriter::WriteAttributeNameAndValue(const string& name, const string& value, bool add_quote_marks) { WriteAttributeName(name); WriteAttributeValue(add_quote_marks, value, add_quote_marks); } void XmlWriter::WriteAttributeName(const string& name) { if (!element_data_.empty()) { os_ << std::endl << indent_ << name << "="; element_data_.back().has_attributes = true; } } void XmlWriter::WriteAttributeValue(bool add_leading_quote_mark, const string& value, bool add_trailing_quote_mark) { if (!element_data_.empty()) { if (add_leading_quote_mark) os_ << quote_mark_; os_ << value; if (add_trailing_quote_mark) os_ << quote_mark_; } } void XmlWriter::WriteComment(const std::string& comment) { MaybeWriteCloseBracket(true); os_ << indent_ << "" << std::endl; if (!element_data_.empty()) { auto& data = element_data_.back(); data.has_children = true; } } bool XmlWriter::MaybeWriteCloseBracket(bool with_trailing_newline) { if (!element_data_.empty()) { auto& data = element_data_.back(); if (!data.has_content && !data.has_children) { os_ << ">"; if (with_trailing_newline) { os_ << std::endl; } return true; } } return false; } } // namespace image_io } // namespace photos_editing_formats