• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
XmlStringToStdString(const xmlChar * xmlstring)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 
XmlReader()17 XmlReader::XmlReader() : reader_(NULL) {
18 }
19 
~XmlReader()20 XmlReader::~XmlReader() {
21   if (reader_)
22     xmlFreeTextReader(reader_);
23 }
24 
Load(const std::string & input)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 
LoadFile(const std::string & file_path)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 
NodeAttribute(const char * name,std::string * out)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 
IsClosingElement()51 bool XmlReader::IsClosingElement() {
52   return NodeType() == XML_READER_TYPE_END_ELEMENT;
53 }
54 
ReadElementContent(std::string * content)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 
SkipToElement()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 
XmlWriter()105 XmlWriter::XmlWriter()
106     : writer_(NULL),
107       buffer_(NULL) {}
108 
~XmlWriter()109 XmlWriter::~XmlWriter() {
110   if (writer_)
111     xmlFreeTextWriter(writer_);
112   if (buffer_)
113     xmlBufferFree(buffer_);
114 }
115 
StartWriting()116 void XmlWriter::StartWriting() {
117   buffer_ = xmlBufferCreate();
118   writer_ = xmlNewTextWriterMemory(buffer_, 0);
119   xmlTextWriterSetIndent(writer_, 1);
120   xmlTextWriterStartDocument(writer_, NULL, NULL, NULL);
121 }
122 
StopWriting()123 void XmlWriter::StopWriting() {
124   xmlTextWriterEndDocument(writer_);
125   xmlFreeTextWriter(writer_);
126   writer_ = NULL;
127 }
128