/** @file sample for the libxml++ textreader
 *
 * Last CVS checkin:
 * $Date: $
 * $Author: scheff $
 */

/**************************************************************************/

// standard C/C++ header:
#include <iostream>

// Gnome header:
#include <libxml++/parsers/textreader.h>

using namespace std;

/**************************************************************************/

/// provides a structure for an indent manipulator for output streams.
struct indent {
  int n; ///< indent step
  indent(int n_): n(n_) {} ///< indent manipulator constructor
};

/** provides an indent manipulator for output streams.
 * @param out the output stream
 * @param in the indent structure
 * @return the output stream
 */
ostream& operator << (ostream &out, indent const & in)
{
  for(int i = 0; i != in.n; ++i) out << "  ";
  return out;
}

/** waits for user confirm.
 *
 * @param action text with next action
 */
static void pause(const string &action)
{
  cout << "Press [ENTER] to " << action << ": " << flush;
  string in; getline(cin, in);
}

/** provides the main function of application.
 *
 * @param argc number of command line arguments
 * @param argv pointer to array of pointers to strings with command line
 *        arguments
 * @return 0 ... application exited regularly\n
 *         else ... execution of application aborted
 */
int main(int argc, char *argv[])
{
  // check command line
  if (argc < 2) {
    cerr << "ERROR: Missing XML file!" << endl
      << "Usage: xml++-textreader file.xml" << endl;
    pause("abort");
    return 1;
  }
  const char *file = argv[1];
  // start text reader
  pause(string("read ") + file);
  try {
    xmlpp::TextReader xmlTextReader(file);
    for (;;) {
      cout << "xmlTextReader.read();" << endl;
      if (!xmlTextReader.read()) break;
      int depth = xmlTextReader.get_depth();
      cout << indent(depth) << "--- node ---" << endl;
      cout << indent(depth) << "name: " << xmlTextReader.get_name() << endl;
      cout << indent(depth) << "depth: " << xmlTextReader.get_depth() << endl;
      if (xmlTextReader.has_attributes()) {
        cout << indent(depth) << "attributes: " << endl;
        cout << "xmlTextReader.move_to_first_attribute();" << endl;
        xmlTextReader.move_to_first_attribute();
        for (;;) {
          cout << indent(depth) << "  " << xmlTextReader.get_name() << ": "
            << xmlTextReader.get_value() << endl;
          cout << "xmlTextReader.move_to_next_attribute(): ";
          if (xmlTextReader.move_to_next_attribute()) cout << "true" << endl;
          else { cout << "false" << endl; break; }
        }
        cout << "xmlTextReader.move_to_element()" << endl;
        xmlTextReader.move_to_element();
      } else cout << indent(depth) << "no attributes" << endl;
      if(xmlTextReader.has_value())
        cout << indent(depth) << "value: '" << xmlTextReader.get_value() << "'" << endl;
      else cout << indent(depth) << "novalue" << endl;
    }
  } catch(const exception &error) {
    cout << "ERROR: Exception caught: " << error.what() << endl;
  }
  // done
  pause("finish");
  return 0;
}

