1
2
3
4
5
6 #include <sngxml/xpath/XPathExpr.hpp>
7 #include <sngxml/xpath/XPathFunction.hpp>
8 #include <sngxml/dom/CharacterData.hpp>
9 #include <sngxml/dom/Document.hpp>
10 #include <sngxml/dom/Element.hpp>
11 #include <soulng/util/Unicode.hpp>
12 #include <map>
13 #include <sstream>
14
15 namespace sngxml { namespace xpath {
16
17 using namespace soulng::unicode;
18
19 XPathExpr::XPathExpr()
20 {
21 }
22
23 XPathExpr::~XPathExpr()
24 {
25 }
26
27 XPathUnaryExpr::XPathUnaryExpr(XPathExpr* operand_) : operand(operand_)
28 {
29 }
30
31 XPathBinaryExpr::XPathBinaryExpr(XPathExpr* left_, XPathExpr* right_) : left(left_), right(right_)
32 {
33 }
34
35 XPathOrExpr::XPathOrExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
36 {
37 }
38
39 std::std::unique_ptr<XPathObject>XPathOrExpr::Evaluate(XPathContext&context)
40 {
41 XPathFunction* boolean = GetXPathLibraryFunction(U"boolean");
42 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
43 std::vector<XPathObject*> leftArgs;
44 leftArgs.push_back(left.get());
45 std::unique_ptr<XPathObject> leftAsBoolean = boolean->Evaluate(context, leftArgs);
46 if (leftAsBoolean->Type() != XPathObjectType::boolean)
47 {
48 throw std::runtime_error("boolean result expected");
49 }
50 if (static_cast<XPathBoolean*>(leftAsBoolean.get())->Value())
51 {
52 return leftAsBoolean;
53 }
54 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
55 std::vector<XPathObject*> rightArgs;
56 rightArgs.push_back(right.get());
57 std::unique_ptr<XPathObject> rightAsBoolean = boolean->Evaluate(context, rightArgs);
58 if (rightAsBoolean->Type() != XPathObjectType::boolean)
59 {
60 throw std::runtime_error("boolean result expected");
61 }
62 return rightAsBoolean;
63 }
64
65 std::std::unique_ptr<dom::Node>XPathOrExpr::ToDom() const
66 {
67 std::unique_ptr<dom::Element> element(new dom::Element(U"or"));
68 element->AppendChild(Left()->ToDom());
69 element->AppendChild(Right()->ToDom());
70 return std::unique_ptr<dom::Node>(element.release());
71 }
72
73 XPathAndExpr::XPathAndExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
74 {
75 }
76
77 std::std::unique_ptr<XPathObject>XPathAndExpr::Evaluate(XPathContext&context)
78 {
79 XPathFunction* boolean = GetXPathLibraryFunction(U"boolean");
80 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
81 std::vector<XPathObject*> leftArgs;
82 leftArgs.push_back(left.get());
83 std::unique_ptr<XPathObject> leftAsBoolean = boolean->Evaluate(context, leftArgs);
84 if (leftAsBoolean->Type() != XPathObjectType::boolean)
85 {
86 throw std::runtime_error("boolean result expected");
87 }
88 if (!static_cast<XPathBoolean*>(leftAsBoolean.get())->Value())
89 {
90 return leftAsBoolean;
91 }
92 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
93 std::vector<XPathObject*> rightArgs;
94 rightArgs.push_back(right.get());
95 std::unique_ptr<XPathObject> rightAsBoolean = boolean->Evaluate(context, rightArgs);
96 if (rightAsBoolean->Type() != XPathObjectType::boolean)
97 {
98 throw std::runtime_error("boolean result expected");
99 }
100 return rightAsBoolean;
101 }
102
103 std::std::unique_ptr<dom::Node>XPathAndExpr::ToDom() const
104 {
105 std::unique_ptr<dom::Element> element(new dom::Element(U"and"));
106 element->AppendChild(Left()->ToDom());
107 element->AppendChild(Right()->ToDom());
108 return std::unique_ptr<dom::Node>(element.release());
109 }
110
111 std::std::unique_ptr<XPathObject>CompareNodeSets(XPathContext&context, XPathObject*left, XPathObject*right, OperatorcomparisonOp)
112 {
113 if (left->Type() == XPathObjectType::nodeSet && right->Type() == XPathObjectType::nodeSet)
114 {
115 XPathNodeSet* leftNodeSet = static_cast<XPathNodeSet*>(left);
116 XPathNodeSet* rightNodeSet = static_cast<XPathNodeSet*>(right);
117 int n = leftNodeSet->Length();
118 for (int i = 0; i < n; ++i)
119 {
120 sngxml::dom::Node* leftNode = (*leftNodeSet)[i];
121 std::u32string leftStr = StringValue(leftNode);
122 int m = rightNodeSet->Length();
123 for (int j = 0; j < m; ++j)
124 {
125 sngxml::dom::Node* rightNode = (*rightNodeSet)[j];
126 std::u32string rightStr = StringValue(rightNode);
127 switch (comparisonOp)
128 {
129 case Operator::equal:
130 {
131 if (leftStr == rightStr)
132 {
133 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
134 return result;
135 }
136 break;
137 }
138 case Operator::notEqual:
139 {
140 if (leftStr != rightStr)
141 {
142 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
143 return result;
144 }
145 break;
146 }
147 case Operator::less:
148 {
149 if (leftStr < rightStr)
150 {
151 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
152 return result;
153 }
154 break;
155 }
156 case Operator::greater:
157 {
158 if (leftStr > rightStr)
159 {
160 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
161 return result;
162 }
163 break;
164 }
165 case Operator::lessOrEqual:
166 {
167 if (leftStr <= rightStr)
168 {
169 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
170 return result;
171 }
172 break;
173 }
174 case Operator::greaterOrEqual:
175 {
176 if (leftStr >= rightStr)
177 {
178 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
179 return result;
180 }
181 break;
182 }
183 }
184 }
185 }
186 }
187 else if (left->Type() == XPathObjectType::nodeSet)
188 {
189 XPathFunction* numberFunction = GetXPathLibraryFunction(U"number");
190 XPathFunction* booleanFunction = GetXPathLibraryFunction(U"boolean");
191 if (right->Type() == XPathObjectType::number)
192 {
193 double rightNumber = static_cast<XPathNumber*>(right)->Value();
194 XPathNodeSet* leftNodeSet = static_cast<XPathNodeSet*>(left);
195 int n = leftNodeSet->Length();
196 for (int i = 0; i < n; ++i)
197 {
198 sngxml::dom::Node* leftNode = (*leftNodeSet)[i];
199 XPathString leftAsString(StringValue(leftNode));
200 std::vector<XPathObject*> leftArgs;
201 leftArgs.push_back(&leftAsString);
202 std::unique_ptr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
203 if (leftAsNumber->Type() != XPathObjectType::number)
204 {
205 throw std::runtime_error("number result expected");
206 }
207 double leftNumber = static_cast<XPathNumber*>(leftAsNumber.get())->Value();
208 switch (comparisonOp)
209 {
210 case Operator::equal:
211 {
212 if (leftNumber == rightNumber)
213 {
214 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
215 return result;
216 }
217 break;
218 }
219 case Operator::notEqual:
220 {
221 if (leftNumber != rightNumber)
222 {
223 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
224 return result;
225 }
226 break;
227 }
228 case Operator::less:
229 {
230 if (leftNumber < rightNumber)
231 {
232 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
233 return result;
234 }
235 break;
236 }
237 case Operator::greater:
238 {
239 if (leftNumber > rightNumber)
240 {
241 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
242 return result;
243 }
244 break;
245 }
246 case Operator::lessOrEqual:
247 {
248 if (leftNumber <= rightNumber)
249 {
250 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
251 return result;
252 }
253 break;
254 }
255 case Operator::greaterOrEqual:
256 {
257 if (leftNumber >= rightNumber)
258 {
259 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
260 return result;
261 }
262 break;
263 }
264 }
265 }
266 }
267 else if (right->Type() == XPathObjectType::string)
268 {
269 std::u32string rightString = static_cast<XPathString*>(right)->Value();
270 XPathNodeSet* leftNodeSet = static_cast<XPathNodeSet*>(left);
271 int n = leftNodeSet->Length();
272 for (int i = 0; i < n; ++i)
273 {
274 sngxml::dom::Node* leftNode = (*leftNodeSet)[i];
275 std::u32string leftString = StringValue(leftNode);
276 switch (comparisonOp)
277 {
278 case Operator::equal:
279 {
280 if (leftString == rightString)
281 {
282 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
283 return result;
284 }
285 break;
286 }
287 case Operator::notEqual:
288 {
289 if (leftString != rightString)
290 {
291 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
292 return result;
293 }
294 break;
295 }
296 case Operator::less:
297 {
298 if (leftString < rightString)
299 {
300 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
301 return result;
302 }
303 break;
304 }
305 case Operator::greater:
306 {
307 if (leftString > rightString)
308 {
309 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
310 return result;
311 }
312 break;
313 }
314 case Operator::lessOrEqual:
315 {
316 if (leftString <= rightString)
317 {
318 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
319 return result;
320 }
321 break;
322 }
323 case Operator::greaterOrEqual:
324 {
325 if (leftString >= rightString)
326 {
327 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
328 return result;
329 }
330 break;
331 }
332 }
333 }
334 }
335 else if (right->Type() == XPathObjectType::boolean)
336 {
337 bool rightBool = static_cast<XPathBoolean*>(right)->Value();
338 std::vector<XPathObject*> leftArgs;
339 leftArgs.push_back(left);
340 std::unique_ptr<XPathObject> leftAsBool = booleanFunction->Evaluate(context, leftArgs);
341 if (leftAsBool->Type() != XPathObjectType::boolean)
342 {
343 throw std::runtime_error("boolean result expected");
344 }
345 bool leftBool = static_cast<XPathBoolean*>(leftAsBool.get())->Value();
346 switch (comparisonOp)
347 {
348 case Operator::equal:
349 {
350 if (leftBool == rightBool)
351 {
352 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
353 return result;
354 }
355 break;
356 }
357 case Operator::notEqual:
358 {
359 if (leftBool != rightBool)
360 {
361 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
362 return result;
363 }
364 break;
365 }
366 case Operator::less:
367 {
368 if (leftBool < rightBool)
369 {
370 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
371 return result;
372 }
373 break;
374 }
375 case Operator::greater:
376 {
377 if (leftBool > rightBool)
378 {
379 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
380 return result;
381 }
382 break;
383 }
384 case Operator::lessOrEqual:
385 {
386 if (leftBool <= rightBool)
387 {
388 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
389 return result;
390 }
391 break;
392 }
393 case Operator::greaterOrEqual:
394 {
395 if (leftBool >= rightBool)
396 {
397 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
398 return result;
399 }
400 break;
401 }
402 }
403 }
404 }
405 else if (right->Type() == XPathObjectType::nodeSet)
406 {
407 XPathFunction* numberFunction = GetXPathLibraryFunction(U"number");
408 XPathFunction* booleanFunction = GetXPathLibraryFunction(U"boolean");
409 if (left->Type() == XPathObjectType::number)
410 {
411 double leftNumber = static_cast<XPathNumber*>(left)->Value();
412 XPathNodeSet* rightNodeSet = static_cast<XPathNodeSet*>(right);
413 int n = rightNodeSet->Length();
414 for (int i = 0; i < n; ++i)
415 {
416 sngxml::dom::Node* rightNode = (*rightNodeSet)[i];
417 XPathString rightAsString(StringValue(rightNode));
418 std::vector<XPathObject*> rightArgs;
419 rightArgs.push_back(&rightAsString);
420 std::unique_ptr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
421 if (rightAsNumber->Type() != XPathObjectType::number)
422 {
423 throw std::runtime_error("number result expected");
424 }
425 double rightNumber = static_cast<XPathNumber*>(rightAsNumber.get())->Value();
426 switch (comparisonOp)
427 {
428 case Operator::equal:
429 {
430 if (leftNumber == rightNumber)
431 {
432 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
433 return result;
434 }
435 break;
436 }
437 case Operator::notEqual:
438 {
439 if (leftNumber != rightNumber)
440 {
441 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
442 return result;
443 }
444 break;
445 }
446 case Operator::less:
447 {
448 if (leftNumber < rightNumber)
449 {
450 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
451 return result;
452 }
453 break;
454 }
455 case Operator::greater:
456 {
457 if (leftNumber > rightNumber)
458 {
459 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
460 return result;
461 }
462 break;
463 }
464 case Operator::lessOrEqual:
465 {
466 if (leftNumber <= rightNumber)
467 {
468 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
469 return result;
470 }
471 break;
472 }
473 case Operator::greaterOrEqual:
474 {
475 if (leftNumber >= rightNumber)
476 {
477 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
478 return result;
479 }
480 break;
481 }
482 }
483 }
484 }
485 else if (left->Type() == XPathObjectType::string)
486 {
487 std::u32string leftString = static_cast<XPathString*>(left)->Value();
488 XPathNodeSet* rightNodeSet = static_cast<XPathNodeSet*>(right);
489 int n = rightNodeSet->Length();
490 for (int i = 0; i < n; ++i)
491 {
492 sngxml::dom::Node* rightNode = (*rightNodeSet)[i];
493 std::u32string rightString = StringValue(rightNode);
494 switch (comparisonOp)
495 {
496 case Operator::equal:
497 {
498 if (leftString == rightString)
499 {
500 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
501 return result;
502 }
503 break;
504 }
505 case Operator::notEqual:
506 {
507 if (leftString != rightString)
508 {
509 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
510 return result;
511 }
512 break;
513 }
514 case Operator::less:
515 {
516 if (leftString < rightString)
517 {
518 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
519 return result;
520 }
521 break;
522 }
523 case Operator::greater:
524 {
525 if (leftString > rightString)
526 {
527 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
528 return result;
529 }
530 break;
531 }
532 case Operator::lessOrEqual:
533 {
534 if (leftString <= rightString)
535 {
536 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
537 return result;
538 }
539 break;
540 }
541 case Operator::greaterOrEqual:
542 {
543 if (leftString >= rightString)
544 {
545 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
546 return result;
547 }
548 break;
549 }
550 }
551 }
552 }
553 else if (left->Type() == XPathObjectType::boolean)
554 {
555 bool leftBool = static_cast<XPathBoolean*>(left)->Value();
556 std::vector<XPathObject*> rightArgs;
557 rightArgs.push_back(right);
558 std::unique_ptr<XPathObject> rightAsBool = booleanFunction->Evaluate(context, rightArgs);
559 if (rightAsBool->Type() != XPathObjectType::boolean)
560 {
561 throw std::runtime_error("boolean result expected");
562 }
563 bool rightBool = static_cast<XPathBoolean*>(rightAsBool.get())->Value();
564 switch (comparisonOp)
565 {
566 case Operator::equal:
567 {
568 if (leftBool == rightBool)
569 {
570 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
571 return result;
572 }
573 break;
574 }
575 case Operator::notEqual:
576 {
577 if (leftBool != rightBool)
578 {
579 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
580 return result;
581 }
582 break;
583 }
584 case Operator::less:
585 {
586 if (leftBool < rightBool)
587 {
588 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
589 return result;
590 }
591 break;
592 }
593 case Operator::greater:
594 {
595 if (leftBool > rightBool)
596 {
597 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
598 return result;
599 }
600 break;
601 }
602 case Operator::lessOrEqual:
603 {
604 if (leftBool <= rightBool)
605 {
606 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
607 return result;
608 }
609 break;
610 }
611 case Operator::greaterOrEqual:
612 {
613 if (leftBool >= rightBool)
614 {
615 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
616 return result;
617 }
618 break;
619 }
620 }
621 }
622 }
623 std::unique_ptr<XPathObject> result(new XPathBoolean(false));
624 return result;
625 }
626
627 std::std::unique_ptr<XPathObject>CompareEquality(XPathContext&context, XPathObject*left, XPathObject*right)
628 {
629 if (left->Type() == XPathObjectType::nodeSet || right->Type() == XPathObjectType::nodeSet)
630 {
631 return CompareNodeSets(context, left, right, Operator::equal);
632 }
633 else
634 {
635 XPathFunction* numberFunction = GetXPathLibraryFunction(U"number");
636 XPathFunction* booleanFunction = GetXPathLibraryFunction(U"boolean");
637 XPathFunction* stringFunction = GetXPathLibraryFunction(U"string");
638 if (left->Type() == XPathObjectType::number || right->Type() == XPathObjectType::number)
639 {
640 std::vector<XPathObject*> leftArgs;
641 leftArgs.push_back(left);
642 std::unique_ptr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
643 if (leftAsNumber->Type() != XPathObjectType::number)
644 {
645 throw std::runtime_error("number result expected");
646 }
647 double leftNumber = static_cast<XPathNumber*>(leftAsNumber.get())->Value();
648 std::vector<XPathObject*> rightArgs;
649 rightArgs.push_back(right);
650 std::unique_ptr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
651 if (rightAsNumber->Type() != XPathObjectType::number)
652 {
653 throw std::runtime_error("number result expected");
654 }
655 double rightNumber = static_cast<XPathNumber*>(rightAsNumber.get())->Value();
656 if (leftNumber == rightNumber)
657 {
658 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
659 return result;
660 }
661 else
662 {
663 std::unique_ptr<XPathObject> result(new XPathBoolean(false));
664 return result;
665 }
666 }
667 else
668 {
669 std::vector<XPathObject*> leftArgs;
670 leftArgs.push_back(left);
671 std::unique_ptr<XPathObject> leftAsString = stringFunction->Evaluate(context, leftArgs);
672 if (leftAsString->Type() != XPathObjectType::string)
673 {
674 throw std::runtime_error("string result expected");
675 }
676 std::u32string leftString = static_cast<XPathString*>(leftAsString.get())->Value();
677 std::vector<XPathObject*> rightArgs;
678 rightArgs.push_back(right);
679 std::unique_ptr<XPathObject> rightAsString = stringFunction->Evaluate(context, rightArgs);
680 if (rightAsString->Type() != XPathObjectType::string)
681 {
682 throw std::runtime_error("string result expected");
683 }
684 std::u32string rightString = static_cast<XPathString*>(rightAsString.get())->Value();
685 if (leftString == rightString)
686 {
687 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
688 return result;
689 }
690 else
691 {
692 std::unique_ptr<XPathObject> result(new XPathBoolean(false));
693 return result;
694 }
695 }
696 }
697 std::unique_ptr<XPathObject> result(new XPathBoolean(false));
698 return result;
699 }
700
701 XPathEqualExpr::XPathEqualExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
702 {
703 }
704
705 std::std::unique_ptr<XPathObject>XPathEqualExpr::Evaluate(XPathContext&context)
706 {
707 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
708 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
709 return CompareEquality(context, left.get(), right.get());
710 }
711
712 std::std::unique_ptr<dom::Node>XPathEqualExpr::ToDom() const
713 {
714 std::unique_ptr<dom::Element> element(new dom::Element(U"equal"));
715 element->AppendChild(Left()->ToDom());
716 element->AppendChild(Right()->ToDom());
717 return std::unique_ptr<dom::Node>(element.release());
718 }
719
720 XPathNotEqualExpr::XPathNotEqualExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
721 {
722 }
723
724 std::std::unique_ptr<XPathObject>XPathNotEqualExpr::Evaluate(XPathContext&context)
725 {
726 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
727 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
728 std::unique_ptr<XPathObject> equal = CompareEquality(context, left.get(), right.get());
729 if (equal->Type() != XPathObjectType::boolean)
730 {
731 throw std::runtime_error("boolean result expected");
732 }
733 return std::unique_ptr<XPathObject>(new XPathBoolean(!static_cast<XPathBoolean*>(equal.get())->Value()));
734 }
735
736 std::std::unique_ptr<dom::Node>XPathNotEqualExpr::ToDom() const
737 {
738 std::unique_ptr<dom::Element> element(new dom::Element(U"notEqual"));
739 element->AppendChild(Left()->ToDom());
740 element->AppendChild(Right()->ToDom());
741 return std::unique_ptr<dom::Node>(element.release());
742 }
743
744 std::std::unique_ptr<XPathObject>Compare(XPathContext&context, XPathObject*left, XPathObject*right, OperatorcomparisonOp)
745 {
746 if (left->Type() == XPathObjectType::nodeSet || right->Type() == XPathObjectType::nodeSet)
747 {
748 return CompareNodeSets(context, left, right, comparisonOp);
749 }
750 else
751 {
752 XPathFunction* numberFunction = GetXPathLibraryFunction(U"number");
753 std::vector<XPathObject*> leftArgs;
754 leftArgs.push_back(left);
755 std::unique_ptr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
756 if (leftAsNumber->Type() != XPathObjectType::number)
757 {
758 throw std::runtime_error("number result expected");
759 }
760 double leftNumber = static_cast<XPathNumber*>(leftAsNumber.get())->Value();
761 std::vector<XPathObject*> rightArgs;
762 rightArgs.push_back(right);
763 std::unique_ptr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
764 if (rightAsNumber->Type() != XPathObjectType::number)
765 {
766 throw std::runtime_error("number result expected");
767 }
768 double rightNumber = static_cast<XPathNumber*>(rightAsNumber.get())->Value();
769 switch (comparisonOp)
770 {
771 case Operator::less:
772 {
773 if (leftNumber < rightNumber)
774 {
775 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
776 return result;
777 }
778 else
779 {
780 std::unique_ptr<XPathObject> result(new XPathBoolean(false));
781 return result;
782 }
783 break;
784 }
785 case Operator::greater:
786 {
787 if (leftNumber > rightNumber)
788 {
789 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
790 return result;
791 }
792 else
793 {
794 std::unique_ptr<XPathObject> result(new XPathBoolean(false));
795 return result;
796 }
797 break;
798 }
799 case Operator::lessOrEqual:
800 {
801 if (leftNumber <= rightNumber)
802 {
803 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
804 return result;
805 }
806 else
807 {
808 std::unique_ptr<XPathObject> result(new XPathBoolean(false));
809 return result;
810 }
811 break;
812 }
813 case Operator::greaterOrEqual:
814 {
815 if (leftNumber >= rightNumber)
816 {
817 std::unique_ptr<XPathObject> result(new XPathBoolean(true));
818 return result;
819 }
820 else
821 {
822 std::unique_ptr<XPathObject> result(new XPathBoolean(false));
823 return result;
824 }
825 break;
826 }
827 }
828 }
829 std::unique_ptr<XPathObject> result(new XPathBoolean(false));
830 return result;
831 }
832
833 XPathLessExpr::XPathLessExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
834 {
835 }
836
837 std::std::unique_ptr<XPathObject>XPathLessExpr::Evaluate(XPathContext&context)
838 {
839 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
840 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
841 return Compare(context, left.get(), right.get(), Operator::less);
842 }
843
844 std::std::unique_ptr<dom::Node>XPathLessExpr::ToDom() const
845 {
846 std::unique_ptr<dom::Element> element(new dom::Element(U"less"));
847 element->AppendChild(Left()->ToDom());
848 element->AppendChild(Right()->ToDom());
849 return std::unique_ptr<dom::Node>(element.release());
850 }
851
852 XPathGreaterExpr::XPathGreaterExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
853 {
854 }
855
856 std::std::unique_ptr<XPathObject>XPathGreaterExpr::Evaluate(XPathContext&context)
857 {
858 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
859 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
860 return Compare(context, left.get(), right.get(), Operator::greater);
861 }
862
863 std::std::unique_ptr<dom::Node>XPathGreaterExpr::ToDom() const
864 {
865 std::unique_ptr<dom::Element> element(new dom::Element(U"greater"));
866 element->AppendChild(Left()->ToDom());
867 element->AppendChild(Right()->ToDom());
868 return std::unique_ptr<dom::Node>(element.release());
869 }
870
871 XPathLessOrEqualExpr::XPathLessOrEqualExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
872 {
873 }
874
875 std::std::unique_ptr<XPathObject>XPathLessOrEqualExpr::Evaluate(XPathContext&context)
876 {
877 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
878 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
879 return Compare(context, left.get(), right.get(), Operator::lessOrEqual);
880 }
881
882 std::std::unique_ptr<dom::Node>XPathLessOrEqualExpr::ToDom() const
883 {
884 std::unique_ptr<dom::Element> element(new dom::Element(U"lessOrEqual"));
885 element->AppendChild(Left()->ToDom());
886 element->AppendChild(Right()->ToDom());
887 return std::unique_ptr<dom::Node>(element.release());
888 }
889
890 XPathGreaterOrEqualExpr::XPathGreaterOrEqualExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
891 {
892 }
893
894 std::std::unique_ptr<XPathObject>XPathGreaterOrEqualExpr::Evaluate(XPathContext&context)
895 {
896 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
897 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
898 return Compare(context, left.get(), right.get(), Operator::greaterOrEqual);
899 }
900
901 std::std::unique_ptr<dom::Node>XPathGreaterOrEqualExpr::ToDom() const
902 {
903 std::unique_ptr<dom::Element> element(new dom::Element(U"greaterOrEqual"));
904 element->AppendChild(Left()->ToDom());
905 element->AppendChild(Right()->ToDom());
906 return std::unique_ptr<dom::Node>(element.release());
907 }
908
909 XPathAddExpr::XPathAddExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
910 {
911 }
912
913 std::std::unique_ptr<XPathObject>XPathAddExpr::Evaluate(XPathContext&context)
914 {
915 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
916 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
917 XPathFunction* numberFunction = GetXPathLibraryFunction(U"number");
918 std::vector<XPathObject*> leftArgs;
919 leftArgs.push_back(left.get());
920 std::unique_ptr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
921 if (leftAsNumber->Type() != XPathObjectType::number)
922 {
923 throw std::runtime_error("number result expected");
924 }
925 double leftNumber = static_cast<XPathNumber*>(leftAsNumber.get())->Value();
926 std::vector<XPathObject*> rightArgs;
927 rightArgs.push_back(right.get());
928 std::unique_ptr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
929 if (rightAsNumber->Type() != XPathObjectType::number)
930 {
931 throw std::runtime_error("number result expected");
932 }
933 double rightNumber = static_cast<XPathNumber*>(rightAsNumber.get())->Value();
934 return std::unique_ptr<XPathObject>(new XPathNumber(leftNumber + rightNumber));
935 }
936
937 std::std::unique_ptr<dom::Node>XPathAddExpr::ToDom() const
938 {
939 std::unique_ptr<dom::Element> element(new dom::Element(U"add"));
940 element->AppendChild(Left()->ToDom());
941 element->AppendChild(Right()->ToDom());
942 return std::unique_ptr<dom::Node>(element.release());
943 }
944
945 XPathSubExpr::XPathSubExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
946 {
947 }
948
949 std::std::unique_ptr<XPathObject>XPathSubExpr::Evaluate(XPathContext&context)
950 {
951 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
952 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
953 XPathFunction* numberFunction = GetXPathLibraryFunction(U"number");
954 std::vector<XPathObject*> leftArgs;
955 leftArgs.push_back(left.get());
956 std::unique_ptr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
957 if (leftAsNumber->Type() != XPathObjectType::number)
958 {
959 throw std::runtime_error("number result expected");
960 }
961 double leftNumber = static_cast<XPathNumber*>(leftAsNumber.get())->Value();
962 std::vector<XPathObject*> rightArgs;
963 rightArgs.push_back(right.get());
964 std::unique_ptr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
965 if (rightAsNumber->Type() != XPathObjectType::number)
966 {
967 throw std::runtime_error("number result expected");
968 }
969 double rightNumber = static_cast<XPathNumber*>(rightAsNumber.get())->Value();
970 return std::unique_ptr<XPathObject>(new XPathNumber(leftNumber - rightNumber));
971 }
972
973 std::std::unique_ptr<dom::Node>XPathSubExpr::ToDom() const
974 {
975 std::unique_ptr<dom::Element> element(new dom::Element(U"sub"));
976 element->AppendChild(Left()->ToDom());
977 element->AppendChild(Right()->ToDom());
978 return std::unique_ptr<dom::Node>(element.release());
979 }
980
981 XPathMulExpr::XPathMulExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
982 {
983 }
984
985 std::std::unique_ptr<XPathObject>XPathMulExpr::Evaluate(XPathContext&context)
986 {
987 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
988 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
989 XPathFunction* numberFunction = GetXPathLibraryFunction(U"number");
990 std::vector<XPathObject*> leftArgs;
991 leftArgs.push_back(left.get());
992 std::unique_ptr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
993 if (leftAsNumber->Type() != XPathObjectType::number)
994 {
995 throw std::runtime_error("number result expected");
996 }
997 double leftNumber = static_cast<XPathNumber*>(leftAsNumber.get())->Value();
998 std::vector<XPathObject*> rightArgs;
999 rightArgs.push_back(right.get());
1000 std::unique_ptr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
1001 if (rightAsNumber->Type() != XPathObjectType::number)
1002 {
1003 throw std::runtime_error("number result expected");
1004 }
1005 double rightNumber = static_cast<XPathNumber*>(rightAsNumber.get())->Value();
1006 return std::unique_ptr<XPathObject>(new XPathNumber(leftNumber * rightNumber));
1007 }
1008
1009 std::std::unique_ptr<dom::Node>XPathMulExpr::ToDom() const
1010 {
1011 std::unique_ptr<dom::Element> element(new dom::Element(U"mul"));
1012 element->AppendChild(Left()->ToDom());
1013 element->AppendChild(Right()->ToDom());
1014 return std::unique_ptr<dom::Node>(element.release());
1015 }
1016
1017 XPathDivExpr::XPathDivExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
1018 {
1019 }
1020
1021 std::std::unique_ptr<XPathObject>XPathDivExpr::Evaluate(XPathContext&context)
1022 {
1023 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
1024 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
1025 XPathFunction* numberFunction = GetXPathLibraryFunction(U"number");
1026 std::vector<XPathObject*> leftArgs;
1027 leftArgs.push_back(left.get());
1028 std::unique_ptr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
1029 if (leftAsNumber->Type() != XPathObjectType::number)
1030 {
1031 throw std::runtime_error("number result expected");
1032 }
1033 double leftNumber = static_cast<XPathNumber*>(leftAsNumber.get())->Value();
1034 std::vector<XPathObject*> rightArgs;
1035 rightArgs.push_back(right.get());
1036 std::unique_ptr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
1037 if (rightAsNumber->Type() != XPathObjectType::number)
1038 {
1039 throw std::runtime_error("number result expected");
1040 }
1041 double rightNumber = static_cast<XPathNumber*>(rightAsNumber.get())->Value();
1042 return std::unique_ptr<XPathObject>(new XPathNumber(leftNumber / rightNumber));
1043 }
1044
1045 std::std::unique_ptr<dom::Node>XPathDivExpr::ToDom() const
1046 {
1047 std::unique_ptr<dom::Element> element(new dom::Element(U"div"));
1048 element->AppendChild(Left()->ToDom());
1049 element->AppendChild(Right()->ToDom());
1050 return std::unique_ptr<dom::Node>(element.release());
1051 }
1052
1053 XPathModExpr::XPathModExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
1054 {
1055 }
1056
1057 std::std::unique_ptr<XPathObject>XPathModExpr::Evaluate(XPathContext&context)
1058 {
1059 std::unique_ptr<XPathObject> left = Left()->Evaluate(context);
1060 std::unique_ptr<XPathObject> right = Right()->Evaluate(context);
1061 XPathFunction* numberFunction = GetXPathLibraryFunction(U"number");
1062 std::vector<XPathObject*> leftArgs;
1063 leftArgs.push_back(left.get());
1064 std::unique_ptr<XPathObject> leftAsNumber = numberFunction->Evaluate(context, leftArgs);
1065 if (leftAsNumber->Type() != XPathObjectType::number)
1066 {
1067 throw std::runtime_error("number result expected");
1068 }
1069 int64_t leftNumber = static_cast<int64_t>(static_cast<XPathNumber*>(leftAsNumber.get())->Value());
1070 std::vector<XPathObject*> rightArgs;
1071 rightArgs.push_back(right.get());
1072 std::unique_ptr<XPathObject> rightAsNumber = numberFunction->Evaluate(context, rightArgs);
1073 if (rightAsNumber->Type() != XPathObjectType::number)
1074 {
1075 throw std::runtime_error("number result expected");
1076 }
1077 int64_t rightNumber = static_cast<int64_t>(static_cast<XPathNumber*>(rightAsNumber.get())->Value());
1078 return std::unique_ptr<XPathObject>(new XPathNumber(double(leftNumber % rightNumber)));
1079 }
1080
1081 std::std::unique_ptr<dom::Node>XPathModExpr::ToDom() const
1082 {
1083 std::unique_ptr<dom::Element> element(new dom::Element(U"mod"));
1084 element->AppendChild(Left()->ToDom());
1085 element->AppendChild(Right()->ToDom());
1086 return std::unique_ptr<dom::Node>(element.release());
1087 }
1088
1089 XPathUnaryMinusExpr::XPathUnaryMinusExpr(XPathExpr* operand_) : XPathUnaryExpr(operand_)
1090 {
1091 }
1092
1093 std::std::unique_ptr<XPathObject>XPathUnaryMinusExpr::Evaluate(XPathContext&context)
1094 {
1095 std::unique_ptr<XPathObject> operand = Operand()->Evaluate(context);
1096 XPathFunction* numberFunction = GetXPathLibraryFunction(U"number");
1097 std::vector<XPathObject*> operandArgs;
1098 operandArgs.push_back(operand.get());
1099 std::unique_ptr<XPathObject> operandAsNumber = numberFunction->Evaluate(context, operandArgs);
1100 if (operandAsNumber->Type() != XPathObjectType::number)
1101 {
1102 throw std::runtime_error("number result expected");
1103 }
1104 double operandNumber = static_cast<XPathNumber*>(operandAsNumber.get())->Value();
1105 return std::unique_ptr<XPathObject>(new XPathNumber(-operandNumber));
1106 }
1107
1108 std::std::unique_ptr<dom::Node>XPathUnaryMinusExpr::ToDom() const
1109 {
1110 std::unique_ptr<dom::Element> element(new dom::Element(U"unaryMinus"));
1111 element->AppendChild(Operand()->ToDom());
1112 return std::unique_ptr<dom::Node>(element.release());
1113 }
1114
1115 XPathUnionExpr::XPathUnionExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
1116 {
1117 }
1118
1119 std::std::unique_ptr<XPathObject>XPathUnionExpr::Evaluate(XPathContext&context)
1120 {
1121 std::unique_ptr<XPathNodeSet> result(new XPathNodeSet());
1122 std::unique_ptr<XPathObject> leftResult = Left()->Evaluate(context);
1123 if (leftResult->Type() != XPathObjectType::nodeSet)
1124 {
1125 throw std::runtime_error("node set expected");
1126 }
1127 XPathNodeSet* leftNodeSet = static_cast<XPathNodeSet*>(leftResult.get());
1128 int n = leftNodeSet->Length();
1129 for (int i = 0; i < n; ++i)
1130 {
1131 result->Add((*leftNodeSet)[i]);
1132 }
1133 std::unique_ptr<XPathObject> rightResult = Right()->Evaluate(context);
1134 if (rightResult->Type() != XPathObjectType::nodeSet)
1135 {
1136 throw std::runtime_error("node set expected");
1137 }
1138 XPathNodeSet* rightNodeSet = static_cast<XPathNodeSet*>(rightResult.get());
1139 int m = rightNodeSet->Length();
1140 for (int i = 0; i < m; ++i)
1141 {
1142 result->Add((*rightNodeSet)[i]);
1143 }
1144 return std::unique_ptr<XPathObject>(result.release());
1145 }
1146
1147 std::std::unique_ptr<dom::Node>XPathUnionExpr::ToDom() const
1148 {
1149 std::unique_ptr<dom::Element> element(new dom::Element(U"union"));
1150 element->AppendChild(Left()->ToDom());
1151 element->AppendChild(Right()->ToDom());
1152 return std::unique_ptr<dom::Node>(element.release());
1153 }
1154
1155 XPathCombineStepExpr::XPathCombineStepExpr(XPathExpr* left_, XPathExpr* right_) : XPathBinaryExpr(left_, right_)
1156 {
1157 }
1158
1159 std::std::unique_ptr<XPathObject>XPathCombineStepExpr::Evaluate(XPathContext&context)
1160 {
1161 std::unique_ptr<XPathNodeSet> result(new XPathNodeSet());
1162 std::unique_ptr<XPathObject> leftResult = Left()->Evaluate(context);
1163 if (leftResult->Type() != XPathObjectType::nodeSet)
1164 {
1165 throw std::runtime_error("node set expected");
1166 }
1167 XPathNodeSet* leftNodeSet = static_cast<XPathNodeSet*>(leftResult.get());
1168 int n = leftNodeSet->Length();
1169 for (int i = 0; i < n; ++i)
1170 {
1171 sngxml::dom::Node* node = (*leftNodeSet)[i];
1172 XPathContext rightContext(node, i + 1, n);
1173 std::unique_ptr<XPathObject> rightResult = Right()->Evaluate(rightContext);
1174 if (rightResult->Type() != XPathObjectType::nodeSet)
1175 {
1176 throw std::runtime_error("node set expected");
1177 }
1178 XPathNodeSet* rightNodeSet = static_cast<XPathNodeSet*>(rightResult.get());
1179 int m = rightNodeSet->Length();
1180 for (int i = 0; i < m; ++i)
1181 {
1182 sngxml::dom::Node* node = (*rightNodeSet)[i];
1183 result->Add(node);
1184 }
1185 }
1186 return std::unique_ptr<XPathObject>(result.release());
1187 }
1188
1189 std::std::unique_ptr<dom::Node>XPathCombineStepExpr::ToDom() const
1190 {
1191 std::unique_ptr<dom::Element> element(new dom::Element(U"combineStep"));
1192 element->AppendChild(Left()->ToDom());
1193 element->AppendChild(Right()->ToDom());
1194 return std::unique_ptr<dom::Node>(element.release());
1195 }
1196
1197 XPathRootNodeExpr::XPathRootNodeExpr()
1198 {
1199 }
1200
1201 std::std::unique_ptr<XPathObject>XPathRootNodeExpr::Evaluate(XPathContext&context)
1202 {
1203 std::unique_ptr<XPathNodeSet> nodeSet(new XPathNodeSet());
1204 if (context.Node()->GetNodeType() == sngxml::dom::NodeType::documentNode)
1205 {
1206 nodeSet->Add(context.Node());
1207 }
1208 else
1209 {
1210 nodeSet->Add(context.Node()->OwnerDocument());
1211 }
1212 return std::unique_ptr<XPathObject>(nodeSet.release());
1213 }
1214
1215 std::std::unique_ptr<dom::Node>XPathRootNodeExpr::ToDom() const
1216 {
1217 std::unique_ptr<dom::Element> element(new dom::Element(U"root"));
1218 return std::unique_ptr<dom::Node>(element.release());
1219 }
1220
1221 XPathFilterExpr::XPathFilterExpr(XPathExpr* expr_, XPathExpr* predicate_) : XPathUnaryExpr(expr_), predicate(predicate_)
1222 {
1223 }
1224
1225 std::std::unique_ptr<XPathObject>XPathFilterExpr::Evaluate(XPathContext&context)
1226 {
1227 std::unique_ptr<XPathObject> result = Operand()->Evaluate(context);
1228 if (result->Type() != XPathObjectType::nodeSet)
1229 {
1230 throw std::runtime_error("node-set expected");
1231 }
1232 std::unique_ptr<XPathNodeSet> nodeSet(static_cast<XPathNodeSet*>(result.release()));
1233 std::unique_ptr<XPathNodeSet> filteredNodeSet(new XPathNodeSet());
1234 int n = nodeSet->Length();
1235 for (int i = 0; i < n; ++i)
1236 {
1237 sngxml::dom::Node* node = (*nodeSet)[i];
1238 XPathContext context(node, i + 1, n);
1239 std::unique_ptr<XPathObject> result = predicate->Evaluate(context);
1240 bool booleanResult = false;
1241 if (result->Type() == XPathObjectType::number)
1242 {
1243 XPathNumber* number = static_cast<XPathNumber*>(result.get());
1244 if (number->Value() == context.Position())
1245 {
1246 booleanResult = true;
1247 }
1248 }
1249 else
1250 {
1251 XPathFunction* boolean = GetXPathLibraryFunction(U"boolean");
1252 std::vector<XPathObject*> args;
1253 args.push_back(result.get());
1254 std::unique_ptr<XPathObject> resultAsBoolean = boolean->Evaluate(context, args);
1255 booleanResult = static_cast<XPathBoolean*>(resultAsBoolean.get())->Value();
1256 }
1257 if (booleanResult)
1258 {
1259 filteredNodeSet->Add(node);
1260 }
1261 }
1262 std::swap(nodeSet, filteredNodeSet);
1263 return std::unique_ptr<XPathObject>(nodeSet.release());
1264 }
1265
1266 std::std::unique_ptr<dom::Node>XPathFilterExpr::ToDom() const
1267 {
1268 std::unique_ptr<dom::Element> element(new dom::Element(U"filter"));
1269 element->AppendChild(Operand()->ToDom());
1270 std::unique_ptr<dom::Element> predicateElement(new dom::Element(U"predicate"));
1271 predicateElement->AppendChild(predicate->ToDom());
1272 element->AppendChild(std::unique_ptr<dom::Node>(predicateElement.release()));
1273 return std::unique_ptr<dom::Node>(element.release());
1274 }
1275
1276 class NodeSelectionOp : public sngxml::dom::NodeOp
1277 {
1278 public:
1279 NodeSelectionOp(XPathNodeTestExpr* nodeTest_, XPathNodeSet& nodeSet_, sngxml::dom::Axis axis_);
1280 void Apply(sngxml::dom::Node* node) override;
1281 private:
1282 XPathNodeTestExpr* nodeTest;
1283 XPathNodeSet& nodeSet;
1284 sngxml::dom::Axis axis;
1285 };
1286
1287 NodeSelectionOp::NodeSelectionOp(XPathNodeTestExpr* nodeTest_, XPathNodeSet& nodeSet_, sngxml::dom::Axis axis_) : nodeTest(nodeTest_), nodeSet(nodeSet_), axis(axis_)
1288 {
1289 }
1290
1291 void NodeSelectionOp::Apply(sngxml::dom::Node* node)
1292 {
1293 if (nodeTest->Select(node, axis))
1294 {
1295 nodeSet.Add(node);
1296 }
1297 }
1298
1299 XPathLocationStepExpr::XPathLocationStepExpr(sngxml::dom::Axis axis_, XPathNodeTestExpr* nodeTest_) : axis(axis_), nodeTest(nodeTest_)
1300 {
1301 }
1302
1303 void XPathLocationStepExpr::AddPredicate(XPathExpr* predicate)
1304 {
1305 predicates.push_back(std::unique_ptr<XPathExpr>(predicate));
1306 }
1307
1308 std::std::unique_ptr<XPathObject>XPathLocationStepExpr::Evaluate(XPathContext&context)
1309 {
1310 std::unique_ptr<XPathNodeSet> nodeSet(new XPathNodeSet());
1311 NodeSelectionOp selectNodes(nodeTest.get(), *nodeSet, axis);
1312 context.Node()->Walk(selectNodes, axis);
1313 for (const std::std::unique_ptr<XPathExpr>&predicate : predicates)
1314 {
1315 std::unique_ptr<XPathNodeSet> filteredNodeSet(new XPathNodeSet());
1316 int n = nodeSet->Length();
1317 for (int i = 0; i < n; ++i)
1318 {
1319 sngxml::dom::Node* node = (*nodeSet)[i];
1320 XPathContext context(node, i + 1, n);
1321 std::unique_ptr<XPathObject> result = predicate->Evaluate(context);
1322 bool booleanResult = false;
1323 if (result->Type() == XPathObjectType::number)
1324 {
1325 XPathNumber* number = static_cast<XPathNumber*>(result.get());
1326 if (number->Value() == context.Position())
1327 {
1328 booleanResult = true;
1329 }
1330 }
1331 else
1332 {
1333 XPathFunction* boolean = GetXPathLibraryFunction(U"boolean");
1334 std::vector<XPathObject*> args;
1335 args.push_back(result.get());
1336 std::unique_ptr<XPathObject> resultAsBoolean = boolean->Evaluate(context, args);
1337 booleanResult = static_cast<XPathBoolean*>(resultAsBoolean.get())->Value();
1338 }
1339 if (booleanResult)
1340 {
1341 filteredNodeSet->Add(node);
1342 }
1343 }
1344 std::swap(nodeSet, filteredNodeSet);
1345 }
1346 return std::unique_ptr<XPathObject>(nodeSet.release());
1347 }
1348
1349 std::std::unique_ptr<dom::Node>XPathLocationStepExpr::ToDom() const
1350 {
1351 std::unique_ptr<dom::Element> element(new dom::Element(U"locationStep"));
1352 dom::Element* axisElement = new dom::Element(U"axis");
1353 std::u32string axisName = AxisName(axis);
1354 axisElement->SetAttribute(U"name", axisName);
1355 element->AppendChild(std::unique_ptr<dom::Node>(axisElement));
1356 dom::Element* nodeTestElement = new dom::Element(U"nodeTest");
1357 nodeTestElement->AppendChild(nodeTest->ToDom());
1358 element->AppendChild(std::unique_ptr<dom::Node>(nodeTestElement));
1359 std::unique_ptr<dom::Element> predicatesElement(new dom::Element(U"predicates"));
1360 for (const std::std::unique_ptr<XPathExpr>&predicate : predicates)
1361 {
1362 predicatesElement->AppendChild(predicate->ToDom());
1363 }
1364 element->AppendChild(std::unique_ptr<dom::Node>(predicatesElement.release()));
1365 return std::unique_ptr<dom::Node>(element.release());
1366 }
1367
1368 class AxisMap
1369 {
1370 public:
1371 AxisMap();
1372 sngxml::dom::Axis GetAxis(const std::u32string& axis) const;
1373 private:
1374 std::map<std::u32string, sngxml::dom::Axis> axisMap;
1375 };
1376
1377 AxisMap::AxisMap()
1378 {
1379 axisMap[U"ancestor"] = sngxml::dom::Axis::ancestor;
1380 axisMap[U"ancestor-or-self"] = sngxml::dom::Axis::ancestorOrSelf;
1381 axisMap[U"attribute"] = sngxml::dom::Axis::attribute;
1382 axisMap[U"child"] = sngxml::dom::Axis::child;
1383 axisMap[U"descendant"] = sngxml::dom::Axis::descendant;
1384 axisMap[U"descendant-or-self"] = sngxml::dom::Axis::descendantOrSelf;
1385 axisMap[U"following"] = sngxml::dom::Axis::following;
1386 axisMap[U"following-sibling"] = sngxml::dom::Axis::followingSibling;
1387 axisMap[U"namespace"] = sngxml::dom::Axis::ns;
1388 axisMap[U"parent"] = sngxml::dom::Axis::parent;
1389 axisMap[U"preceding"] = sngxml::dom::Axis::preceding;
1390 axisMap[U"preceding-sibling"] = sngxml::dom::Axis::precedingSibling;
1391 axisMap[U"self"] = sngxml::dom::Axis::self;
1392 }
1393
1394 sngxml::dom::Axis AxisMap::GetAxis(const std::u32string& axis) const
1395 {
1396 std::map<std::u32string, sngxml::dom::Axis>::const_iterator it = axisMap.find(axis);
1397 if (it != axisMap.cend())
1398 {
1399 return it->second;
1400 }
1401 else
1402 {
1403 throw std::runtime_error("axis '" + ToUtf8(axis) + "' not found");
1404 }
1405 }
1406
1407 AxisMap axisMap;
1408
1409 sngxml::dom::Axis GetAxis(const std::u32string& axisName)
1410 {
1411 return axisMap.GetAxis(axisName);
1412 }
1413
1414 XPathPILiteralTest::XPathPILiteralTest(XPathExpr* literal_) : literal(literal_)
1415 {
1416 }
1417
1418 bool XPathPILiteralTest::Select(sngxml::dom::Node* node, sngxml::dom::Axis axis) const
1419 {
1420 if (node->GetNodeType() == sngxml::dom::NodeType::processingInstructionNode)
1421 {
1422 sngxml::dom::ProcessingInstruction* pi = static_cast<sngxml::dom::ProcessingInstruction*>(node);
1423 if (pi->Target() == literal->TextValue())
1424 {
1425 return true;
1426 }
1427 }
1428 return false;
1429 }
1430
1431 std::std::unique_ptr<dom::Node>XPathPILiteralTest::ToDom() const
1432 {
1433 std::unique_ptr<dom::Element> element(new dom::Element(U"piLiteralTest"));
1434 element->AppendChild(literal->ToDom());
1435 return std::unique_ptr<dom::Node>(element.release());
1436 }
1437
1438 bool XPathCommentNodeTest::Select(sngxml::dom::Node* node, sngxml::dom::Axis axis) const
1439 {
1440 return node->GetNodeType() == sngxml::dom::NodeType::commentNode;
1441 }
1442
1443 std::std::unique_ptr<dom::Node>XPathCommentNodeTest::ToDom() const
1444 {
1445 std::unique_ptr<dom::Element> element(new dom::Element(U"commentNodeTest"));
1446 return std::unique_ptr<dom::Node>(element.release());
1447 }
1448
1449 bool XPathTextNodeTest::Select(sngxml::dom::Node* node, sngxml::dom::Axis axis) const
1450 {
1451 return node->GetNodeType() == sngxml::dom::NodeType::textNode;
1452 }
1453
1454 std::std::unique_ptr<dom::Node>XPathTextNodeTest::ToDom() const
1455 {
1456 std::unique_ptr<dom::Element> element(new dom::Element(U"textNodeTest"));
1457 return std::unique_ptr<dom::Node>(element.release());
1458 }
1459
1460 bool XPathPINodeTest::Select(sngxml::dom::Node* node, sngxml::dom::Axis axis) const
1461 {
1462 return node->GetNodeType() == sngxml::dom::NodeType::processingInstructionNode;
1463 }
1464
1465 std::std::unique_ptr<dom::Node>XPathPINodeTest::ToDom() const
1466 {
1467 std::unique_ptr<dom::Element> element(new dom::Element(U"piNodeTest"));
1468 return std::unique_ptr<dom::Node>(element.release());
1469 }
1470
1471 bool XPathPrincipalNodeTest::Select(sngxml::dom::Node* node, sngxml::dom::Axis axis) const
1472 {
1473 if (axis == sngxml::dom::Axis::attribute)
1474 {
1475 return node->GetNodeType() == sngxml::dom::NodeType::attributeNode;
1476 }
1477 else if (axis == sngxml::dom::Axis::ns)
1478 {
1479 return false;
1480 }
1481 else
1482 {
1483 return node->GetNodeType() == sngxml::dom::NodeType::elementNode;
1484 }
1485 }
1486
1487 std::std::unique_ptr<dom::Node>XPathPrincipalNodeTest::ToDom() const
1488 {
1489 std::unique_ptr<dom::Element> element(new dom::Element(U"principalNodeTest"));
1490 return std::unique_ptr<dom::Node>(element.release());
1491 }
1492
1493 bool XPathAnyNodeTest::Select(sngxml::dom::Node* node, sngxml::dom::Axis axis) const
1494 {
1495 return true;
1496 }
1497
1498 std::std::unique_ptr<dom::Node>XPathAnyNodeTest::ToDom() const
1499 {
1500 std::unique_ptr<dom::Element> element(new dom::Element(U"anyNodeTest"));
1501 return std::unique_ptr<dom::Node>(element.release());
1502 }
1503
1504 XPathPrefixTest::XPathPrefixTest(const std::u32string& name_) : name(name_)
1505 {
1506 }
1507
1508 bool XPathPrefixTest::Select(sngxml::dom::Node* node, sngxml::dom::Axis axis) const
1509 {
1510 if (axis == sngxml::dom::Axis::attribute)
1511 {
1512 if (node->GetNodeType() == sngxml::dom::NodeType::attributeNode)
1513 {
1514 sngxml::dom::Attr* attr = static_cast<sngxml::dom::Attr*>(node);
1515 if (attr->Prefix() == name)
1516 {
1517 return true;
1518 }
1519 }
1520 }
1521 else if (axis == sngxml::dom::Axis::ns)
1522 {
1523
1524 return false;
1525 }
1526 else if (node->GetNodeType() == sngxml::dom::NodeType::elementNode)
1527 {
1528 sngxml::dom::Element* element = static_cast<sngxml::dom::Element*>(node);
1529 if (element->Prefix() == name)
1530 {
1531 return true;
1532 }
1533 }
1534 return false;
1535 }
1536
1537 std::std::unique_ptr<dom::Node>XPathPrefixTest::ToDom() const
1538 {
1539 std::unique_ptr<dom::Element> element(new dom::Element(U"prefixTest"));
1540 element->SetAttribute(U"prefix", name);
1541 return std::unique_ptr<dom::Node>(element.release());
1542 }
1543
1544 XPathNameTest::XPathNameTest(const std::u32string& name_) : name(name_)
1545 {
1546 }
1547
1548 bool XPathNameTest::Select(sngxml::dom::Node* node, sngxml::dom::Axis axis) const
1549 {
1550 if (axis == sngxml::dom::Axis::attribute)
1551 {
1552 if (node->GetNodeType() == sngxml::dom::NodeType::attributeNode)
1553 {
1554 sngxml::dom::Attr* attr = static_cast<sngxml::dom::Attr*>(node);
1555 if (attr->Name() == name)
1556 {
1557 return true;
1558 }
1559 }
1560 }
1561 else if (axis != sngxml::dom::Axis::ns)
1562 {
1563 if (node->GetNodeType() == sngxml::dom::NodeType::elementNode)
1564 {
1565 sngxml::dom::Element* element = static_cast<sngxml::dom::Element*>(node);
1566 if (element->Name() == name)
1567 {
1568 return true;
1569 }
1570 }
1571 }
1572 return false;
1573 }
1574
1575 std::std::unique_ptr<dom::Node>XPathNameTest::ToDom() const
1576 {
1577 std::unique_ptr<dom::Element> element(new dom::Element(U"nameTest"));
1578 element->SetAttribute(U"name", name);
1579 return std::unique_ptr<dom::Node>(element.release());
1580 }
1581
1582 XPathVariableReference::XPathVariableReference(const std::u32string& name_) : name(name_)
1583 {
1584 }
1585
1586 std::std::unique_ptr<dom::Node>XPathVariableReference::ToDom() const
1587 {
1588 std::unique_ptr<dom::Element> element(new dom::Element(U"variableReference"));
1589 element->SetAttribute(U"name", name);
1590 return std::unique_ptr<dom::Node>(element.release());
1591 }
1592
1593 XPathLiteral::XPathLiteral(const std::u32string& value_) : value(value_)
1594 {
1595 }
1596
1597 std::std::unique_ptr<XPathObject>XPathLiteral::Evaluate(XPathContext&context)
1598 {
1599 return std::unique_ptr<XPathObject>(new XPathString(value));
1600 }
1601
1602 std::std::unique_ptr<dom::Node>XPathLiteral::ToDom() const
1603 {
1604 std::unique_ptr<dom::Element> element(new dom::Element(U"literal"));
1605 element->SetAttribute(U"value", value);
1606 return std::unique_ptr<dom::Node>(element.release());
1607 }
1608
1609 XPathNumberExpr::XPathNumberExpr(const std::u32string& value_)
1610 {
1611 std::string s = ToUtf8(value_);
1612 std::stringstream strm;
1613 strm.str(s);
1614 strm >> value;
1615 }
1616
1617 XPathNumberExpr::XPathNumberExpr(double value_) : value(value_)
1618 {
1619 }
1620
1621 std::std::unique_ptr<XPathObject>XPathNumberExpr::Evaluate(XPathContext&context)
1622 {
1623 return std::unique_ptr<XPathObject>(new XPathNumber(value));
1624 }
1625
1626 std::std::unique_ptr<dom::Node>XPathNumberExpr::ToDom() const
1627 {
1628 std::unique_ptr<dom::Element> element(new dom::Element(U"number"));
1629 element->SetAttribute(U"value", ToUtf32(std::to_string(value)));
1630 return std::unique_ptr<dom::Node>(element.release());
1631 }
1632
1633 XPathFunctionCall::XPathFunctionCall(const std::u32string& functionName_) : functionName(functionName_)
1634 {
1635 }
1636
1637 void XPathFunctionCall::AddArgument(XPathExpr* argument)
1638 {
1639 arguments.push_back(std::unique_ptr<XPathExpr>(argument));
1640 }
1641
1642 std::std::unique_ptr<XPathObject>XPathFunctionCall::Evaluate(XPathContext&context)
1643 {
1644 XPathFunction* function = GetXPathLibraryFunction(functionName);
1645 if (arguments.size() < function->MinArity() || arguments.size() > function->MaxArity())
1646 {
1647 throw std::runtime_error("function '" + ToUtf8(functionName) + "' takes " + std::to_string(function->MinArity()) + "..." + std::to_string(function->MaxArity()) + " arguments (" +
1648 std::to_string(arguments.size()) + " arguments provided)");
1649 }
1650 std::vector<std::std::unique_ptr<XPathObject>>ownedArgs;
1651 std::vector<XPathObject*> args;
1652 for (const std::std::unique_ptr<XPathExpr>&argument : arguments)
1653 {
1654 std::unique_ptr<XPathObject> arg = argument->Evaluate(context);
1655 args.push_back(arg.get());
1656 ownedArgs.push_back(std::move(arg));
1657 }
1658 std::unique_ptr<XPathObject> result = function->Evaluate(context, args);
1659 return result;
1660 }
1661
1662 std::std::unique_ptr<dom::Node>XPathFunctionCall::ToDom() const
1663 {
1664 std::unique_ptr<dom::Element> element(new dom::Element(U"functionCall"));
1665 element->AppendChild(std::unique_ptr<dom::Node>(new dom::Element(functionName)));
1666 std::unique_ptr<dom::Element> argumentsElement(new dom::Element(U"arguments"));
1667 for (const std::std::unique_ptr<XPathExpr>&argument : arguments)
1668 {
1669 argumentsElement->AppendChild(argument->ToDom());
1670 }
1671 element->AppendChild(std::unique_ptr<dom::Node>(argumentsElement.release()));
1672 return std::unique_ptr<dom::Node>(element.release());
1673 }
1674
1675 } }