00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <string.h>
00026
00027 #include "XmlReader.h"
00028
00029
00030 int yyFlexLexer::yylex() { return 0; }
00031
00032 namespace Tanl {
00033 namespace XML {
00034
00035 using namespace std;
00036
00037 XmlReader::XmlReader(istream& stream) :
00038 NodeType(None),
00039 state(Initial),
00040 depth(0),
00041 isEmptyElement(false),
00042 scanner(&stream)
00043 {
00044 }
00045
00046 bool XmlReader::Read() throw(XmlException)
00047 {
00048 if (Eof())
00049 return false;
00050 state = Interactive;
00051 while (true) {
00052 Name.clear();
00053 Value.clear();
00054 int tokType = scanner.scan();
00055 switch (tokType) {
00056 case XML_DECL:
00057 NodeType = XmlDeclaration;
00058 Name = "xml";
00059 Value = string(scanner.YYText()+5, scanner.YYLeng()-7);
00060 return true;
00061 case PROC_INST:
00062 NodeType = ProcessingInstruction;
00063
00064 Value = string(scanner.YYText()+2, scanner.YYLeng()-4);
00065 return true;
00066 case DOCTYPE:
00067 NodeType = DocumentType;
00068
00069 Value = string(scanner.YYText()+10, scanner.YYLeng()-11);
00070 return true;
00071 case COMMENT:
00072 NodeType = Comment;
00073 Value = string(scanner.YYText()+4, scanner.YYLeng()-7);
00074 return true;
00075 case TAG_OPEN: {
00076 attrs.clear();
00077 attrIndex = 0;
00078 tokType = scanner.scan();
00079 if (tokType == ID) {
00080 NodeType = Element;
00081 Name = tagName = scanner.YYText();
00082 } else if (tokType == EndOfFile) {
00083 state = Error;
00084 throw XmlException("Premature EOF");
00085 } else {
00086 state = Error;
00087 throw XmlException("Syntax error: no element name");
00088 }
00089
00090 attrIndex = -1;
00091 bool moreAttr = true;
00092 while (moreAttr) {
00093 tokType = scanner.scan();
00094 switch (tokType) {
00095 case ID: {
00096 string name = scanner.YYText();
00097 switch (scanner.scan()) {
00098 case EQ:
00099 switch (scanner.scan()) {
00100 case VAL: {
00101 string value = scanner.YYText();
00102 attrs.push_back(NodeAttr(name, value));
00103 continue;
00104 }
00105 case EOF:
00106 state = Error;
00107 throw XmlException("Premature EOF");
00108 }
00109 break;
00110 case EOF:
00111 state = Error;
00112 throw XmlException("Premature EOF");
00113 default:
00114 state = Error;
00115 throw XmlException("Syntax error: no equal sign");
00116 }
00117 }
00118 case TAG_EMPTY:
00119 isEmptyElement = true;
00120 tagName.clear();
00121 return true;
00122 case TAG_END:
00123 moreAttr = false;
00124 break;
00125 }
00126 }
00127 ++depth;
00128 return true;
00129 }
00130 case TAG_CLOSE:
00131 tagName.clear();
00132 if (depth) {
00133 NodeType = EndElement;
00134 char const* text = scanner.YYText()+2;
00135
00136 char const* end = strpbrk(text, " \n\r\t>");
00137 Name = string(text, end - text);
00138 --depth;
00139 return true;
00140 } else {
00141 state = Error;
00142 throw XmlException("Syntax error: extra close tag");
00143 }
00144 case CHARACTERS:
00145 NodeType = Text;
00146 Value = scanner.YYText();
00147 return true;
00148 case RAW_CHARS:
00149 NodeType = CDATA;
00150 Value = scanner.YYText();
00151 return true;
00152 case WHITESPACE:
00153 NodeType = Whitespace;
00154 Value = scanner.YYText();
00155 return true;
00156 case EoF:
00157 state = EndOfFile;
00158 return false;
00159 default:
00160 state = Error;
00161 throw XmlException("Syntax error: ");
00162 }
00163 }
00164 }
00165
00166 bool XmlReader::MoveToFirstAttribute()
00167 {
00168 if (!attrs.size())
00169 return false;
00170 attrIndex = 0;
00171 NodeType = Attribute;
00172 Name = attrs[attrIndex].name;
00173 Value = attrs[attrIndex].value;
00174 return true;
00175 }
00176
00177 bool XmlReader::MoveToNextAttribute()
00178 {
00179 if (++attrIndex < attrs.size()) {
00180 NodeType = Attribute;
00181 Name = attrs[attrIndex].name;
00182 Value = attrs[attrIndex].value;
00183 return true;
00184 } else
00185 return false;
00186 }
00187
00188 }
00189 }