[libxml++] Parsers: Improve the error handling.
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libxml++] Parsers: Improve the error handling.
- Date: Tue, 7 Aug 2012 17:59:05 +0000 (UTC)
commit f93008e2566cdd1e92b4253c2ec0e16fb0690a37
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date: Tue Aug 7 19:35:23 2012 +0200
Parsers: Improve the error handling.
* libxml++/parsers/domparser.[h|cc]:
* libxml++/parsers/saxparser.[h|cc]:
* libxml++/parsers/textreader.[h|cc]: Check more return codes from libxml2
functions. Improve the description of errors in the reference documentation.
Bug #635846.
ChangeLog | 18 ++++-
libxml++/parsers/domparser.cc | 71 ++++++++++++++--------
libxml++/parsers/domparser.h | 46 +++++++++++----
libxml++/parsers/saxparser.cc | 129 +++++++++++++++++++++++++++++++--------
libxml++/parsers/saxparser.h | 39 ++++++++----
libxml++/parsers/textreader.cc | 16 +----
libxml++/parsers/textreader.h | 63 +++++++++++++++++--
7 files changed, 280 insertions(+), 102 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 4f71d8a..77d06e7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2012-08-07 Kjell Ahlstedt <kjell ahlstedt bredband net>
-
+
+ Parsers: Improve the error handling.
+
+ * libxml++/parsers/domparser.[h|cc]:
+ * libxml++/parsers/saxparser.[h|cc]:
+ * libxml++/parsers/textreader.[h|cc]: Check more return codes from libxml2
+ functions. Improve the description of errors in the reference documentation.
+ Bug #635846.
+
+2012-08-07 Kjell Ahlstedt <kjell ahlstedt bredband net>
+
Document, Element, Node: Remove unnecessary tests for null pointers.
* libxml++/document.cc:
@@ -9,14 +19,14 @@
tests were newly added when error handling was improved. Bug #635846.
2012-08-05 Kjell Ahlstedt <kjell ahlstedt bredband net>
-
+
Schema::set_document(): Create empty document.
* libxml++/schema.[h|cc]: set_document(): If the argument 'document' is 0,
create an empty document, as the documentation says.
2012-08-05 Kjell Ahlstedt <kjell ahlstedt bredband net>
-
+
Document, Schema: Improve the error handling.
* libxml++/document.[h|cc]:
@@ -24,7 +34,7 @@
Improve the description of errors in the reference documentation. Bug #635846.
2012-08-02 Kjell Ahlstedt <kjell ahlstedt bredband net>
-
+
Element, Node: Improve the error handling.
* libxml++/nodes/element.[h|cc]:
diff --git a/libxml++/parsers/domparser.cc b/libxml++/parsers/domparser.cc
index 52fb8d2..f1aaa52 100644
--- a/libxml++/parsers/domparser.cc
+++ b/libxml++/parsers/domparser.cc
@@ -50,13 +50,12 @@ void DomParser::parse_file(const Glib::ustring& filename)
if(!context_)
{
- throw internal_error("Couldn't create parsing context\n" + format_xml_error());
+ throw internal_error("Could not create parser context\n" + format_xml_error());
}
if(context_->directory == 0)
{
- char* directory = xmlParserGetDirectory(filename.c_str());
- context_->directory = (char*) xmlStrdup((xmlChar*) directory);
+ context_->directory = xmlParserGetDirectory(filename.c_str());
}
parse_context();
@@ -74,7 +73,7 @@ void DomParser::parse_memory_raw(const unsigned char* contents, size_type bytes_
if(!context_)
{
- throw internal_error("Couldn't create parsing context\n" + format_xml_error());
+ throw internal_error("Could not create parser context\n" + format_xml_error());
}
parse_context();
@@ -96,19 +95,28 @@ void DomParser::parse_context()
if(!context_)
{
- throw internal_error("Context not initialized\n" + format_xml_error());
+ throw internal_error("Parser context not initialized\n" + format_xml_error());
}
- xmlParseDocument(context_);
+ const int parseError = xmlParseDocument(context_);
- check_for_exception();
+ try
+ {
+ check_for_exception();
+ }
+ catch (...)
+ {
+ release_underlying(); //Free doc_ and context_
+ throw; // re-throw exception
+ }
- const Glib::ustring error_str = format_xml_parser_error(context_);
+ Glib::ustring error_str = format_xml_parser_error(context_);
+ if (error_str.empty() && parseError == -1)
+ error_str = "xmlParseDocument() failed.";
if(!error_str.empty())
{
release_underlying(); //Free doc_ and context_
-
throw parse_error(error_str);
}
@@ -120,11 +128,8 @@ void DomParser::parse_context()
//Free the parse context, but keep the document alive so people can navigate the DOM tree:
//TODO: Why not keep the context alive too?
Parser::release_underlying();
-
- check_for_exception();
}
-
void DomParser::parse_stream(std::istream& in)
{
release_underlying(); //Free any existing document.
@@ -133,20 +138,21 @@ void DomParser::parse_stream(std::istream& in)
xmlResetLastError();
context_ = xmlCreatePushParserCtxt(
- 0, // setting thoses two parameters to 0 force the parser
+ 0, // Setting those two parameters to 0 force the parser
0, // to create a document while parsing.
- 0,
- 0,
- ""); // here should come the filename. I don't know if it is a problem to let it empty
+ 0, // chunk
+ 0, // size
+ 0); // no filename for fetching external entities
if(!context_)
{
- throw internal_error("Couldn't create parsing context\n" + format_xml_error());
+ throw internal_error("Could not create parser context\n" + format_xml_error());
}
initialize_context();
//TODO: Shouldn't we use a Glib::ustring here, and some alternative to std::getline()?
+ int firstParseError = XML_ERR_OK;
std::string line;
while(std::getline(in, line))
{
@@ -154,19 +160,36 @@ void DomParser::parse_stream(std::istream& in)
// about layout in certain cases.
line += '\n';
- xmlParseChunk(context_, line.c_str(), line.size() /* This is a std::string, not a ustring, so this is the number of bytes. */, 0);
+ const int parseError = xmlParseChunk(context_, line.c_str(),
+ line.size() /* This is a std::string, not a ustring, so this is the number of bytes. */, 0);
+
+ // Save the first error code if any, but read on.
+ // More errors might be reported and then thrown by check_for_exception().
+ if (parseError != XML_ERR_OK && firstParseError == XML_ERR_OK)
+ firstParseError = parseError;
}
- xmlParseChunk(context_, 0, 0, 1);
+ const int parseError = xmlParseChunk(context_, 0, 0, 1 /* last chunk */);
+ if (parseError != XML_ERR_OK && firstParseError == XML_ERR_OK)
+ firstParseError = parseError;
- check_for_exception();
+ try
+ {
+ check_for_exception();
+ }
+ catch (...)
+ {
+ release_underlying(); //Free doc_ and context_
+ throw; // re-throw exception
+ }
- const Glib::ustring error_str = format_xml_parser_error(context_);
+ Glib::ustring error_str = format_xml_parser_error(context_);
+ if (error_str.empty() && firstParseError != XML_ERR_OK)
+ error_str = "Error code from xmlParseChunk(): " + Glib::ustring::format(firstParseError);
if(!error_str.empty())
{
release_underlying(); //Free doc_ and context_
-
throw parse_error(error_str);
}
@@ -179,8 +202,6 @@ void DomParser::parse_stream(std::istream& in)
//Free the parse context, but keep the document alive so people can navigate the DOM tree:
//TODO: Why not keep the context alive too?
Parser::release_underlying();
-
- check_for_exception();
}
void DomParser::release_underlying()
@@ -210,5 +231,3 @@ const Document* DomParser::get_document() const
}
} // namespace xmlpp
-
-
diff --git a/libxml++/parsers/domparser.h b/libxml++/parsers/domparser.h
index 8d6c296..5c2282a 100644
--- a/libxml++/parsers/domparser.h
+++ b/libxml++/parsers/domparser.h
@@ -19,46 +19,74 @@ namespace xmlpp {
class DomParser : public Parser
{
public:
+ /** Create a parser with an empty document.
+ * @throws xmlpp::internal_error If an empty document can't be created.
+ */
DomParser();
/** Instantiate the parser and parse a document immediately.
- * @throw exception
* @param filename The path to the file.
* @param validate Whether the parser should validate the XML.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
explicit DomParser(const Glib::ustring& filename, bool validate = false);
virtual ~DomParser();
/** Parse an XML document from a file.
- * @throw exception
+ * If the parser already contains a document, that document and all its nodes
+ * are deleted.
* @param filename The path to the file.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
virtual void parse_file(const Glib::ustring& filename);
/** Parse an XML document from a string.
- * @throw exception
+ * If the parser already contains a document, that document and all its nodes
+ * are deleted.
* @param contents The XML document as a string.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
virtual void parse_memory(const Glib::ustring& contents);
/** Parse an XML document from raw memory.
- * @throw exception
+ * If the parser already contains a document, that document and all its nodes
+ * are deleted.
* @param contents The XML document as an array of bytes.
* @param bytes_count The number of bytes in the @a contents array.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
void parse_memory_raw(const unsigned char* contents, size_type bytes_count);
/** Parse an XML document from a stream.
- * @throw exception
+ * If the parser already contains a document, that document and all its nodes
+ * are deleted.
* @param in The stream.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
virtual void parse_stream(std::istream& in);
/** Test whether a document has been parsed.
- */
+ */
operator bool() const;
+ /** Get the parsed document.
+ * @returns A pointer to the parsed document, or <tt>0</tt>.
+ */
Document* get_document();
+
+ /** Get the parsed document.
+ * @returns A pointer to the parsed document, or <tt>0</tt>.
+ */
const Document* get_document() const;
protected:
@@ -69,12 +97,6 @@ protected:
Document* doc_;
};
-
-
-
} // namespace xmlpp
#endif //__LIBXMLPP_PARSERS_DOMPARSER_H
-
-
-
diff --git a/libxml++/parsers/saxparser.cc b/libxml++/parsers/saxparser.cc
index d937cbf..204dd7d 100644
--- a/libxml++/parsers/saxparser.cc
+++ b/libxml++/parsers/saxparser.cc
@@ -15,7 +15,6 @@
#include <libxml/parserInternals.h> // for xmlCreateFileParserCtxt
#include <cstdarg> //For va_list.
-#include <cassert> // for assert()
#include <iostream>
namespace xmlpp {
@@ -147,28 +146,41 @@ void SaxParser::on_internal_subset(const Glib::ustring& name,
// (http://www.daa.com.au/~james/gnome/xml-sax/implementing.html)
void SaxParser::parse()
{
-
+ //TODO If this is not the first parsing with this SaxParser, the xmlDoc object
+ // in entity_resolver_doc_ should be deleted and replaced by a new one.
+ // Otherwise entity declarations from a previous parsing may erroneously affect
+ // this parsing. This would be much easier if entity_resolver_doc_ were a
+ // std::auto_ptr<Document>, so the xmlpp::Document could be deleted and a new
+ // one created. A good place for such code would be in an overridden
+ // SaxParser::initialize_context(). It would be an ABI break.
+
if(!context_)
{
- throw internal_error("Parse context not created.");
+ throw internal_error("Parser context not created.");
}
xmlSAXHandlerPtr old_sax = context_->sax;
context_->sax = sax_handler_.get();
+ xmlResetLastError();
initialize_context();
- xmlParseDocument(context_);
+ const int parseError = xmlParseDocument(context_);
context_->sax = old_sax;
- if( (! context_->wellFormed)
- && (! exception_) )
- exception_ = new parse_error("Document not well-formed");
+ Glib::ustring error_str = format_xml_parser_error(context_);
+ if (error_str.empty() && parseError == -1)
+ error_str = "xmlParseDocument() failed.";
- release_underlying();
+ release_underlying(); // Free context_
check_for_exception();
+
+ if(!error_str.empty())
+ {
+ throw parse_error(error_str);
+ }
}
void SaxParser::parse_file(const Glib::ustring& filename)
@@ -210,17 +222,24 @@ void SaxParser::parse_stream(std::istream& in)
}
KeepBlanks k(KeepBlanks::Default);
+ xmlResetLastError();
context_ = xmlCreatePushParserCtxt(
sax_handler_.get(),
0, // user_data
- 0,
- 0,
- ""); // This should be the filename. I don't know if it is a problem to leave it empty.
+ 0, // chunk
+ 0, // size
+ 0); // no filename for fetching external entities
+
+ if(!context_)
+ {
+ throw internal_error("Could not create parser context\n" + format_xml_error());
+ }
initialize_context();
//TODO: Shouldn't we use a Glib::ustring here, and some alternative to std::getline()?
+ int firstParseError = XML_ERR_OK;
std::string line;
while( ( ! exception_ )
&& std::getline(in, line))
@@ -229,15 +248,37 @@ void SaxParser::parse_stream(std::istream& in)
// about layout in certain cases.
line += '\n';
- xmlParseChunk(context_, line.c_str(), line.size() /* This is a std::string, not a ustring, so this is the number of bytes. */, 0 /* don't terminate */);
+ const int parseError = xmlParseChunk(context_, line.c_str(),
+ line.size() /* This is a std::string, not a ustring, so this is the number of bytes. */,
+ 0 /* don't terminate */);
+
+ // Save the first error code if any, but read on.
+ // More errors might be reported and then thrown by check_for_exception().
+ if (parseError != XML_ERR_OK && firstParseError == XML_ERR_OK)
+ firstParseError = parseError;
}
if( ! exception_ )
- xmlParseChunk(context_, 0 /* chunk */, 0 /* size */, 1 /* terminate (1 or 0) */); //This seems to be called just to terminate parsing.
+ {
+ //This is called just to terminate parsing.
+ const int parseError = xmlParseChunk(context_, 0 /* chunk */, 0 /* size */, 1 /* terminate (1 or 0) */);
- release_underlying();
+ if (parseError != XML_ERR_OK && firstParseError == XML_ERR_OK)
+ firstParseError = parseError;
+ }
+
+ Glib::ustring error_str = format_xml_parser_error(context_);
+ if (error_str.empty() && firstParseError != XML_ERR_OK)
+ error_str = "Error code from xmlParseChunk(): " + Glib::ustring::format(firstParseError);
+
+ release_underlying(); // Free context_
check_for_exception();
+
+ if(!error_str.empty())
+ {
+ throw parse_error(error_str);
+ }
}
void SaxParser::parse_chunk(const Glib::ustring& chunk)
@@ -248,23 +289,39 @@ void SaxParser::parse_chunk(const Glib::ustring& chunk)
void SaxParser::parse_chunk_raw(const unsigned char* contents, size_type bytes_count)
{
KeepBlanks k(KeepBlanks::Default);
+ xmlResetLastError();
if(!context_)
{
context_ = xmlCreatePushParserCtxt(
sax_handler_.get(),
0, // user_data
- 0,
- 0,
- ""); // This should be the filename. I don't know if it is a problem to let it empty
-
+ 0, // chunk
+ 0, // size
+ 0); // no filename for fetching external entities
+
+ if(!context_)
+ {
+ throw internal_error("Could not create parser context\n" + format_xml_error());
+ }
initialize_context();
}
+ else
+ xmlCtxtResetLastError(context_);
+ int parseError = XML_ERR_OK;
if(!exception_)
- xmlParseChunk(context_, (const char*)contents, bytes_count, 0 /* don't terminate */);
+ parseError = xmlParseChunk(context_, (const char*)contents, bytes_count, 0 /* don't terminate */);
check_for_exception();
+
+ Glib::ustring error_str = format_xml_parser_error(context_);
+ if (error_str.empty() && parseError != XML_ERR_OK)
+ error_str = "Error code from xmlParseChunk(): " + Glib::ustring::format(parseError);
+ if(!error_str.empty())
+ {
+ throw parse_error(error_str);
+ }
}
void SaxParser::release_underlying()
@@ -274,22 +331,42 @@ void SaxParser::release_underlying()
void SaxParser::finish_chunk_parsing()
{
+ xmlResetLastError();
if(!context_)
{
context_ = xmlCreatePushParserCtxt(
sax_handler_.get(),
0, // this, // user_data
- 0,
- 0,
- ""); // This should be the filename. I don't know if it is a problem to leave it empty
+ 0, // chunk
+ 0, // size
+ 0); // no filename for fetching external entities
+
+ if(!context_)
+ {
+ throw internal_error("Could not create parser context\n" + format_xml_error());
+ }
+ initialize_context();
}
-
+ else
+ xmlCtxtResetLastError(context_);
+
+ int parseError = XML_ERR_OK;
if(!exception_)
- xmlParseChunk(context_, 0 /* chunk */, 0 /* size */, 1 /* terminate (1 or 0) */); //This seems to be called just to terminate parsing.
+ //This is called just to terminate parsing.
+ parseError = xmlParseChunk(context_, 0 /* chunk */, 0 /* size */, 1 /* terminate (1 or 0) */);
- release_underlying();
+ Glib::ustring error_str = format_xml_parser_error(context_);
+ if (error_str.empty() && parseError != XML_ERR_OK)
+ error_str = "Error code from xmlParseChunk(): " + Glib::ustring::format(parseError);
+
+ release_underlying(); // Free context_
check_for_exception();
+
+ if(!error_str.empty())
+ {
+ throw parse_error(error_str);
+ }
}
@@ -548,5 +625,3 @@ void SaxParserCallback::internal_subset(void* context, const xmlChar* name,
}
} // namespace xmlpp
-
-
diff --git a/libxml++/parsers/saxparser.h b/libxml++/parsers/saxparser.h
index 6c30440..2e64482 100644
--- a/libxml++/parsers/saxparser.h
+++ b/libxml++/parsers/saxparser.h
@@ -81,27 +81,35 @@ public:
virtual ~SaxParser();
/** Parse an XML document from a file.
- * @throw exception
* @param filename The path to the file.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
virtual void parse_file(const Glib::ustring& filename);
/** Parse an XML document from a string.
- * @throw exception
* @param contents The XML document as a string.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
virtual void parse_memory(const Glib::ustring& contents);
/** Parse an XML document from raw memory.
- * @throw exception
* @param contents The XML document as an array of bytes.
* @param bytes_count The number of bytes in the @a contents array.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
void parse_memory_raw(const unsigned char* contents, size_type bytes_count);
/** Parse an XML document from a stream.
- * @throw exception
* @param in The stream.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
virtual void parse_stream(std::istream& in);
@@ -114,8 +122,10 @@ public:
* The first call to parse_chunk will setup the parser. When the last chunk
* has been parsed, call finish_chunk_parsing() to finish the parse.
*
- * @throw exception
* @param chunk The next piece of the XML document.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
virtual void parse_chunk(const Glib::ustring& chunk);
@@ -130,9 +140,11 @@ public:
* The first call to parse_chunk will setup the parser. When the last chunk
* has been parsed, call finish_chunk_parsing() to finish the parse.
*
- * @throw exception
* @param contents The next piece of the XML document as an array of bytes.
* @param bytes_count The number of bytes in the @a contents array.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
void parse_chunk_raw(const unsigned char* contents, size_type bytes_count);
@@ -140,6 +152,9 @@ public:
*
* Call this after the last call to parse_chunk(). Don't use this function with
* the other parsing methods.
+ * @throws xmlpp::internal_error
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
virtual void finish_chunk_parsing();
@@ -153,6 +168,8 @@ protected:
virtual void on_comment(const Glib::ustring& text);
virtual void on_warning(const Glib::ustring& text);
virtual void on_error(const Glib::ustring& text);
+ /** @throws xmlpp::parse_error
+ */
virtual void on_fatal_error(const Glib::ustring& text);
virtual void on_cdata_block(const Glib::ustring& text);
@@ -176,7 +193,8 @@ protected:
* Unlike the DomParser, the SaxParser will also tell you about entity references for the 5 predefined entities.
*
* @param name The entity reference name.
- * @returns The resolved xmlEntity for the entity reference. You must include libxml/parser.h in order to use this C struct.
+ * @returns The resolved xmlEntity for the entity reference, or <tt>0</tt> if not found.
+ * You must include libxml/parser.h in order to use this C struct.
* This instance will not be freed by the caller.
*/
virtual _xmlEntity* on_get_entity(const Glib::ustring& name);
@@ -185,6 +203,7 @@ protected:
* If you override this function, and you want normal entity substitution to work, then you must call the base class in your override.
*
* This would be useful when overriding on_get_entity().
+ * @throws xmlpp::internal_error
*/
virtual void on_entity_declaration(const Glib::ustring& name, XmlEntityType type, const Glib::ustring& publicId, const Glib::ustring& systemId, const Glib::ustring& content);
@@ -202,12 +221,6 @@ private:
friend struct SaxParserCallback;
};
-
-
-
} // namespace xmlpp
#endif //__LIBXMLPP_PARSERS_SAXPARSER_H
-
-
-
diff --git a/libxml++/parsers/textreader.cc b/libxml++/parsers/textreader.cc
index 4a258dc..c041cd4 100644
--- a/libxml++/parsers/textreader.cc
+++ b/libxml++/parsers/textreader.cc
@@ -106,7 +106,7 @@ int TextReader::get_attribute_count() const
Glib::ustring TextReader::get_base_uri() const
{
return propertyreader->String(
- xmlTextReaderBaseUri(impl_));
+ xmlTextReaderBaseUri(impl_), true);
}
int TextReader::get_depth() const
@@ -306,15 +306,7 @@ Node* TextReader::get_current_node()
const Node* TextReader::get_current_node() const
{
- xmlNodePtr node = xmlTextReaderCurrentNode(impl_);
- if(node)
- {
- Node::create_wrapper(node);
- return static_cast<Node*>(node->_private);
- }
-
- check_for_exceptions();
- return 0;
+ return const_cast<TextReader*>(this)->get_current_node();
}
/*
@@ -331,7 +323,6 @@ Node* TextReader::expand()
{
xmlNodePtr node = xmlTextReaderExpand(impl_);
if(node)
- if(node)
{
Node::create_wrapper(node);
return static_cast<Node*>(node->_private);
@@ -384,7 +375,6 @@ void TextReader::check_for_exceptions() const
int severity = severity_;
ths->severity_ = 0;
- //TODO: Offer an alternative when not using exceptions?
if( severity == XML_PARSER_SEVERITY_ERROR )
throw parse_error(error_);
else if( severity == XML_PARSER_SEVERITY_VALIDITY_ERROR )
@@ -404,7 +394,7 @@ bool TextReader::PropertyReader::Bool(int value)
if(value == -1)
owner_.check_for_exceptions();
- return value;
+ return value > 0;
}
char TextReader::PropertyReader::Char(int value)
diff --git a/libxml++/parsers/textreader.h b/libxml++/parsers/textreader.h
index 595e2e5..5901894 100644
--- a/libxml++/parsers/textreader.h
+++ b/libxml++/parsers/textreader.h
@@ -22,7 +22,7 @@ extern "C"
namespace xmlpp
{
-/** A TextReader-style XML parser
+/** A TextReader-style XML parser.
* A reader that provides fast, non-cached, forward-only access to XML data,
* in the style of .Net's <a href="http://msdn.microsoft.com/en-us/library/system.xml.xmltextreader.aspx">XmlTextReader</a> class.
*/
@@ -81,6 +81,7 @@ class TextReader: NonCopyable
/**
* Creates a new TextReader object to parse a file or URI.
* @param URI The URI to read.
+ * @throws xmlpp::internal_error If an xmlTextReader object cannot be created.
*/
TextReader(const Glib::ustring& URI);
@@ -88,39 +89,53 @@ class TextReader: NonCopyable
* Creates a new TextReader object which parses in memory data.
* @param data The data to parse.
* @param size The number of bytes in data.
- * @param uri The base URI of the file.
+ * @param uri The base URI to use for the document.
+ * @throws xmlpp::internal_error If an xmlTextReader object cannot be created.
*/
TextReader(const unsigned char* data, size_type size, const Glib::ustring& uri = Glib::ustring());
~TextReader();
/** Moves the position of the current instance to the next node in the stream, exposing its properties.
- * @return true if the node was read successfully, false if there is no more nodes to read.
+ * @return true if the node was read successfully, false if there are no more nodes to read.
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
bool read();
/** Reads the contents of the current node, including child nodes and markup.
- * @return A Glib::ustring containing the XML content, or and empty Glib::ustring if the current node is neither an element nor attribute, or has no child nodes.
+ * @return A Glib::ustring containing the XML content, or an empty Glib::ustring if the current node is neither an element nor attribute, or has no child nodes.
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
Glib::ustring read_inner_xml();
/** Reads the current node and its contents, including child nodes and markup.
* @return A Glib::ustring containing the XML content, or an empty Glib::ustring if the current node is neither an element nor attribute.
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
Glib::ustring read_outer_xml();
/** Reads the contents of an element or a text node as a string.
* @return A Glib::ustring containing the contents of the Element or Text node, or an empty Glib::ustring if the reader is positioned on any other type of node.
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
Glib::ustring read_string();
/** Parses an attribute value into one or more Text and EntityReference nodes.
* @return A bool where true indicates the attribute value was parsed, and false indicates the reader was not positioned on an attribute node or all the attribute values have been read.
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
bool read_attribute_value();
/** Gets the number of attributes on the current node.
- * @return The number of attributes on the current node, or zero if the current node does not support attributes.
+ * @return The number of attributes on the current node, or zero if the current node
+ * does not support attributes, or -1 in case of error.
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
*/
int get_attribute_count() const;
@@ -130,7 +145,7 @@ class TextReader: NonCopyable
Glib::ustring get_base_uri() const;
/** Gets the depth of the current node in the XML document.
- * @return The depth of the current node in the XML document.
+ * @return The depth of the current node in the XML document, or -1 in case of error.
*/
int get_depth() const;
@@ -139,7 +154,7 @@ class TextReader: NonCopyable
*/
bool has_attributes() const;
- /** Whether the node can have a text value.
+ /** Whether the node can have a text value.
* @return true if the current node can have an associated text value, false otherwise.
*/
bool has_value() const;
@@ -158,9 +173,19 @@ class TextReader: NonCopyable
Glib::ustring get_name() const;
Glib::ustring get_namespace_uri() const;
+ /** Get the node type of the current node.
+ * @returns The xmlpp::xmlNodeType of the current node, or -1 in case of error.
+ */
xmlNodeType get_node_type() const;
+ /** Get the namespace prefix associated with the current node.
+ * @returns The namespace prefix, or an empty string if not available.
+ */
Glib::ustring get_prefix() const;
+
+ /** Get the quotation mark character used to enclose the value of an attribute.
+ * @returns Returns " or ' and -1 in case of error.
+ */
char get_quote_char() const;
Glib::ustring get_value() const;
@@ -191,9 +216,33 @@ class TextReader: NonCopyable
bool get_parser_property(ParserProperties property) const;
void set_parser_property(ParserProperties property, bool value);
+ /** Get a pointer to the current node.
+ * @warning This is dangerous because the underlying node may be destroyed on the next read.
+ * The C++ wrapper is not deleted. Using this method causes memory leaks,
+ * unless you call xmlpp::Node::free_wrappers(), which is not intended to be
+ * called by the application.
+ * @returns A pointer to the current node, or 0 in case of error.
+ */
Node* get_current_node();
+
+ /** Get a pointer to the current node.
+ * @warning See the non-const get_current_node().
+ * @returns A pointer to the current node, or 0 in case of error.
+ */
const Node* get_current_node() const;
+
// Document* CurrentDocument();
+
+ /** Expand the current node.
+ * Reads the contents of the current node and the full subtree. It then makes
+ * the subtree available until the next call to read() or next().
+ * @warning The C++ wrappers are not deleted. Using this method causes memory leaks,
+ * unless you call xmlpp::Node::free_wrappers(), which is not intended to be
+ * called by the application.
+ * @returns A pointer to the current node, or 0 in case of error.
+ * @throws xmlpp::parse_error
+ * @throws xmlpp::validity_error
+ */
Node* expand();
bool next();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]