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