2008年11月8日土曜日

expat で遊ぼ


#include <iostream>
#include <string>
#include <vector>
#include <expat.h>
#include <boost/shared_ptr.hpp>
#include <boost/foreach.hpp>

class xml_node;

class xml_node {
public:
xml_node( const XML_Char* name ) : node_name_(name) {}
public:
std::basic_string<XML_Char> node_name_;
std::basic_string<XML_Char> node_value_;
std::vector< boost::shared_ptr<xml_node> > childs_;
};


class xml_holder {
public:
std::vector< boost::shared_ptr<xml_node> > stack_;
boost::shared_ptr<xml_node> current_;
};

void starter(void* userData, const XML_Char* name, const XML_Char* attrs[]) {
xml_holder* holder = reinterpret_cast<xml_holder*>(userData);
holder->stack_.push_back( holder->current_ );
boost::shared_ptr<xml_node> element( new xml_node( name ) );
holder->current_->childs_.push_back( element );
holder->current_ = element;
}

void ender( void* userData, const XML_Char* name) {
xml_holder* holder = reinterpret_cast<xml_holder*>(userData);
holder->current_ = holder->stack_.back();
holder->stack_.pop_back();
}

void data( void* userData, const XML_Char* s, int len ) {
xml_holder* holder = reinterpret_cast<xml_holder*>(userData);
holder->current_->node_value_.assign( s, s + len );
}

void trace( int depth, boost::shared_ptr<xml_node> elem ) {
for( int i = 0; i < depth; ++i ) { std::cout << " "; }
std::cout << elem->node_name_ << ":" << elem->node_value_ << std::endl;
BOOST_FOREACH( boost::shared_ptr<xml_node> e, elem->childs_ ) {
trace( depth+1, e );
}
}

bool parse_xml( const std::string& xml ) {
xml_holder holder;
holder.current_ = boost::shared_ptr<xml_node>( new xml_node( "root" ) );
XML_Parser parser = XML_ParserCreate("UTF-8");
if( !parser ) return false;
XML_SetUserData( parser, &holder );
XML_SetElementHandler( parser, starter, ender );
XML_SetCharacterDataHandler( parser, data );
int iseof = 0;
XML_Parse( parser, xml.c_str(), xml.size(), iseof );
XML_ParserFree( parser );
trace( 0, holder.current_ );
return !iseof;
}

0 件のコメント: