00001 #include <iostream>
00002
00003 namespace judo
00004 {
00005 namespace XPath
00006 {
00007 class PositionOp : public Op
00008 {
00009 public:
00010 PositionOp(int pos) : Op(OP_POSITION, ""), _pos(pos)
00011 { }
00012
00013 bool isValid(XPath::Value* ctxt)
00014 {
00015 Value::ElemList elems = ctxt->getList();
00016
00017 Value::ElemList::iterator it = elems.begin();
00018 for (int x = 1; (x < _pos) && (it != elems.end()); x++) it++;
00019 if (it == elems.end())
00020 return false;
00021
00022 ctxt->setElems(*it);
00023
00024 return true;
00025 }
00026 private:
00027 int _pos;
00028 };
00029
00030 class ContextOp : public Op
00031 {
00032 public:
00033 ContextOp(Op* op) : Op(OP_CONTEXT_CONDITION, ""), _op(op)
00034 { }
00035
00036 ~ContextOp()
00037 {
00038 delete _op;
00039 }
00040
00041 bool isValid(XPath::Value* ctxt)
00042 {
00043 Value::ElemList& elems = ctxt->getList();
00044 Value::ElemList::iterator it = elems.begin();
00045 while (it != elems.end())
00046 {
00047 Value::ElemList::iterator next = it;
00048 ++next;
00049
00050 Value* tmp_ctxt = new Value(*it);
00051 tmp_ctxt->in_context(true);
00052
00053 if (!_op->isValid(tmp_ctxt))
00054 {
00055 elems.erase(it);
00056 }
00057
00058 it = next;
00059 }
00060
00061 if (elems.empty())
00062 return false;
00063
00064 return true;
00065 }
00066
00067 private:
00068 Op* _op;
00069 };
00070
00071 class NodeOp : public Op
00072 {
00073 public:
00074 NodeOp(const std::string& name, bool is_root=false) :
00075 Op(Op::OP_NODE, name), _is_root(is_root)
00076 { }
00077
00078 std::string calcStr(judo::Element* elem)
00079 {
00080 return elem->getCDATA();
00081 }
00082
00083 bool isValid(XPath::Value* ctxt)
00084 {
00085 judo::Element* elem = NULL;
00086
00087
00088 if (_is_root)
00089 {
00090 elem = ctxt->getElem();
00091 if (elem->getName() != _value)
00092 return false;
00093 return true;
00094 }
00095
00096
00097 Value::ElemList& elems = ctxt->getList();
00098 Value::ElemList valid_elems;
00099
00100 if (elems.empty())
00101 {
00102 elem = ctxt->getElem();
00103 if (!elem)
00104 return false;
00105 elems.push_back(elem);
00106 }
00107
00108 for (Value::ElemList::iterator it = elems.begin();
00109 it != elems.end(); it++)
00110 {
00111 bool valid = false;
00112
00113 elem = *it;
00114
00115 judo::Element::iterator sit = elem->begin();
00116 for (; sit != elem->end(); sit++)
00117 {
00118 if ((*sit)->getType() == Node::ntElement &&
00119 (_value == "*") || ((*sit)->getName() == _value))
00120 {
00121 if (ctxt->in_context())
00122 valid = true;
00123 else
00124 valid_elems.push_back(static_cast<judo::Element*>(*sit));
00125 }
00126 }
00127 if (valid)
00128 valid_elems.push_back(static_cast<judo::Element*>(*it));
00129 }
00130
00131
00132 if (valid_elems.empty())
00133 return false;
00134
00135 ctxt->setElems(valid_elems);
00136
00137 return true;
00138 }
00139 private:
00140 bool _is_root;
00141 };
00142
00143 class AllOp : public Op
00144 {
00145 public:
00146 AllOp(const std::string& name) : Op(Op::OP_ALL, name)
00147 { }
00148
00149 bool isValid(XPath::Value* ctxt)
00150 {
00151 judo::Element* elem = NULL;
00152
00153
00154 if (_is_root)
00155 {
00156 elem = ctxt->getElem();
00157 if (elem->getName() != _value)
00158 return false;
00159 return true;
00160 }
00161
00162
00163 Value::ElemList& elems = ctxt->getList();
00164 Value::ElemList valid_elems;
00165
00166 if (elems.empty())
00167 {
00168 return false;
00169 }
00170
00171 for (Value::ElemList::iterator it = elems.begin();
00172 it != elems.end(); it++)
00173 {
00174 descend(static_cast<judo::Element*>(*it),&valid_elems);
00175 }
00176
00177
00178 if (valid_elems.empty())
00179 return false;
00180
00181 ctxt->setElems(valid_elems);
00182
00183 return true;
00184 }
00185
00186 void descend(judo::Element* elem, Value::ElemList* valid_elems)
00187 {
00188 judo::Element* temp_elem = NULL;
00189
00190 if ((_value == "*") || (elem->getName() == _value))
00191 {
00192 valid_elems->push_back(elem);
00193 }
00194
00195 judo::Element::iterator it = elem->begin();
00196 for (; it != elem->end(); it++)
00197 {
00198 if ((*it)->getType() == Node::ntElement)
00199 {
00200 temp_elem = static_cast<judo::Element*>(*it);
00201
00202 descend(temp_elem,valid_elems);
00203 }
00204 }
00205 }
00206
00207 private:
00208 bool _is_root;
00209 };
00210
00211 class EqualOp : public Op
00212 {
00213 public:
00214 EqualOp(Op* op_lh, Op* op_rh) :
00215 Op(Op::OP_EQUAL, ""), _op_lh(op_lh), _op_rh(op_rh)
00216 { }
00217
00218 ~EqualOp()
00219 {
00220 delete _op_lh;
00221 delete _op_rh;
00222 }
00223
00224 bool isValid(XPath::Value* ctxt)
00225 {
00226 XPath::Value* tmp_ctxt = new Value(ctxt->getList());
00227
00228 if (!_op_lh->isValid(tmp_ctxt) || !_op_rh->isValid(tmp_ctxt))
00229 return false;
00230
00231 Value::ElemList& elems = tmp_ctxt->getList();
00232 Value::ElemList::iterator it = elems.begin();
00233
00234 while (it != elems.end())
00235 {
00236 Value::ElemList::iterator next = it;
00237 ++next;
00238
00239 judo::Element* elem = *it;
00240 if (_op_lh->calcStr(elem) != _op_rh->calcStr(elem))
00241 {
00242 elems.erase(it);
00243 }
00244 it = next;
00245 }
00246
00247 if (elems.empty())
00248 {
00249 Value::ElemList& elems = ctxt->getList();
00250 elems.clear();
00251 return false;
00252 }
00253
00254 return true;
00255 }
00256
00257 private:
00258 Op* _op_lh;
00259 Op* _op_rh;
00260 };
00261
00262 class NotEqualOp : public Op
00263 {
00264 public:
00265 NotEqualOp(Op* op_lh, Op* op_rh) :
00266 Op(Op::OP_NOTEQUAL, ""), _op_lh(op_lh), _op_rh(op_rh)
00267 { }
00268
00269 ~NotEqualOp()
00270 {
00271 delete _op_lh;
00272 delete _op_rh;
00273 }
00274
00275 bool isValid(XPath::Value* ctxt)
00276 {
00277 XPath::Value* tmp_ctxt = new Value(ctxt->getList());
00278
00279 if (!_op_lh->isValid(tmp_ctxt) || !_op_rh->isValid(tmp_ctxt))
00280 return false;
00281
00282 Value::ElemList& elems = tmp_ctxt->getList();
00283 Value::ElemList::iterator it = elems.begin();
00284
00285 while (it != elems.end())
00286 {
00287 Value::ElemList::iterator next = it;
00288 ++next;
00289
00290 judo::Element* elem = *it;
00291 if (_op_lh->calcStr(elem) == _op_rh->calcStr(elem))
00292 {
00293 elems.erase(it);
00294 }
00295 it = next;
00296 }
00297
00298 if (elems.empty())
00299 {
00300 Value::ElemList& elems = ctxt->getList();
00301 elems.clear();
00302 return false;
00303 }
00304
00305 return true;
00306 }
00307
00308 private:
00309 Op* _op_lh;
00310 Op* _op_rh;
00311 };
00312
00313 class AttributeOp : public Op
00314 {
00315 public:
00316 AttributeOp(const std::string& name) : Op(Op::OP_ATTRIBUTE, name)
00317 { }
00318
00319 std::string getValue()
00320 {
00321 return _val;
00322 }
00323
00324 std::string calcStr(judo::Element* elem)
00325 {
00326 return elem->getAttrib(_value);
00327 }
00328
00329 bool isValid(XPath::Value* ctxt)
00330 {
00331 Value::ElemList& elems = ctxt->getList();
00332 Value::ElemList::iterator it = elems.begin();
00333
00334 Value::ValueList values;
00335 Value::AttribMap attribs;
00336
00337 while (it != elems.end())
00338 {
00339 Value::ElemList::iterator next = it;
00340 ++next;
00341
00342 judo::Element* elem = *it;
00343 if (_value != "*")
00344 {
00345 _val = calcStr(elem);
00346 if (_val.empty())
00347 elems.erase(it);
00348 else
00349 values.push_back(_val);
00350 }
00351 else
00352 {
00353 Value::AttribMap temp_attribs = elem->getAttribs();
00354 if (temp_attribs.empty())
00355 {
00356 elems.erase(it);
00357 }
00358 else
00359 {
00360 Value::AttribMap::const_iterator ait = temp_attribs.begin();
00361 while(ait != temp_attribs.end())
00362 {
00363 attribs[ait->first] = ait->second;
00364 ait++;
00365 }
00366 }
00367 }
00368
00369 it = next;
00370 }
00371
00372 if (elems.empty())
00373 {
00374
00375 return false;
00376 }
00377
00378 ctxt->setValues(values);
00379 ctxt->setAttribs(attribs);
00380
00381 return true;
00382 }
00383 private:
00384 std::string _val;
00385 };
00386
00387 class AndOp : public Op
00388 {
00389 public:
00390 AndOp(Op* lh, Op* rh) : Op(OP_AND, "and"), _lh(lh), _rh(rh)
00391 { }
00392
00393 ~AndOp()
00394 {
00395 delete _lh;
00396 delete _rh;
00397 }
00398
00399 bool isValid(XPath::Value* ctxt)
00400 {
00401 if (_lh->isValid(ctxt) && _rh->isValid(ctxt))
00402 return true;
00403 else
00404 return false;
00405 }
00406 private:
00407 Op* _lh;
00408 Op* _rh;
00409 };
00410
00411 class OrOp : public Op
00412 {
00413 public:
00414 OrOp(Op* lh, Op* rh) : Op(OP_OR, "or"), _lh(lh), _rh(rh)
00415 { }
00416
00417 ~OrOp()
00418 {
00419 delete _lh;
00420 delete _rh;
00421 }
00422
00423 bool isValid(XPath::Value* ctxt)
00424 {
00425 Value::ElemList& elems = ctxt->getList();
00426 Value::ElemList::iterator it = elems.begin();
00427 while (it != elems.end())
00428 {
00429 Value::ElemList::iterator next = it;
00430 ++next;
00431
00432 Value* tmp_ctxt_l = new Value(*it);
00433 tmp_ctxt_l->in_context(true);
00434 Value* tmp_ctxt_r = new Value(*it);
00435 tmp_ctxt_r->in_context(true);
00436 if (!_lh->isValid(tmp_ctxt_l) && !_rh->isValid(tmp_ctxt_r))
00437 {
00438 elems.erase(it);
00439 }
00440
00441 it = next;
00442 }
00443
00444 if (elems.empty())
00445 return false;
00446
00447 return true;
00448 }
00449 private:
00450 Op* _lh;
00451 Op* _rh;
00452 };
00453
00454 class FunctionOp : public Op
00455 {
00456 public:
00457 FunctionOp(const std::string& func) : Op(OP_FUNCTION, func) , _closed(false)
00458 { }
00459
00460 ~FunctionOp()
00461 {
00462 while (!_arg_list.empty())
00463 {
00464 Op *op = _arg_list.back();
00465 _arg_list.pop_back();
00466 delete op;
00467 }
00468 }
00469
00470 bool isValid(XPath::Value* ctxt)
00471 {
00472 if (_value == "text")
00473 return function_text(ctxt);
00474
00475 if (_value == "name")
00476 return function_name(ctxt);
00477
00478 if (_value == "not")
00479 return function_not(ctxt);
00480
00481 if (_value == "starts-with")
00482 return function_startswith(ctxt);
00483
00484 std::cerr << "Unknown query function " << _value << "()" << std::endl;
00485 return false;
00486 }
00487
00488 std::string calcStr(judo::Element* elem)
00489 {
00490 if (_value == "text")
00491 return value_text(elem);
00492
00493 if (_value == "name")
00494 return value_name(elem);
00495
00496 std::cerr << "Unknown internal value function funtion_" << _value << "_value()" << std::endl;
00497 return "";
00498 }
00499
00500 void addArg(Op* arg)
00501 {
00502 _arg_list.push_back(arg);
00503 }
00504
00505 bool function_text(XPath::Value* ctxt)
00506 {
00507 Value::ElemList& elems = ctxt->getList();
00508 Value::ElemList::iterator it = elems.begin();
00509
00510 Value::ValueList values;
00511
00512 while (it != elems.end())
00513 {
00514 std::string value;
00515 Value::ElemList::iterator next = it;
00516 ++next;
00517
00518 judo::Element* elem = *it;
00519 value = value_text(elem);
00520 values.push_back(value);
00521
00522 it = next;
00523 }
00524
00525 if (elems.empty())
00526 {
00527 return false;
00528 }
00529
00530 ctxt->setValues(values);
00531
00532 return true;
00533 }
00534
00535 std::string value_text(judo::Element* elem)
00536 {
00537 return elem->getCDATA();
00538 }
00539
00540 bool function_name(XPath::Value* ctxt)
00541 {
00542 Value::ElemList& elems = ctxt->getList();
00543 Value::ElemList::iterator it = elems.begin();
00544
00545 Value::ValueList values;
00546
00547 while (it != elems.end())
00548 {
00549 std::string value;
00550 Value::ElemList::iterator next = it;
00551 ++next;
00552
00553 judo::Element* elem = *it;
00554 value = value_name(elem);
00555 values.push_back(value);
00556
00557 it = next;
00558 }
00559
00560 if (elems.empty())
00561 {
00562 return false;
00563 }
00564
00565 ctxt->setValues(values);
00566
00567 return true;
00568 }
00569
00570 std::string value_name(judo::Element* elem)
00571 {
00572 return elem->getName();
00573 }
00574
00575 bool function_not(XPath::Value* ctxt)
00576 {
00577 Value::ElemList& elems = ctxt->getList();
00578 Value::ElemList::iterator it = elems.begin();
00579
00580 while (it != elems.end())
00581 {
00582 std::string value;
00583 Value::ElemList::iterator next = it;
00584 ++next;
00585
00586 Value* tmp_ctxt = new Value(*it);
00587 tmp_ctxt->in_context(true);
00588
00589 if (_arg_list[0]->isValid(tmp_ctxt))
00590 {
00591 elems.erase(it);
00592 }
00593
00594 it = next;
00595 }
00596
00597 if (elems.empty())
00598 {
00599 return false;
00600 }
00601
00602 return true;
00603 }
00604
00605 bool function_startswith(XPath::Value* ctxt)
00606 {
00607 Value::ElemList& elems = ctxt->getList();
00608 Value::ElemList::iterator it = elems.begin();
00609
00610 Query::OpList::iterator arg_it = _arg_list.begin();
00611
00612 while (it != elems.end())
00613 {
00614 std::string value;
00615 Value::ElemList::iterator next = it;
00616 ++next;
00617
00618 judo::Element* elem = *it;
00619 std::string val1 = _arg_list[0]->calcStr(elem);
00620 std::string val2 = _arg_list[1]->calcStr(elem);
00621
00622 if (val1.find(val2,0) != 0)
00623 {
00624 elems.erase(it);
00625 }
00626
00627 it = next;
00628 }
00629
00630 if (elems.empty())
00631 {
00632 return false;
00633 }
00634
00635 return true;
00636 }
00637
00638 private:
00639 Query::OpList _arg_list;
00640 bool _closed;
00641 };
00642
00643 };
00644 };