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 9 std::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 17 XmlReader::XmlReader() : reader_(NULL) { 18 } 19 20 XmlReader::~XmlReader() { 21 if (reader_) 22 xmlFreeTextReader(reader_); 23 } 24 25 bool 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 35 bool 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 42 bool 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 51 bool XmlReader::IsClosingElement() { 52 return NodeType() == XML_READER_TYPE_END_ELEMENT; 53 } 54 55 bool 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 87 bool 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 105 XmlWriter::XmlWriter() 106 : writer_(NULL), 107 buffer_(NULL) {} 108 109 XmlWriter::~XmlWriter() { 110 if (writer_) 111 xmlFreeTextWriter(writer_); 112 if (buffer_) 113 xmlBufferFree(buffer_); 114 } 115 116 void XmlWriter::StartWriting() { 117 buffer_ = xmlBufferCreate(); 118 writer_ = xmlNewTextWriterMemory(buffer_, 0); 119 xmlTextWriterSetIndent(writer_, 1); 120 xmlTextWriterStartDocument(writer_, NULL, NULL, NULL); 121 } 122 123 void XmlWriter::StopWriting() { 124 xmlTextWriterEndDocument(writer_); 125 xmlFreeTextWriter(writer_); 126 writer_ = NULL; 127 } 128