| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- // tiny XML sub-set tools implementation -----------------------------------//
- // (C) Copyright Beman Dawes 2002. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #include "tiny_xml.hpp"
- #include <cassert>
- #include <cstring>
- namespace
- {
- void eat_whitespace( char & c, std::istream & in )
- {
- while ( c == ' ' || c == '\r' || c == '\n' || c == '\t' )
- in.get( c );
- }
- std::string get_name( char & c, std::istream & in )
- {
- std::string result;
- eat_whitespace( c, in );
- while ( std::strchr(
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.", c )
- != 0 )
- {
- result += c;
- if(!in.get( c ))
- throw std::string("xml: unexpected eof");
- }
- return result;
- }
- void eat_delim( char & c, std::istream & in,
- char delim, const std::string & msg )
- {
- eat_whitespace( c, in );
- if ( c != delim )
- throw std::string("xml syntax error, expected ") + delim
- + " (" + msg + ")";
- in.get( c );
- }
- std::string get_value( char & c, std::istream & in )
- {
- std::string result;
- while ( c != '\"' )
- {
- result += c;
- in.get( c );
- }
- in.get( c );
- return result;
- }
- }
- namespace boost
- {
- namespace tiny_xml
- {
- // parse -----------------------------------------------------------------//
- element_ptr parse( std::istream & in, const std::string & msg )
- {
- char c = 0; // current character
- element_ptr e( new element );
- if(!in.get( c ))
- throw std::string("xml: unexpected eof");
- if ( c == '<' )
- if(!in.get( c ))
- throw std::string("xml: unexpected eof");
- e->name = get_name( c, in );
- eat_whitespace( c, in );
- // attributes
- while ( c != '>' )
- {
- attribute a;
- a.name = get_name( c, in );
- eat_delim( c, in, '=', msg );
- eat_delim( c, in, '\"', msg );
- a.value = get_value( c, in );
- e->attributes.push_back( a );
- eat_whitespace( c, in );
- }
- if(!in.get( c )) // next after '>'
- throw std::string("xml: unexpected eof");
- eat_whitespace( c, in );
- // sub-elements
- while ( c == '<' )
- {
- if ( in.peek() == '/' ) break;
- e->elements.push_back( parse( in, msg ) );
- in.get( c ); // next after '>'
- eat_whitespace( c, in );
- }
- // content
- if ( c != '<' )
- {
- e->content += '\n';
- while ( c != '<' )
- {
- e->content += c;
- if(!in.get( c ))
- throw std::string("xml: unexpected eof");
- }
- }
- assert( c == '<' );
- if(!in.get( c )) // next after '<'
- throw std::string("xml: unexpected eof");
- eat_delim( c, in, '/', msg );
- std::string end_name( get_name( c, in ) );
- if ( e->name != end_name )
- throw std::string("xml syntax error: beginning name ")
- + e->name + " did not match end name " + end_name
- + " (" + msg + ")";
- eat_delim( c, in, '>', msg );
- return e;
- }
- // write ---------------------------------------------------------------//
- void write( const element & e, std::ostream & out )
- {
- out << "<" << e.name;
- if ( !e.attributes.empty() )
- {
- for( attribute_list::const_iterator itr = e.attributes.begin();
- itr != e.attributes.end(); ++itr )
- {
- out << " " << itr->name << "=\"" << itr->value << "\"";
- }
- }
- out << ">";
- if ( !e.elements.empty() )
- {
- out << "\n";
- for( element_list::const_iterator itr = e.elements.begin();
- itr != e.elements.end(); ++itr )
- {
- write( **itr, out );
- }
- }
- if ( !e.content.empty() )
- {
- out << e.content;
- }
- out << "</" << e.name << ">\n";
- }
- } // namespace tiny_xml
- } // namespace boost
|