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