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