tiny_xml.cpp 4.1 KB

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