tiny_xml.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // tiny XML sub-set tools implementation -----------------------------------//
  2. // (C) Copyright Beman Dawes 2002.
  3. // See accompanying license for terms and conditions of use.
  4. #include "tiny_xml.hpp"
  5. #include <cassert>
  6. #include <cstring>
  7. namespace
  8. {
  9. void eat_whitespace( char & c, std::istream & in )
  10. {
  11. while ( c == ' ' || c == '\r' || c == '\n' || c == '\t' )
  12. in.get( c );
  13. }
  14. std::string get_name( char & c, std::istream & in )
  15. {
  16. std::string result;
  17. eat_whitespace( c, in );
  18. while ( std::strchr(
  19. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.", c )
  20. != 0 )
  21. {
  22. result += c;
  23. if(!in.get( c ))
  24. throw std::string("xml: unexpected eof");
  25. }
  26. return result;
  27. }
  28. void eat_delim( char & c, std::istream & in,
  29. char delim, const std::string & msg )
  30. {
  31. eat_whitespace( c, in );
  32. if ( c != delim )
  33. throw std::string("xml syntax error, expected ") + delim
  34. + " (" + msg + ")";
  35. in.get( c );
  36. }
  37. std::string get_value( char & c, std::istream & in )
  38. {
  39. std::string result;
  40. while ( c != '\"' )
  41. {
  42. result += c;
  43. in.get( c );
  44. }
  45. in.get( c );
  46. return result;
  47. }
  48. }
  49. namespace boost
  50. {
  51. namespace tiny_xml
  52. {
  53. // parse -----------------------------------------------------------------//
  54. element_ptr parse( std::istream & in, const std::string & msg )
  55. {
  56. char c = 0; // current character
  57. element_ptr e( new element );
  58. if(!in.get( c ))
  59. throw std::string("xml: unexpected eof");
  60. if ( c == '<' )
  61. if(!in.get( c ))
  62. throw std::string("xml: unexpected eof");
  63. e->name = get_name( c, in );
  64. eat_whitespace( c, in );
  65. // attributes
  66. while ( c != '>' )
  67. {
  68. attribute a;
  69. a.name = get_name( c, in );
  70. eat_delim( c, in, '=', msg );
  71. eat_delim( c, in, '\"', msg );
  72. a.value = get_value( c, in );
  73. e->attributes.push_back( a );
  74. eat_whitespace( c, in );
  75. }
  76. if(!in.get( c )) // next after '>'
  77. throw std::string("xml: unexpected eof");
  78. eat_whitespace( c, in );
  79. // sub-elements
  80. while ( c == '<' )
  81. {
  82. if ( in.peek() == '/' ) break;
  83. e->elements.push_back( parse( in, msg ) );
  84. in.get( c ); // next after '>'
  85. eat_whitespace( c, in );
  86. }
  87. // content
  88. if ( c != '<' )
  89. {
  90. e->content += '\n';
  91. while ( c != '<' )
  92. {
  93. e->content += c;
  94. if(!in.get( c ))
  95. throw std::string("xml: unexpected eof");
  96. }
  97. }
  98. assert( c == '<' );
  99. if(!in.get( c )) // next after '<'
  100. throw std::string("xml: unexpected eof");
  101. eat_delim( c, in, '/', msg );
  102. std::string end_name( get_name( c, in ) );
  103. if ( e->name != end_name )
  104. throw std::string("xml syntax error: beginning name ")
  105. + e->name + " did not match end name " + end_name
  106. + " (" + msg + ")";
  107. eat_delim( c, in, '>', msg );
  108. return e;
  109. }
  110. // write ---------------------------------------------------------------//
  111. void write( const element & e, std::ostream & out )
  112. {
  113. out << "<" << e.name;
  114. if ( !e.attributes.empty() )
  115. {
  116. for( attribute_list::const_iterator itr = e.attributes.begin();
  117. itr != e.attributes.end(); ++itr )
  118. {
  119. out << " " << itr->name << "=\"" << itr->value << "\"";
  120. }
  121. }
  122. out << ">";
  123. if ( !e.elements.empty() )
  124. {
  125. out << "\n";
  126. for( element_list::const_iterator itr = e.elements.begin();
  127. itr != e.elements.end(); ++itr )
  128. {
  129. write( **itr, out );
  130. }
  131. }
  132. if ( !e.content.empty() )
  133. {
  134. out << e.content;
  135. }
  136. out << "</" << e.name << ">\n";
  137. }
  138. } // namespace tiny_xml
  139. } // namespace boost
粤ICP备19079148号