blob: a237be59a03d44e3c36dfdc162f606d06239aab4 [file] [log] [blame]
// Copyright (c) 2012 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.
#include "libxml_utils.h"
#include "libxml/xmlreader.h"
std::string XmlStringToStdString(const xmlChar* xmlstring) {
// xmlChar*s are UTF-8, so this cast is safe.
if (xmlstring)
return std::string(reinterpret_cast<const char*>(xmlstring));
else
return "";
}
XmlReader::XmlReader() : reader_(NULL) {
}
XmlReader::~XmlReader() {
if (reader_)
xmlFreeTextReader(reader_);
}
bool XmlReader::Load(const std::string& input) {
const int kParseOptions = XML_PARSE_RECOVER | // recover on errors
XML_PARSE_NONET; // forbid network access
// TODO(evanm): Verify it's OK to pass NULL for the URL and encoding.
// The libxml code allows for these, but it's unclear what effect is has.
reader_ = xmlReaderForMemory(input.data(), static_cast<int>(input.size()),
NULL, NULL, kParseOptions);
return reader_ != NULL;
}
bool XmlReader::LoadFile(const std::string& file_path) {
const int kParseOptions = XML_PARSE_RECOVER | // recover on errors
XML_PARSE_NONET; // forbid network access
reader_ = xmlReaderForFile(file_path.c_str(), NULL, kParseOptions);
return reader_ != NULL;
}
bool XmlReader::NodeAttribute(const char* name, std::string* out) {
xmlChar* value = xmlTextReaderGetAttribute(reader_, BAD_CAST name);
if (!value)
return false;
*out = XmlStringToStdString(value);
xmlFree(value);
return true;
}
bool XmlReader::IsClosingElement() {
return NodeType() == XML_READER_TYPE_END_ELEMENT;
}
bool XmlReader::ReadElementContent(std::string* content) {
const int start_depth = Depth();
if (xmlTextReaderIsEmptyElement(reader_)) {
// Empty tag. We succesfully read the content, but it's
// empty.
*content = "";
// Advance past this empty tag.
if (!Read())
return false;
return true;
}
// Advance past opening element tag.
if (!Read())
return false;
// Read the content. We read up until we hit a closing tag at the
// same level as our starting point.
while (NodeType() != XML_READER_TYPE_END_ELEMENT || Depth() != start_depth) {
*content += XmlStringToStdString(xmlTextReaderConstValue(reader_));
if (!Read())
return false;
}
// Advance past ending element tag.
if (!Read())
return false;
return true;
}
bool XmlReader::SkipToElement() {
do {
switch (NodeType()) {
case XML_READER_TYPE_ELEMENT:
return true;
case XML_READER_TYPE_END_ELEMENT:
return false;
default:
// Skip all other node types.
continue;
}
} while (Read());
return false;
}
// XmlWriter functions
XmlWriter::XmlWriter()
: writer_(NULL),
buffer_(NULL) {}
XmlWriter::~XmlWriter() {
if (writer_)
xmlFreeTextWriter(writer_);
if (buffer_)
xmlBufferFree(buffer_);
}
void XmlWriter::StartWriting() {
buffer_ = xmlBufferCreate();
writer_ = xmlNewTextWriterMemory(buffer_, 0);
xmlTextWriterSetIndent(writer_, 1);
xmlTextWriterStartDocument(writer_, NULL, NULL, NULL);
}
void XmlWriter::StopWriting() {
xmlTextWriterEndDocument(writer_);
xmlFreeTextWriter(writer_);
writer_ = NULL;
}