2 * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
3 * are covered by the GNU Lesser General Public License, which should be
4 * included with libxml++ as the file COPYING.
7 #include "libxml++/parsers/domparser.h"
8 #include "libxml++/dtd.h"
9 #include "libxml++/nodes/element.h"
10 #include "libxml++/nodes/textnode.h"
11 #include "libxml++/nodes/commentnode.h"
12 #include "libxml++/keepblanks.h"
13 #include "libxml++/exceptions/internal_error.h"
14 #include <libxml/parserInternals.h>//For xmlCreateFileParserCtxt().
22 DomParser::DomParser()
25 //Start with an empty document:
26 doc_ = new Document();
29 DomParser::DomParser(const Glib::ustring& filename, bool validate)
32 set_validate(validate);
36 DomParser::~DomParser()
41 void DomParser::parse_file(const Glib::ustring& filename)
43 release_underlying(); //Free any existing document.
45 KeepBlanks k(KeepBlanks::Default);
47 //The following is based on the implementation of xmlParseFile(), in xmlSAXParseFileWithData():
48 context_ = xmlCreateFileParserCtxt(filename.c_str());
52 #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
53 throw internal_error("Couldn't create parsing context");
56 #endif //LIBXMLCPP_EXCEPTIONS_ENABLED
59 if(context_->directory == 0)
61 char* directory = xmlParserGetDirectory(filename.c_str());
62 context_->directory = (char*) xmlStrdup((xmlChar*) directory);
68 void DomParser::parse_memory_raw(const unsigned char* contents, size_type bytes_count)
70 release_underlying(); //Free any existing document.
72 KeepBlanks k(KeepBlanks::Default);
74 //The following is based on the implementation of xmlParseFile(), in xmlSAXParseFileWithData():
75 context_ = xmlCreateMemoryParserCtxt((const char*)contents, bytes_count);
79 #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
80 throw internal_error("Couldn't create parsing context");
83 #endif //LIBXMLCPP_EXCEPTIONS_ENABLED
89 void DomParser::parse_memory(const Glib::ustring& contents)
91 parse_memory_raw((const unsigned char*)contents.c_str(), contents.bytes());
94 void DomParser::parse_context()
96 KeepBlanks k(KeepBlanks::Default);
98 //The following is based on the implementation of xmlParseFile(), in xmlSAXParseFileWithData():
99 //and the implementation of xmlParseMemory(), in xmlSaxParseMemoryWithData().
100 initialize_context();
104 #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
105 throw internal_error("Context not initialized");
108 #endif //LIBXMLCPP_EXCEPTIONS_ENABLED
111 xmlParseDocument(context_);
113 check_for_exception();
115 if(!context_->wellFormed)
117 release_underlying(); //Free doc_;
119 #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
120 throw parse_error("Document not well-formed.");
123 #endif //LIBXMLCPP_EXCEPTIONS_ENABLED
126 if(context_->errNo != 0)
128 std::ostringstream o;
129 o << "libxml error " << context_->errNo;
131 release_underlying();
133 #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
134 throw parse_error(o.str());
137 #endif //LIBXMLCPP_EXCEPTIONS_ENABLED
140 doc_ = new Document(context_->myDoc);
141 // This is to indicate to release_underlying that we took the
142 // ownership on the doc.
145 //Free the parse context, but keep the document alive so people can navigate the DOM tree:
146 //TODO: Why not keep the context alive too?
147 Parser::release_underlying();
149 check_for_exception();
153 void DomParser::parse_stream(std::istream& in)
155 release_underlying(); //Free any existing document.
157 KeepBlanks k(KeepBlanks::Default);
159 context_ = xmlCreatePushParserCtxt(
160 0, // setting thoses two parameters to 0 force the parser
161 0, // to create a document while parsing.
164 ""); // here should come the filename. I don't know if it is a problem to let it empty
168 #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
169 throw internal_error("Couldn't create parsing context");
172 #endif //LIBXMLCPP_EXCEPTIONS_ENABLED
175 initialize_context();
177 //TODO: Shouldn't we use a Glib::ustring here, and some alternative to std::getline()?
179 while(std::getline(in, line))
181 // since getline does not get the line separator, we have to add it since the parser cares
182 // about layout in certain cases.
185 xmlParseChunk(context_, line.c_str(), line.size() /* This is a std::string, not a ustring, so this is the number of bytes. */, 0);
188 xmlParseChunk(context_, 0, 0, 1);
190 check_for_exception();
192 if(!context_->wellFormed)
194 release_underlying(); //Free doc_;
196 #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
197 throw parse_error("Document not well-formed.");
200 #endif //LIBXMLCPP_EXCEPTIONS_ENABLED
203 if(context_->errNo != 0)
205 std::ostringstream o;
206 o << "libxml error " << context_->errNo;
208 release_underlying();
210 #ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
211 throw parse_error(o.str());
214 #endif //LIBXMLCPP_EXCEPTIONS_ENABLED
217 doc_ = new Document(context_->myDoc);
218 // This is to indicate to release_underlying that we took the
219 // ownership on the doc.
223 //Free the parse context, but keep the document alive so people can navigate the DOM tree:
224 //TODO: Why not keep the context alive too?
225 Parser::release_underlying();
227 check_for_exception();
230 void DomParser::release_underlying()
238 Parser::release_underlying();
241 DomParser::operator bool() const
246 Document* DomParser::get_document()
251 const Document* DomParser::get_document() const