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#include "libxml_utils.h" 6 7#include "libxml/xmlreader.h" 8 9std::string XmlStringToStdString(const xmlChar* xmlstring) { 10 // xmlChar*s are UTF-8, so this cast is safe. 11 if (xmlstring) 12 return std::string(reinterpret_cast<const char*>(xmlstring)); 13 else 14 return ""; 15} 16 17XmlReader::XmlReader() : reader_(NULL) { 18} 19 20XmlReader::~XmlReader() { 21 if (reader_) 22 xmlFreeTextReader(reader_); 23} 24 25bool XmlReader::Load(const std::string& input) { 26 const int kParseOptions = XML_PARSE_RECOVER | // recover on errors 27 XML_PARSE_NONET; // forbid network access 28 // TODO(evanm): Verify it's OK to pass NULL for the URL and encoding. 29 // The libxml code allows for these, but it's unclear what effect is has. 30 reader_ = xmlReaderForMemory(input.data(), static_cast<int>(input.size()), 31 NULL, NULL, kParseOptions); 32 return reader_ != NULL; 33} 34 35bool XmlReader::LoadFile(const std::string& file_path) { 36 const int kParseOptions = XML_PARSE_RECOVER | // recover on errors 37 XML_PARSE_NONET; // forbid network access 38 reader_ = xmlReaderForFile(file_path.c_str(), NULL, kParseOptions); 39 return reader_ != NULL; 40} 41 42bool XmlReader::NodeAttribute(const char* name, std::string* out) { 43 xmlChar* value = xmlTextReaderGetAttribute(reader_, BAD_CAST name); 44 if (!value) 45 return false; 46 *out = XmlStringToStdString(value); 47 xmlFree(value); 48 return true; 49} 50 51bool XmlReader::IsClosingElement() { 52 return NodeType() == XML_READER_TYPE_END_ELEMENT; 53} 54 55bool XmlReader::ReadElementContent(std::string* content) { 56 const int start_depth = Depth(); 57 58 if (xmlTextReaderIsEmptyElement(reader_)) { 59 // Empty tag. We succesfully read the content, but it's 60 // empty. 61 *content = ""; 62 // Advance past this empty tag. 63 if (!Read()) 64 return false; 65 return true; 66 } 67 68 // Advance past opening element tag. 69 if (!Read()) 70 return false; 71 72 // Read the content. We read up until we hit a closing tag at the 73 // same level as our starting point. 74 while (NodeType() != XML_READER_TYPE_END_ELEMENT || Depth() != start_depth) { 75 *content += XmlStringToStdString(xmlTextReaderConstValue(reader_)); 76 if (!Read()) 77 return false; 78 } 79 80 // Advance past ending element tag. 81 if (!Read()) 82 return false; 83 84 return true; 85} 86 87bool XmlReader::SkipToElement() { 88 do { 89 switch (NodeType()) { 90 case XML_READER_TYPE_ELEMENT: 91 return true; 92 case XML_READER_TYPE_END_ELEMENT: 93 return false; 94 default: 95 // Skip all other node types. 96 continue; 97 } 98 } while (Read()); 99 return false; 100} 101 102 103// XmlWriter functions 104 105XmlWriter::XmlWriter() 106 : writer_(NULL), 107 buffer_(NULL) {} 108 109XmlWriter::~XmlWriter() { 110 if (writer_) 111 xmlFreeTextWriter(writer_); 112 if (buffer_) 113 xmlBufferFree(buffer_); 114} 115 116void XmlWriter::StartWriting() { 117 buffer_ = xmlBufferCreate(); 118 writer_ = xmlNewTextWriterMemory(buffer_, 0); 119 xmlTextWriterSetIndent(writer_, 1); 120 xmlTextWriterStartDocument(writer_, NULL, NULL, NULL); 121} 122 123void XmlWriter::StopWriting() { 124 xmlTextWriterEndDocument(writer_); 125 xmlFreeTextWriter(writer_); 126 writer_ = NULL; 127} 128