Like the SAX parser, the TextReader parser is suitable for sequential parsing, but instead of implementing handlers for specific parts of the document, it allows you to detect the current node type, process the node accordingly, and skip forward in the document as much as necessary. Unlike the DOM parser, you may not move backwards in the XML document. And unlike the SAX parser, you must not waste time processing nodes that do not interest you.
All methods are on the single parser instance, but their result depends on the current context. For instance, use read()
to move to the next node, and move_to_element()
to navigate to child nodes. These methods will return false when no more nodes are available. Then use methods such as get_name()
and get_value()
to examine the elements and their attributes.
This example examines each node in turn, then moves to the next node.
File: main.cc
#include <libxml++/libxml++.h> #include <cstdlib> #include <iostream> struct indent { int depth_; explicit indent(int depth): depth_(depth) {}; }; std::ostream & operator<<(std::ostream & o, indent const & in) { for(int i = 0; i != in.depth_; ++i) { o << " "; } return o; } std::ostream& operator<<(std::ostream& o, const std::optional<xmlpp::ustring>& s) { o << s.value_or("{[(no value)]}"); return o; } int main(int /* argc */, char** /* argv */) { try { xmlpp::TextReader reader("example.xml"); while(reader.read()) { int depth = reader.get_depth(); std::cout << indent(depth) << "--- node ---" << std::endl; std::cout << indent(depth) << "name: " << reader.get_name2() << std::endl; std::cout << indent(depth) << "depth: " << reader.get_depth() << std::endl; if(reader.has_attributes()) { std::cout << indent(depth) << "attributes: " << std::endl; std::cout << indent(depth) << "attribute 0: " << reader.get_attribute2(0) << std::endl; std::cout << indent(depth) << "attribute 9: " << reader.get_attribute2(9) << std::endl; reader.move_to_first_attribute(); do { std::cout << indent(depth) << " " << reader.get_name2() << ": " << reader.get_value2() << std::endl; } while(reader.move_to_next_attribute()); reader.move_to_element(); } else { std::cout << indent(depth) << "no attributes" << std::endl; } std::cout << indent(depth) << "value: '" << reader.get_value2() << "'" << std::endl; } } catch(const std::exception& e) { std::cerr << "Exception caught: " << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }