Home | History | Annotate | Download | only in chromium
      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