| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef TOOLS_GN_XML_ELEMENT_WRITER_H_ |
| #define TOOLS_GN_XML_ELEMENT_WRITER_H_ |
| |
| #include <memory> |
| #include <ostream> |
| #include <string> |
| #include <string_view> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/macros.h" |
| |
| // Vector of XML attribute key-value pairs. |
| class XmlAttributes |
| : public std::vector<std::pair<std::string_view, std::string_view>> { |
| public: |
| XmlAttributes(); |
| XmlAttributes(const std::string_view& attr_key, |
| const std::string_view& attr_value); |
| |
| XmlAttributes& add(const std::string_view& attr_key, |
| const std::string_view& attr_value); |
| }; |
| |
| // Helper class for writing XML elements. New XML element is started in |
| // XmlElementWriter constructor and ended in its destructor. XmlElementWriter |
| // handles XML file formatting in order to produce human-readable document. |
| class XmlElementWriter { |
| public: |
| // Starts new XML element. This constructor adds no indentation and is |
| // designed for XML root element. |
| XmlElementWriter(std::ostream& out, |
| const std::string& tag, |
| const XmlAttributes& attributes); |
| // Starts new XML element with specified indentation. |
| XmlElementWriter(std::ostream& out, |
| const std::string& tag, |
| const XmlAttributes& attributes, |
| int indent); |
| // Starts new XML element with specified indentation. Specialized constructor |
| // that allows writting XML element with single attribute without copying |
| // attribute value. |
| template <class Writer> |
| XmlElementWriter(std::ostream& out, |
| const std::string& tag, |
| const std::string& attribute_name, |
| const Writer& attribute_value_writer, |
| int indent); |
| // Ends XML element. All sub-elements should be ended at this point. |
| ~XmlElementWriter(); |
| |
| // Writes arbitrary XML element text. |
| void Text(const std::string_view& content); |
| |
| // Starts new XML sub-element. Caller must ensure that parent element outlives |
| // its children. |
| std::unique_ptr<XmlElementWriter> SubElement(const std::string& tag); |
| std::unique_ptr<XmlElementWriter> SubElement(const std::string& tag, |
| const XmlAttributes& attributes); |
| template <class Writer> |
| std::unique_ptr<XmlElementWriter> SubElement( |
| const std::string& tag, |
| const std::string& attribute_name, |
| const Writer& attribute_value_writer); |
| |
| // Finishes opening tag if it isn't finished yet and optionally starts new |
| // document line. Returns the stream where XML element content can be written. |
| // This is an alternative to Text() and SubElement() methods. |
| std::ostream& StartContent(bool start_new_line); |
| |
| private: |
| // Output stream. XmlElementWriter objects for XML element and its |
| // sub-elements share the same output stream. |
| std::ostream& out_; |
| |
| // XML element tag name. |
| std::string tag_; |
| |
| // XML element indentation in the document. |
| int indent_; |
| |
| // Flag indicating if opening tag is finished with '>' character already. |
| bool opening_tag_finished_; |
| |
| // Flag indicating if XML element should be written in one document line. |
| bool one_line_; |
| |
| DISALLOW_COPY_AND_ASSIGN(XmlElementWriter); |
| }; |
| |
| template <class Writer> |
| XmlElementWriter::XmlElementWriter(std::ostream& out, |
| const std::string& tag, |
| const std::string& attribute_name, |
| const Writer& attribute_value_writer, |
| int indent) |
| : out_(out), |
| tag_(tag), |
| indent_(indent), |
| opening_tag_finished_(false), |
| one_line_(true) { |
| out << std::string(indent, ' ') << '<' << tag; |
| out << ' ' << attribute_name << "=\""; |
| attribute_value_writer(out); |
| out << '\"'; |
| } |
| |
| template <class Writer> |
| std::unique_ptr<XmlElementWriter> XmlElementWriter::SubElement( |
| const std::string& tag, |
| const std::string& attribute_name, |
| const Writer& attribute_value_writer) { |
| StartContent(true); |
| return std::make_unique<XmlElementWriter>( |
| out_, tag, attribute_name, attribute_value_writer, indent_ + 2); |
| } |
| |
| std::string XmlEscape(const std::string& value); |
| |
| #endif // TOOLS_GN_XML_ELEMENT_WRITER_H_ |