1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef THIRD_PARTY_LIBXML_CHROMIUM_LIBXML_UTILS_H_ 6 #define THIRD_PARTY_LIBXML_CHROMIUM_LIBXML_UTILS_H_ 7 #pragma once 8 9 #include <string> 10 11 #include "libxml/xmlreader.h" 12 #include "libxml/xmlwriter.h" 13 14 // Converts a libxml xmlChar* into a UTF-8 std::string. 15 // NULL inputs produce an empty string. 16 std::string XmlStringToStdString(const xmlChar* xmlstring); 17 18 // libxml uses a global error function pointer for reporting errors. 19 // A ScopedXmlErrorFunc object lets you change the global error pointer 20 // for the duration of the object's lifetime. 21 class ScopedXmlErrorFunc { 22 public: 23 ScopedXmlErrorFunc(void* context, xmlGenericErrorFunc func) { 24 old_error_func_ = xmlGenericError; 25 old_error_context_ = xmlGenericErrorContext; 26 xmlSetGenericErrorFunc(context, func); 27 } 28 ~ScopedXmlErrorFunc() { 29 xmlSetGenericErrorFunc(old_error_context_, old_error_func_); 30 } 31 32 private: 33 xmlGenericErrorFunc old_error_func_; 34 void* old_error_context_; 35 }; 36 37 // XmlReader is a wrapper class around libxml's xmlReader, 38 // providing a simplified C++ API. 39 class XmlReader { 40 public: 41 XmlReader(); 42 ~XmlReader(); 43 44 // Load a document into the reader from memory. |input| must be UTF-8 and 45 // exist for the lifetime of this object. Returns false on error. 46 // TODO(evanm): handle encodings other than UTF-8? 47 bool Load(const std::string& input); 48 49 // Load a document into the reader from a file. Returns false on error. 50 bool LoadFile(const std::string& file_path); 51 52 // Wrappers around libxml functions ----------------------------------------- 53 54 // Read() advances to the next node. Returns false on EOF or error. 55 bool Read() { return xmlTextReaderRead(reader_) == 1; } 56 57 // Next(), when pointing at an opening tag, advances to the node after 58 // the matching closing tag. Returns false on EOF or error. 59 bool Next() { return xmlTextReaderNext(reader_) == 1; } 60 61 // Return the depth in the tree of the current node. 62 int Depth() { return xmlTextReaderDepth(reader_); } 63 64 // Returns the "local" name of the current node. 65 // For a tag like <foo:bar>, this is the string "foo:bar". 66 std::string NodeName() { 67 return XmlStringToStdString(xmlTextReaderConstLocalName(reader_)); 68 } 69 70 // When pointing at a tag, retrieves the value of an attribute. 71 // Returns false on failure. 72 // E.g. for <foo bar:baz="a">, NodeAttribute("bar:baz", &value) 73 // returns true and |value| is set to "a". 74 bool NodeAttribute(const char* name, std::string* value); 75 76 // Helper functions not provided by libxml ---------------------------------- 77 78 // Return the string content within an element. 79 // "<foo>bar</foo>" is a sequence of three nodes: 80 // (1) open tag, (2) text, (3) close tag. 81 // With the reader currently at (1), this returns the text of (2), 82 // and advances past (3). 83 // Returns false on error. 84 bool ReadElementContent(std::string* content); 85 86 // Skip to the next opening tag, returning false if we reach a closing 87 // tag or EOF first. 88 // If currently on an opening tag, doesn't advance at all. 89 bool SkipToElement(); 90 91 private: 92 // Returns the libxml node type of the current node. 93 int NodeType() { return xmlTextReaderNodeType(reader_); } 94 95 // The underlying libxml xmlTextReader. 96 xmlTextReaderPtr reader_; 97 }; 98 99 // XmlWriter is a wrapper class around libxml's xmlWriter, 100 // providing a simplified C++ API. 101 // StartWriting must be called before other methods, and StopWriting 102 // must be called before GetWrittenString() will return results. 103 class XmlWriter { 104 public: 105 XmlWriter(); 106 ~XmlWriter(); 107 108 // Allocates the xmlTextWriter and an xmlBuffer and starts an XML document. 109 // This must be called before any other functions. By default, indenting is 110 // set to true. 111 void StartWriting(); 112 113 // Ends the XML document and frees the xmlTextWriter. 114 // This must be called before GetWrittenString() is called. 115 void StopWriting(); 116 // Wrappers around libxml functions ----------------------------------------- 117 118 // All following elements will be indented to match their depth. 119 void StartIndenting() { xmlTextWriterSetIndent(writer_, 1); } 120 121 // All follow elements will not be indented. 122 void StopIndenting() { xmlTextWriterSetIndent(writer_, 0); } 123 124 // Start an element with the given name. All future elements added will be 125 // children of this element, until it is ended. Returns false on error. 126 bool StartElement(const std::string& element_name) { 127 return xmlTextWriterStartElement(writer_, 128 BAD_CAST element_name.c_str()) >= 0; 129 } 130 131 // Ends the current open element. Returns false on error. 132 bool EndElement() { 133 return xmlTextWriterEndElement(writer_) >= 0; 134 } 135 136 // Adds an attribute to the current open element. Returns false on error. 137 bool AddAttribute(const std::string& attribute_name, 138 const std::string& attribute_value) { 139 return xmlTextWriterWriteAttribute(writer_, 140 BAD_CAST attribute_name.c_str(), 141 BAD_CAST attribute_value.c_str()) >= 0; 142 } 143 144 // Adds a new element with name |element_name| and content |content| 145 // to the buffer. Example: <|element_name|>|content|</|element_name|> 146 // Returns false on errors. 147 bool WriteElement(const std::string& element_name, 148 const std::string& content) { 149 return xmlTextWriterWriteElement(writer_, 150 BAD_CAST element_name.c_str(), 151 BAD_CAST content.c_str()) >= 0; 152 } 153 154 // Helper functions not provided by xmlTextWriter --------------------------- 155 156 // Returns the string that has been written to the buffer. 157 std::string GetWrittenString() { 158 if (buffer_ == NULL) 159 return ""; 160 return XmlStringToStdString(buffer_->content); 161 } 162 163 private: 164 // The underlying libxml xmlTextWriter. 165 xmlTextWriterPtr writer_; 166 167 // Stores the output. 168 xmlBufferPtr buffer_; 169 }; 170 171 #endif // THIRD_PARTY_LIBXML_CHROMIUM_INCLUDE_LIBXML_LIBXML_UTILS_H_ 172