1
0

tiny_xml.cpp 3.9 KB

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