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