1package xpath 2 3import ( 4 "reflect" 5) 6 7type iterator interface { 8 Current() NodeNavigator 9} 10 11// An XPath query interface. 12type query interface { 13 // Select traversing iterator returns a query matched node NodeNavigator. 14 Select(iterator) NodeNavigator 15 16 // Evaluate evaluates query and returns values of the current query. 17 Evaluate(iterator) interface{} 18 19 Clone() query 20} 21 22// contextQuery is returns current node on the iterator object query. 23type contextQuery struct { 24 count int 25 Root bool // Moving to root-level node in the current context iterator. 26} 27 28func (c *contextQuery) Select(t iterator) (n NodeNavigator) { 29 if c.count == 0 { 30 c.count++ 31 n = t.Current().Copy() 32 if c.Root { 33 n.MoveToRoot() 34 } 35 } 36 return n 37} 38 39func (c *contextQuery) Evaluate(iterator) interface{} { 40 c.count = 0 41 return c 42} 43 44func (c *contextQuery) Clone() query { 45 return &contextQuery{count: 0, Root: c.Root} 46} 47 48// ancestorQuery is an XPath ancestor node query.(ancestor::*|ancestor-self::*) 49type ancestorQuery struct { 50 iterator func() NodeNavigator 51 52 Self bool 53 Input query 54 Predicate func(NodeNavigator) bool 55} 56 57func (a *ancestorQuery) Select(t iterator) NodeNavigator { 58 for { 59 if a.iterator == nil { 60 node := a.Input.Select(t) 61 if node == nil { 62 return nil 63 } 64 first := true 65 a.iterator = func() NodeNavigator { 66 if first && a.Self { 67 first = false 68 if a.Predicate(node) { 69 return node 70 } 71 } 72 for node.MoveToParent() { 73 if !a.Predicate(node) { 74 continue 75 } 76 return node 77 } 78 return nil 79 } 80 } 81 82 if node := a.iterator(); node != nil { 83 return node 84 } 85 a.iterator = nil 86 } 87} 88 89func (a *ancestorQuery) Evaluate(t iterator) interface{} { 90 a.Input.Evaluate(t) 91 a.iterator = nil 92 return a 93} 94 95func (a *ancestorQuery) Test(n NodeNavigator) bool { 96 return a.Predicate(n) 97} 98 99func (a *ancestorQuery) Clone() query { 100 return &ancestorQuery{Self: a.Self, Input: a.Input.Clone(), Predicate: a.Predicate} 101} 102 103// attributeQuery is an XPath attribute node query.(@*) 104type attributeQuery struct { 105 iterator func() NodeNavigator 106 107 Input query 108 Predicate func(NodeNavigator) bool 109} 110 111func (a *attributeQuery) Select(t iterator) NodeNavigator { 112 for { 113 if a.iterator == nil { 114 node := a.Input.Select(t) 115 if node == nil { 116 return nil 117 } 118 node = node.Copy() 119 a.iterator = func() NodeNavigator { 120 for { 121 onAttr := node.MoveToNextAttribute() 122 if !onAttr { 123 return nil 124 } 125 if a.Predicate(node) { 126 return node 127 } 128 } 129 } 130 } 131 132 if node := a.iterator(); node != nil { 133 return node 134 } 135 a.iterator = nil 136 } 137} 138 139func (a *attributeQuery) Evaluate(t iterator) interface{} { 140 a.Input.Evaluate(t) 141 a.iterator = nil 142 return a 143} 144 145func (a *attributeQuery) Test(n NodeNavigator) bool { 146 return a.Predicate(n) 147} 148 149func (a *attributeQuery) Clone() query { 150 return &attributeQuery{Input: a.Input.Clone(), Predicate: a.Predicate} 151} 152 153// childQuery is an XPath child node query.(child::*) 154type childQuery struct { 155 posit int 156 iterator func() NodeNavigator 157 158 Input query 159 Predicate func(NodeNavigator) bool 160} 161 162func (c *childQuery) Select(t iterator) NodeNavigator { 163 for { 164 if c.iterator == nil { 165 c.posit = 0 166 node := c.Input.Select(t) 167 if node == nil { 168 return nil 169 } 170 node = node.Copy() 171 first := true 172 c.iterator = func() NodeNavigator { 173 for { 174 if (first && !node.MoveToChild()) || (!first && !node.MoveToNext()) { 175 return nil 176 } 177 first = false 178 if c.Predicate(node) { 179 return node 180 } 181 } 182 } 183 } 184 185 if node := c.iterator(); node != nil { 186 c.posit++ 187 return node 188 } 189 c.iterator = nil 190 } 191} 192 193func (c *childQuery) Evaluate(t iterator) interface{} { 194 c.Input.Evaluate(t) 195 c.iterator = nil 196 return c 197} 198 199func (c *childQuery) Test(n NodeNavigator) bool { 200 return c.Predicate(n) 201} 202 203func (c *childQuery) Clone() query { 204 return &childQuery{Input: c.Input.Clone(), Predicate: c.Predicate} 205} 206 207// position returns a position of current NodeNavigator. 208func (c *childQuery) position() int { 209 return c.posit 210} 211 212// descendantQuery is an XPath descendant node query.(descendant::* | descendant-or-self::*) 213type descendantQuery struct { 214 iterator func() NodeNavigator 215 posit int 216 217 Self bool 218 Input query 219 Predicate func(NodeNavigator) bool 220} 221 222func (d *descendantQuery) Select(t iterator) NodeNavigator { 223 for { 224 if d.iterator == nil { 225 d.posit = 0 226 node := d.Input.Select(t) 227 if node == nil { 228 return nil 229 } 230 node = node.Copy() 231 level := 0 232 first := true 233 d.iterator = func() NodeNavigator { 234 if first && d.Self { 235 first = false 236 if d.Predicate(node) { 237 return node 238 } 239 } 240 241 for { 242 if node.MoveToChild() { 243 level++ 244 } else { 245 for { 246 if level == 0 { 247 return nil 248 } 249 if node.MoveToNext() { 250 break 251 } 252 node.MoveToParent() 253 level-- 254 } 255 } 256 if d.Predicate(node) { 257 return node 258 } 259 } 260 } 261 } 262 263 if node := d.iterator(); node != nil { 264 d.posit++ 265 return node 266 } 267 d.iterator = nil 268 } 269} 270 271func (d *descendantQuery) Evaluate(t iterator) interface{} { 272 d.Input.Evaluate(t) 273 d.iterator = nil 274 return d 275} 276 277func (d *descendantQuery) Test(n NodeNavigator) bool { 278 return d.Predicate(n) 279} 280 281// position returns a position of current NodeNavigator. 282func (d *descendantQuery) position() int { 283 return d.posit 284} 285 286func (d *descendantQuery) Clone() query { 287 return &descendantQuery{Self: d.Self, Input: d.Input.Clone(), Predicate: d.Predicate} 288} 289 290// followingQuery is an XPath following node query.(following::*|following-sibling::*) 291type followingQuery struct { 292 iterator func() NodeNavigator 293 294 Input query 295 Sibling bool // The matching sibling node of current node. 296 Predicate func(NodeNavigator) bool 297} 298 299func (f *followingQuery) Select(t iterator) NodeNavigator { 300 for { 301 if f.iterator == nil { 302 node := f.Input.Select(t) 303 if node == nil { 304 return nil 305 } 306 node = node.Copy() 307 if f.Sibling { 308 f.iterator = func() NodeNavigator { 309 for { 310 if !node.MoveToNext() { 311 return nil 312 } 313 if f.Predicate(node) { 314 return node 315 } 316 } 317 } 318 } else { 319 var q query // descendant query 320 f.iterator = func() NodeNavigator { 321 for { 322 if q == nil { 323 for !node.MoveToNext() { 324 if !node.MoveToParent() { 325 return nil 326 } 327 } 328 q = &descendantQuery{ 329 Self: true, 330 Input: &contextQuery{}, 331 Predicate: f.Predicate, 332 } 333 t.Current().MoveTo(node) 334 } 335 if node := q.Select(t); node != nil { 336 return node 337 } 338 q = nil 339 } 340 } 341 } 342 } 343 344 if node := f.iterator(); node != nil { 345 return node 346 } 347 f.iterator = nil 348 } 349} 350 351func (f *followingQuery) Evaluate(t iterator) interface{} { 352 f.Input.Evaluate(t) 353 return f 354} 355 356func (f *followingQuery) Test(n NodeNavigator) bool { 357 return f.Predicate(n) 358} 359 360func (f *followingQuery) Clone() query { 361 return &followingQuery{Input: f.Input.Clone(), Sibling: f.Sibling, Predicate: f.Predicate} 362} 363 364// precedingQuery is an XPath preceding node query.(preceding::*) 365type precedingQuery struct { 366 iterator func() NodeNavigator 367 Input query 368 Sibling bool // The matching sibling node of current node. 369 Predicate func(NodeNavigator) bool 370} 371 372func (p *precedingQuery) Select(t iterator) NodeNavigator { 373 for { 374 if p.iterator == nil { 375 node := p.Input.Select(t) 376 if node == nil { 377 return nil 378 } 379 node = node.Copy() 380 if p.Sibling { 381 p.iterator = func() NodeNavigator { 382 for { 383 for !node.MoveToPrevious() { 384 return nil 385 } 386 if p.Predicate(node) { 387 return node 388 } 389 } 390 } 391 } else { 392 var q query 393 p.iterator = func() NodeNavigator { 394 for { 395 if q == nil { 396 for !node.MoveToPrevious() { 397 if !node.MoveToParent() { 398 return nil 399 } 400 } 401 q = &descendantQuery{ 402 Self: true, 403 Input: &contextQuery{}, 404 Predicate: p.Predicate, 405 } 406 t.Current().MoveTo(node) 407 } 408 if node := q.Select(t); node != nil { 409 return node 410 } 411 q = nil 412 } 413 } 414 } 415 } 416 if node := p.iterator(); node != nil { 417 return node 418 } 419 p.iterator = nil 420 } 421} 422 423func (p *precedingQuery) Evaluate(t iterator) interface{} { 424 p.Input.Evaluate(t) 425 return p 426} 427 428func (p *precedingQuery) Test(n NodeNavigator) bool { 429 return p.Predicate(n) 430} 431 432func (p *precedingQuery) Clone() query { 433 return &precedingQuery{Input: p.Input.Clone(), Sibling: p.Sibling, Predicate: p.Predicate} 434} 435 436// parentQuery is an XPath parent node query.(parent::*) 437type parentQuery struct { 438 Input query 439 Predicate func(NodeNavigator) bool 440} 441 442func (p *parentQuery) Select(t iterator) NodeNavigator { 443 for { 444 node := p.Input.Select(t) 445 if node == nil { 446 return nil 447 } 448 node = node.Copy() 449 if node.MoveToParent() && p.Predicate(node) { 450 return node 451 } 452 } 453} 454 455func (p *parentQuery) Evaluate(t iterator) interface{} { 456 p.Input.Evaluate(t) 457 return p 458} 459 460func (p *parentQuery) Clone() query { 461 return &parentQuery{Input: p.Input.Clone(), Predicate: p.Predicate} 462} 463 464func (p *parentQuery) Test(n NodeNavigator) bool { 465 return p.Predicate(n) 466} 467 468// selfQuery is an Self node query.(self::*) 469type selfQuery struct { 470 Input query 471 Predicate func(NodeNavigator) bool 472} 473 474func (s *selfQuery) Select(t iterator) NodeNavigator { 475 for { 476 node := s.Input.Select(t) 477 if node == nil { 478 return nil 479 } 480 481 if s.Predicate(node) { 482 return node 483 } 484 } 485} 486 487func (s *selfQuery) Evaluate(t iterator) interface{} { 488 s.Input.Evaluate(t) 489 return s 490} 491 492func (s *selfQuery) Test(n NodeNavigator) bool { 493 return s.Predicate(n) 494} 495 496func (s *selfQuery) Clone() query { 497 return &selfQuery{Input: s.Input.Clone(), Predicate: s.Predicate} 498} 499 500// filterQuery is an XPath query for predicate filter. 501type filterQuery struct { 502 Input query 503 Predicate query 504} 505 506func (f *filterQuery) do(t iterator) bool { 507 val := reflect.ValueOf(f.Predicate.Evaluate(t)) 508 switch val.Kind() { 509 case reflect.Bool: 510 return val.Bool() 511 case reflect.String: 512 return len(val.String()) > 0 513 case reflect.Float64: 514 pt := float64(getNodePosition(f.Input)) 515 return int(val.Float()) == int(pt) 516 default: 517 if q, ok := f.Predicate.(query); ok { 518 return q.Select(t) != nil 519 } 520 } 521 return false 522} 523 524func (f *filterQuery) Select(t iterator) NodeNavigator { 525 for { 526 node := f.Input.Select(t) 527 if node == nil { 528 return node 529 } 530 node = node.Copy() 531 //fmt.Println(node.LocalName()) 532 533 t.Current().MoveTo(node) 534 if f.do(t) { 535 return node 536 } 537 } 538} 539 540func (f *filterQuery) Evaluate(t iterator) interface{} { 541 f.Input.Evaluate(t) 542 return f 543} 544 545func (f *filterQuery) Clone() query { 546 return &filterQuery{Input: f.Input.Clone(), Predicate: f.Predicate.Clone()} 547} 548 549// functionQuery is an XPath function that call a function to returns 550// value of current NodeNavigator node. 551type functionQuery struct { 552 Input query // Node Set 553 Func func(query, iterator) interface{} // The xpath function. 554} 555 556func (f *functionQuery) Select(t iterator) NodeNavigator { 557 return nil 558} 559 560// Evaluate call a specified function that will returns the 561// following value type: number,string,boolean. 562func (f *functionQuery) Evaluate(t iterator) interface{} { 563 return f.Func(f.Input, t) 564} 565 566func (f *functionQuery) Clone() query { 567 return &functionQuery{Input: f.Input.Clone(), Func: f.Func} 568} 569 570// constantQuery is an XPath constant operand. 571type constantQuery struct { 572 Val interface{} 573} 574 575func (c *constantQuery) Select(t iterator) NodeNavigator { 576 return nil 577} 578 579func (c *constantQuery) Evaluate(t iterator) interface{} { 580 return c.Val 581} 582 583func (c *constantQuery) Clone() query { 584 return c 585} 586 587// logicalQuery is an XPath logical expression. 588type logicalQuery struct { 589 Left, Right query 590 591 Do func(iterator, interface{}, interface{}) interface{} 592} 593 594func (l *logicalQuery) Select(t iterator) NodeNavigator { 595 // When a XPath expr is logical expression. 596 node := t.Current().Copy() 597 val := l.Evaluate(t) 598 switch val.(type) { 599 case bool: 600 if val.(bool) == true { 601 return node 602 } 603 } 604 return nil 605} 606 607func (l *logicalQuery) Evaluate(t iterator) interface{} { 608 m := l.Left.Evaluate(t) 609 n := l.Right.Evaluate(t) 610 return l.Do(t, m, n) 611} 612 613func (l *logicalQuery) Clone() query { 614 return &logicalQuery{Left: l.Left.Clone(), Right: l.Right.Clone(), Do: l.Do} 615} 616 617// numericQuery is an XPath numeric operator expression. 618type numericQuery struct { 619 Left, Right query 620 621 Do func(interface{}, interface{}) interface{} 622} 623 624func (n *numericQuery) Select(t iterator) NodeNavigator { 625 return nil 626} 627 628func (n *numericQuery) Evaluate(t iterator) interface{} { 629 m := n.Left.Evaluate(t) 630 k := n.Right.Evaluate(t) 631 return n.Do(m, k) 632} 633 634func (n *numericQuery) Clone() query { 635 return &numericQuery{Left: n.Left.Clone(), Right: n.Right.Clone(), Do: n.Do} 636} 637 638type booleanQuery struct { 639 IsOr bool 640 Left, Right query 641 iterator func() NodeNavigator 642} 643 644func (b *booleanQuery) Select(t iterator) NodeNavigator { 645 if b.iterator == nil { 646 var list []NodeNavigator 647 i := 0 648 root := t.Current().Copy() 649 if b.IsOr { 650 for { 651 node := b.Left.Select(t) 652 if node == nil { 653 break 654 } 655 node = node.Copy() 656 list = append(list, node) 657 } 658 t.Current().MoveTo(root) 659 for { 660 node := b.Right.Select(t) 661 if node == nil { 662 break 663 } 664 node = node.Copy() 665 list = append(list, node) 666 } 667 } else { 668 var m []NodeNavigator 669 var n []NodeNavigator 670 for { 671 node := b.Left.Select(t) 672 if node == nil { 673 break 674 } 675 node = node.Copy() 676 list = append(m, node) 677 } 678 t.Current().MoveTo(root) 679 for { 680 node := b.Right.Select(t) 681 if node == nil { 682 break 683 } 684 node = node.Copy() 685 list = append(n, node) 686 } 687 for _, k := range m { 688 for _, j := range n { 689 if k == j { 690 list = append(list, k) 691 } 692 } 693 } 694 } 695 696 b.iterator = func() NodeNavigator { 697 if i >= len(list) { 698 return nil 699 } 700 node := list[i] 701 i++ 702 return node 703 } 704 } 705 return b.iterator() 706} 707 708func (b *booleanQuery) Evaluate(t iterator) interface{} { 709 m := b.Left.Evaluate(t) 710 left := asBool(t, m) 711 if b.IsOr && left { 712 return true 713 } else if !b.IsOr && !left { 714 return false 715 } 716 m = b.Right.Evaluate(t) 717 return asBool(t, m) 718} 719 720func (b *booleanQuery) Clone() query { 721 return &booleanQuery{IsOr: b.IsOr, Left: b.Left.Clone(), Right: b.Right.Clone()} 722} 723 724type unionQuery struct { 725 Left, Right query 726 iterator func() NodeNavigator 727} 728 729func (u *unionQuery) Select(t iterator) NodeNavigator { 730 if u.iterator == nil { 731 var list []NodeNavigator 732 var i int 733 root := t.Current().Copy() 734 for { 735 node := u.Left.Select(t) 736 if node == nil { 737 break 738 } 739 node = node.Copy() 740 list = append(list, node) 741 } 742 t.Current().MoveTo(root) 743 for { 744 node := u.Right.Select(t) 745 if node == nil { 746 break 747 } 748 node = node.Copy() 749 var exists bool 750 for _, x := range list { 751 if reflect.DeepEqual(x, node) { 752 exists = true 753 break 754 } 755 } 756 if !exists { 757 list = append(list, node) 758 } 759 } 760 u.iterator = func() NodeNavigator { 761 if i >= len(list) { 762 return nil 763 } 764 node := list[i] 765 i++ 766 return node 767 } 768 } 769 return u.iterator() 770} 771 772func (u *unionQuery) Evaluate(t iterator) interface{} { 773 u.iterator = nil 774 u.Left.Evaluate(t) 775 u.Right.Evaluate(t) 776 return u 777} 778 779func (u *unionQuery) Clone() query { 780 return &unionQuery{Left: u.Left.Clone(), Right: u.Right.Clone()} 781} 782 783func getNodePosition(q query) int { 784 type Position interface { 785 position() int 786 } 787 if count, ok := q.(Position); ok { 788 return count.position() 789 } 790 return 1 791} 792