00001 00002 #ifndef XPATH_H 00003 #define XPATH_H 00004 00005 #include "judo.hpp" 00006 00007 #include <vector> 00008 #include <iostream> 00009 00010 namespace judo 00011 { 00012 namespace XPath 00013 { 00017 class Value 00018 { 00019 public: 00020 typedef std::list<judo::Element*> ElemList; 00021 typedef std::list<std::string> ValueList; 00022 typedef std::map<std::string,std::string> AttribMap; 00023 00024 Value(judo::Element* elem) 00025 { 00026 _elems.push_back(elem); 00027 _matched = false; 00028 _in_context = false; 00029 } 00030 00031 Value(ElemList& elems) : _elems(elems) 00032 { 00033 _matched = false; 00034 _in_context = false; 00035 } 00036 00037 Value(const std::string value) 00038 { 00039 _values.push_back(value); 00040 _matched = false; 00041 _in_context = false; 00042 } 00043 00044 Value(ValueList& values) : _values(values) 00045 { 00046 _matched = false; 00047 _in_context = false; 00048 } 00049 00050 Value() 00051 { 00052 _matched = false; 00053 _in_context = false; 00054 } 00055 00056 judo::Element* getElem() const { return _elems.front(); } 00057 ElemList& getList() { return _elems; } 00058 void setElems(ElemList& elems) { _elems = elems; } 00059 void setElems(judo::Element* elem) 00060 { 00061 _elems.clear(); 00062 _elems.push_back(elem); 00063 } 00064 00065 const std::string getValue() const { return _values.front(); } 00066 ValueList& getValues() { return _values; } 00067 void setValues(ValueList& values) { _values = values; } 00068 00069 const std::string getAttrib(const std::string& name) const 00070 { 00071 AttribMap::const_iterator it = _attribs.find(name); 00072 if (it != _attribs.end()) 00073 return it->second; 00074 else 00075 return ""; 00076 } 00077 AttribMap& getAttribs() { return _attribs; } 00078 void setAttribs(AttribMap& attribs) { _attribs = attribs; } 00079 00080 void setMatch(const bool matched) 00081 { 00082 _matched = matched; 00083 } 00084 00085 bool check() 00086 { 00087 return _matched; 00088 } 00089 00090 bool in_context() 00091 { 00092 return _in_context; 00093 } 00094 00095 bool in_context(bool in_context) 00096 { 00097 _in_context = in_context; 00098 return _in_context; 00099 } 00100 00101 private: 00102 ElemList _elems; 00103 ValueList _values; 00104 AttribMap _attribs; 00105 bool _matched; 00106 bool _in_context; 00107 }; 00108 00109 class Op 00110 { 00111 public: 00112 typedef std::vector<Op*> OpList; 00113 enum Type 00114 { 00115 OP_NODE, 00116 OP_ALL, 00117 OP_ATTRIBUTE, 00118 OP_CONTEXT_CONDITION, 00119 OP_LITERAL, 00120 OP_POSITION, 00121 OP_EQUAL, 00122 OP_NOTEQUAL, 00123 OP_AND, 00124 OP_OR, 00125 OP_FUNCTION 00126 }; 00127 00128 Op(Type op, const std::string& value) : 00129 _op(op), _value(value) 00130 { } 00131 00132 virtual ~Op() 00133 { } 00134 00135 virtual std::string getValue() 00136 { 00137 return _value; 00138 } 00139 00140 virtual std::string calcStr(judo::Element* elem) 00141 { 00142 return _value; 00143 } 00144 00145 virtual bool isValid(XPath::Value* ctxt) 00146 { 00147 return true; 00148 } 00149 00150 void display() 00151 { 00152 std::string type_str; 00153 switch(_op) 00154 { 00155 case OP_NODE: 00156 type_str = "NODE"; 00157 break; 00158 case OP_ATTRIBUTE: 00159 type_str = "ATTRIBUTE"; 00160 break; 00161 case OP_CONTEXT_CONDITION: 00162 type_str = "CONTEXT_CONDITION"; 00163 break; 00164 case OP_LITERAL: 00165 type_str = "LITERAL"; 00166 break; 00167 case OP_POSITION: 00168 type_str = "POSITION"; 00169 break; 00170 case OP_EQUAL: 00171 type_str = "EQUAL"; 00172 break; 00173 case OP_NOTEQUAL: 00174 type_str = "NOTEQUAL"; 00175 break; 00176 case OP_FUNCTION: 00177 type_str = "FUNCTION"; 00178 break; 00179 default: 00180 type_str = "UNKNOWN"; 00181 break; 00182 }; 00183 00184 std::cout << "OP: type(" << type_str << ") value(" << _value << ")" 00185 << std::endl; 00186 } 00187 00188 bool isType(Type type) 00189 { 00190 return (_op == type); 00191 } 00192 00193 virtual void setArgs(OpList& args) 00194 { 00195 } 00196 00197 virtual bool isClosed() 00198 { 00199 return true; 00200 } 00201 00202 virtual void close() 00203 { 00204 } 00205 00206 protected: 00207 Type _op; 00208 std::string _value; 00209 }; 00210 00214 class Query 00215 { 00216 public: 00217 typedef std::vector<Op*> OpList; 00218 Query(const std::string query) : 00219 _query(query) 00220 { 00221 _tokens.push_back('/'); 00222 _tokens.push_back('['); 00223 _tokens.push_back(']'); 00224 _tokens.push_back('@'); 00225 _tokens.push_back('\"'); 00226 _tokens.push_back('\''); 00227 _tokens.push_back('='); 00228 _tokens.push_back('!'); 00229 _tokens.push_back('('); 00230 _tokens.push_back(')'); 00231 _tokens.push_back(':'); 00232 _tokens.push_back(' '); 00233 _tokens.push_back(','); 00234 00235 if (!parseQuery()) 00236 throw Invalid(); 00237 } 00238 00239 ~Query() 00240 { 00241 while (!_ops.empty()) 00242 { 00243 Op *op = _ops.back(); 00244 _ops.pop_back(); 00245 delete op; 00246 } 00247 } 00248 00255 bool check(const judo::Element& root); 00262 Value* execute(judo::Element* root); 00263 00264 const OpList& getOps() const 00265 { return _ops; }; 00266 00267 class Invalid{}; 00268 private: 00269 std::list<char> _tokens; 00270 std::string _query; 00271 OpList _ops; 00272 00273 bool parseQuery(); 00274 char getNextToken(std::string::size_type& cur); 00275 std::string getNextIdentifier(std::string::size_type& pos); 00276 Op* getOp(std::string::size_type& pos, char in_context = 0); 00277 00278 }; 00279 }; 00280 } 00281 00282 #endif // ifndef XPATH_H