17 #include <libxml/parser.h> 38 static_assert(
sizeof(xmlChar) ==
sizeof(
char),
"Must be raw characters");
41 XMLDocumentParser* GetParser(
void* context) {
42 return reinterpret_cast<XMLDocumentParser*
>(context);
45 std::string ToString(
const xmlChar* data) {
46 return reinterpret_cast<const char*
>(data);
49 std::string ToString(
const xmlChar* data,
int length) {
50 auto* text =
reinterpret_cast<const char*
>(data);
51 return std::string(text, text + length);
55 void SaxEndDocument(
void* context) {
56 GetParser(context)->EndDocument();
59 void SaxStartElementNS(
void* context,
const xmlChar* local_name,
60 const xmlChar* prefix,
const xmlChar* namespace_uri,
62 const xmlChar** ,
int nb_attributes,
63 int ,
const xmlChar** attributes) {
64 GetParser(context)->StartElement(
66 namespace_uri ? optional<std::string>(ToString(namespace_uri)) :
nullopt,
67 prefix ? optional<std::string>(ToString(prefix)) : nullopt, nb_attributes,
68 reinterpret_cast<const char**>(attributes));
71 void SaxEndElementNS(
void* context,
const xmlChar* ,
72 const xmlChar* ,
const xmlChar* ) {
73 GetParser(context)->EndElement();
76 void SaxCharacters(
void* context,
const xmlChar* raw_data,
int size) {
77 GetParser(context)->Text(ToString(raw_data, size));
80 void SaxProcessingInstruction(
void* context,
const xmlChar* ,
85 void SaxComment(
void* context,
const xmlChar* raw_data) {
86 GetParser(context)->Comment(ToString(raw_data));
91 void* , const
char* format, ...) {
93 va_start(args, format);
95 LOG(WARNING) <<
"XML parsing warning: " <<
message;
101 void* context, const
char* format, ...) {
103 va_start(args, format);
107 GetParser(context)->SetException(
111 void SaxCdata(
void* context,
const xmlChar* value,
int len) {
113 GetParser(context)->Text(ToString(value, len));
119 : document_(document), current_node_(document) {}
124 const std::string&
source) {
130 memset(&sax, 0,
sizeof(sax));
131 sax.initialized = XML_SAX2_MAGIC;
132 sax.endDocument = &SaxEndDocument;
133 sax.startElementNs = &SaxStartElementNS;
134 sax.endElementNs = &SaxEndElementNS;
135 sax.characters = &SaxCharacters;
136 sax.processingInstruction = &SaxProcessingInstruction;
137 sax.comment = &SaxComment;
138 sax.warning = &SaxWarning;
139 sax.error = &SaxError;
140 sax.fatalError = &SaxError;
141 sax.cdataBlock = &SaxCdata;
143 int code = xmlSAXUserParseMemory(&sax,
this, source.c_str(), source.size());
145 LOG(ERROR) <<
"Error parsing XML document, code=" << code;
149 return std::move(*error_);
161 size_t attribute_count,
162 const char** attributes) {
166 new Element(document_, local_name, namespace_uri, namespace_prefix);
167 for (
size_t i = 0; i < attribute_count; i++) {
169 const char* local_name = attributes[i * 5];
170 const char* namespace_prefix = attributes[i * 5 + 1];
171 const char* namespace_uri = attributes[i * 5 + 2];
172 const char* value_begin = attributes[i * 5 + 3];
173 const char* value_end = attributes[i * 5 + 4];
176 std::string qualified_name;
177 if (namespace_prefix)
178 qualified_name = std::string(namespace_prefix) +
":" + local_name;
180 qualified_name = local_name;
182 child->SetAttributeNS(namespace_uri, qualified_name,
183 std::string(value_begin, value_end));
185 child->SetAttribute(local_name, std::string(value_begin, value_end));
189 current_node_->AppendChild(child);
190 current_node_ = child;
195 current_node_ = current_node_->parent_node();
196 DCHECK(!current_node_.empty());
200 current_text_.append(text);
205 current_node_->AppendChild(document_->CreateComment(text));
209 error_.reset(
new JsError(std::move(error)));
212 void XMLDocumentParser::FinishTextNode() {
213 if (!current_text_.empty()) {
214 current_node_->AppendChild(document_->CreateTextNode(current_text_));
215 current_text_.clear();
XMLDocumentParser(RefPtr< Document > document)
void Text(const std::string &text)
void StartElement(const std::string &local_name, optional< std::string > namespace_uri, optional< std::string > namespace_prefix, size_t attribute_count, const char **attributes)
std::string StringPrintfV(const char *format, va_list va)
ExceptionOr< RefPtr< Document > > Parse(const std::string &source)
static JsError DOMException(ExceptionCode code)
void SetException(JsError error)
#define PRINTF_FORMAT(format, dots)
void Comment(const std::string &text)