1 package goquery
2
3 import "golang.org/x/net/html"
4
5 type siblingType int
6
7
8
9 const (
10 siblingPrevUntil siblingType = iota - 3
11 siblingPrevAll
12 siblingPrev
13 siblingAll
14 siblingNext
15 siblingNextAll
16 siblingNextUntil
17 siblingAllIncludingNonElements
18 )
19
20
21
22
23
24
25
26
27
28
29 func (s *Selection) Find(selector string) *Selection {
30 return pushStack(s, findWithMatcher(s.Nodes, compileMatcher(selector)))
31 }
32
33
34
35
36 func (s *Selection) FindMatcher(m Matcher) *Selection {
37 return pushStack(s, findWithMatcher(s.Nodes, m))
38 }
39
40
41
42
43 func (s *Selection) FindSelection(sel *Selection) *Selection {
44 if sel == nil {
45 return pushStack(s, nil)
46 }
47 return s.FindNodes(sel.Nodes...)
48 }
49
50
51
52
53 func (s *Selection) FindNodes(nodes ...*html.Node) *Selection {
54 return pushStack(s, mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
55 if sliceContains(s.Nodes, n) {
56 return []*html.Node{n}
57 }
58 return nil
59 }))
60 }
61
62
63
64
65 func (s *Selection) Contents() *Selection {
66 return pushStack(s, getChildrenNodes(s.Nodes, siblingAllIncludingNonElements))
67 }
68
69
70
71
72
73
74 func (s *Selection) ContentsFiltered(selector string) *Selection {
75 if selector != "" {
76 return s.ChildrenFiltered(selector)
77 }
78 return s.Contents()
79 }
80
81
82
83
84
85 func (s *Selection) ContentsMatcher(m Matcher) *Selection {
86 return s.ChildrenMatcher(m)
87 }
88
89
90
91 func (s *Selection) Children() *Selection {
92 return pushStack(s, getChildrenNodes(s.Nodes, siblingAll))
93 }
94
95
96
97
98 func (s *Selection) ChildrenFiltered(selector string) *Selection {
99 return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), compileMatcher(selector))
100 }
101
102
103
104
105 func (s *Selection) ChildrenMatcher(m Matcher) *Selection {
106 return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), m)
107 }
108
109
110
111 func (s *Selection) Parent() *Selection {
112 return pushStack(s, getParentNodes(s.Nodes))
113 }
114
115
116
117 func (s *Selection) ParentFiltered(selector string) *Selection {
118 return filterAndPush(s, getParentNodes(s.Nodes), compileMatcher(selector))
119 }
120
121
122
123 func (s *Selection) ParentMatcher(m Matcher) *Selection {
124 return filterAndPush(s, getParentNodes(s.Nodes), m)
125 }
126
127
128
129 func (s *Selection) Closest(selector string) *Selection {
130 cs := compileMatcher(selector)
131 return s.ClosestMatcher(cs)
132 }
133
134
135
136 func (s *Selection) ClosestMatcher(m Matcher) *Selection {
137 return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
138
139
140 for ; n != nil; n = n.Parent {
141 if m.Match(n) {
142 return []*html.Node{n}
143 }
144 }
145 return nil
146 }))
147 }
148
149
150
151 func (s *Selection) ClosestNodes(nodes ...*html.Node) *Selection {
152 set := make(map[*html.Node]bool)
153 for _, n := range nodes {
154 set[n] = true
155 }
156 return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
157
158
159 for ; n != nil; n = n.Parent {
160 if set[n] {
161 return []*html.Node{n}
162 }
163 }
164 return nil
165 }))
166 }
167
168
169
170
171 func (s *Selection) ClosestSelection(sel *Selection) *Selection {
172 if sel == nil {
173 return pushStack(s, nil)
174 }
175 return s.ClosestNodes(sel.Nodes...)
176 }
177
178
179
180 func (s *Selection) Parents() *Selection {
181 return pushStack(s, getParentsNodes(s.Nodes, nil, nil))
182 }
183
184
185
186 func (s *Selection) ParentsFiltered(selector string) *Selection {
187 return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), compileMatcher(selector))
188 }
189
190
191
192 func (s *Selection) ParentsMatcher(m Matcher) *Selection {
193 return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), m)
194 }
195
196
197
198
199 func (s *Selection) ParentsUntil(selector string) *Selection {
200 return pushStack(s, getParentsNodes(s.Nodes, compileMatcher(selector), nil))
201 }
202
203
204
205
206 func (s *Selection) ParentsUntilMatcher(m Matcher) *Selection {
207 return pushStack(s, getParentsNodes(s.Nodes, m, nil))
208 }
209
210
211
212
213 func (s *Selection) ParentsUntilSelection(sel *Selection) *Selection {
214 if sel == nil {
215 return s.Parents()
216 }
217 return s.ParentsUntilNodes(sel.Nodes...)
218 }
219
220
221
222
223 func (s *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection {
224 return pushStack(s, getParentsNodes(s.Nodes, nil, nodes))
225 }
226
227
228
229
230 func (s *Selection) ParentsFilteredUntil(filterSelector, untilSelector string) *Selection {
231 return filterAndPush(s, getParentsNodes(s.Nodes, compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
232 }
233
234
235
236 func (s *Selection) ParentsFilteredUntilMatcher(filter, until Matcher) *Selection {
237 return filterAndPush(s, getParentsNodes(s.Nodes, until, nil), filter)
238 }
239
240
241
242
243 func (s *Selection) ParentsFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
244 return s.ParentsMatcherUntilSelection(compileMatcher(filterSelector), sel)
245 }
246
247
248
249
250 func (s *Selection) ParentsMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
251 if sel == nil {
252 return s.ParentsMatcher(filter)
253 }
254 return s.ParentsMatcherUntilNodes(filter, sel.Nodes...)
255 }
256
257
258
259
260 func (s *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
261 return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), compileMatcher(filterSelector))
262 }
263
264
265
266
267 func (s *Selection) ParentsMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
268 return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), filter)
269 }
270
271
272
273 func (s *Selection) Siblings() *Selection {
274 return pushStack(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil))
275 }
276
277
278
279
280 func (s *Selection) SiblingsFiltered(selector string) *Selection {
281 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), compileMatcher(selector))
282 }
283
284
285
286
287 func (s *Selection) SiblingsMatcher(m Matcher) *Selection {
288 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), m)
289 }
290
291
292
293 func (s *Selection) Next() *Selection {
294 return pushStack(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil))
295 }
296
297
298
299
300 func (s *Selection) NextFiltered(selector string) *Selection {
301 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), compileMatcher(selector))
302 }
303
304
305
306
307 func (s *Selection) NextMatcher(m Matcher) *Selection {
308 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), m)
309 }
310
311
312
313 func (s *Selection) NextAll() *Selection {
314 return pushStack(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil))
315 }
316
317
318
319
320 func (s *Selection) NextAllFiltered(selector string) *Selection {
321 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), compileMatcher(selector))
322 }
323
324
325
326
327 func (s *Selection) NextAllMatcher(m Matcher) *Selection {
328 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), m)
329 }
330
331
332
333 func (s *Selection) Prev() *Selection {
334 return pushStack(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil))
335 }
336
337
338
339
340 func (s *Selection) PrevFiltered(selector string) *Selection {
341 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), compileMatcher(selector))
342 }
343
344
345
346
347 func (s *Selection) PrevMatcher(m Matcher) *Selection {
348 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), m)
349 }
350
351
352
353 func (s *Selection) PrevAll() *Selection {
354 return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil))
355 }
356
357
358
359
360 func (s *Selection) PrevAllFiltered(selector string) *Selection {
361 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), compileMatcher(selector))
362 }
363
364
365
366
367 func (s *Selection) PrevAllMatcher(m Matcher) *Selection {
368 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), m)
369 }
370
371
372
373
374 func (s *Selection) NextUntil(selector string) *Selection {
375 return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
376 compileMatcher(selector), nil))
377 }
378
379
380
381
382 func (s *Selection) NextUntilMatcher(m Matcher) *Selection {
383 return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
384 m, nil))
385 }
386
387
388
389
390 func (s *Selection) NextUntilSelection(sel *Selection) *Selection {
391 if sel == nil {
392 return s.NextAll()
393 }
394 return s.NextUntilNodes(sel.Nodes...)
395 }
396
397
398
399
400 func (s *Selection) NextUntilNodes(nodes ...*html.Node) *Selection {
401 return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
402 nil, nodes))
403 }
404
405
406
407
408 func (s *Selection) PrevUntil(selector string) *Selection {
409 return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
410 compileMatcher(selector), nil))
411 }
412
413
414
415
416 func (s *Selection) PrevUntilMatcher(m Matcher) *Selection {
417 return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
418 m, nil))
419 }
420
421
422
423
424 func (s *Selection) PrevUntilSelection(sel *Selection) *Selection {
425 if sel == nil {
426 return s.PrevAll()
427 }
428 return s.PrevUntilNodes(sel.Nodes...)
429 }
430
431
432
433
434 func (s *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
435 return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
436 nil, nodes))
437 }
438
439
440
441
442 func (s *Selection) NextFilteredUntil(filterSelector, untilSelector string) *Selection {
443 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
444 compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
445 }
446
447
448
449
450 func (s *Selection) NextFilteredUntilMatcher(filter, until Matcher) *Selection {
451 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
452 until, nil), filter)
453 }
454
455
456
457
458 func (s *Selection) NextFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
459 return s.NextMatcherUntilSelection(compileMatcher(filterSelector), sel)
460 }
461
462
463
464
465 func (s *Selection) NextMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
466 if sel == nil {
467 return s.NextMatcher(filter)
468 }
469 return s.NextMatcherUntilNodes(filter, sel.Nodes...)
470 }
471
472
473
474
475 func (s *Selection) NextFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
476 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
477 nil, nodes), compileMatcher(filterSelector))
478 }
479
480
481
482
483 func (s *Selection) NextMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
484 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
485 nil, nodes), filter)
486 }
487
488
489
490
491 func (s *Selection) PrevFilteredUntil(filterSelector, untilSelector string) *Selection {
492 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
493 compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
494 }
495
496
497
498
499 func (s *Selection) PrevFilteredUntilMatcher(filter, until Matcher) *Selection {
500 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
501 until, nil), filter)
502 }
503
504
505
506
507 func (s *Selection) PrevFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
508 return s.PrevMatcherUntilSelection(compileMatcher(filterSelector), sel)
509 }
510
511
512
513
514 func (s *Selection) PrevMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
515 if sel == nil {
516 return s.PrevMatcher(filter)
517 }
518 return s.PrevMatcherUntilNodes(filter, sel.Nodes...)
519 }
520
521
522
523
524 func (s *Selection) PrevFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
525 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
526 nil, nodes), compileMatcher(filterSelector))
527 }
528
529
530
531
532 func (s *Selection) PrevMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
533 return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
534 nil, nodes), filter)
535 }
536
537
538
539 func filterAndPush(srcSel *Selection, nodes []*html.Node, m Matcher) *Selection {
540
541 sel := &Selection{nodes, srcSel.document, nil}
542
543 return pushStack(srcSel, winnow(sel, m, true))
544 }
545
546
547 func findWithMatcher(nodes []*html.Node, m Matcher) []*html.Node {
548
549 return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
550
551 for c := n.FirstChild; c != nil; c = c.NextSibling {
552 if c.Type == html.ElementNode {
553 result = append(result, m.MatchAll(c)...)
554 }
555 }
556 return
557 })
558 }
559
560
561
562 func getParentsNodes(nodes []*html.Node, stopm Matcher, stopNodes []*html.Node) []*html.Node {
563 return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
564 for p := n.Parent; p != nil; p = p.Parent {
565 sel := newSingleSelection(p, nil)
566 if stopm != nil {
567 if sel.IsMatcher(stopm) {
568 break
569 }
570 } else if len(stopNodes) > 0 {
571 if sel.IsNodes(stopNodes...) {
572 break
573 }
574 }
575 if p.Type == html.ElementNode {
576 result = append(result, p)
577 }
578 }
579 return
580 })
581 }
582
583
584 func getSiblingNodes(nodes []*html.Node, st siblingType, untilm Matcher, untilNodes []*html.Node) []*html.Node {
585 var f func(*html.Node) bool
586
587
588
589 if st == siblingNextUntil || st == siblingPrevUntil {
590 f = func(n *html.Node) bool {
591 if untilm != nil {
592
593 sel := newSingleSelection(n, nil)
594 return sel.IsMatcher(untilm)
595 } else if len(untilNodes) > 0 {
596
597 sel := newSingleSelection(n, nil)
598 return sel.IsNodes(untilNodes...)
599 }
600 return false
601 }
602 }
603
604 return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
605 return getChildrenWithSiblingType(n.Parent, st, n, f)
606 })
607 }
608
609
610
611 func getChildrenNodes(nodes []*html.Node, st siblingType) []*html.Node {
612 return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
613 return getChildrenWithSiblingType(n, st, nil, nil)
614 })
615 }
616
617
618
619 func getChildrenWithSiblingType(parent *html.Node, st siblingType, skipNode *html.Node,
620 untilFunc func(*html.Node) bool) (result []*html.Node) {
621
622
623 var iter = func(cur *html.Node) (ret *html.Node) {
624
625 for {
626 switch st {
627 case siblingAll, siblingAllIncludingNonElements:
628 if cur == nil {
629
630
631 if ret = parent.FirstChild; ret == skipNode && skipNode != nil {
632 ret = skipNode.NextSibling
633 }
634 } else {
635
636 if ret = cur.NextSibling; ret == skipNode && skipNode != nil {
637 ret = skipNode.NextSibling
638 }
639 }
640 case siblingPrev, siblingPrevAll, siblingPrevUntil:
641 if cur == nil {
642
643 ret = skipNode.PrevSibling
644 } else {
645 ret = cur.PrevSibling
646 }
647 case siblingNext, siblingNextAll, siblingNextUntil:
648 if cur == nil {
649
650 ret = skipNode.NextSibling
651 } else {
652 ret = cur.NextSibling
653 }
654 default:
655 panic("Invalid sibling type.")
656 }
657 if ret == nil || ret.Type == html.ElementNode || st == siblingAllIncludingNonElements {
658 return
659 }
660
661 cur = ret
662 }
663 }
664
665 for c := iter(nil); c != nil; c = iter(c) {
666
667
668 if st == siblingNextUntil || st == siblingPrevUntil {
669 if untilFunc(c) {
670 return
671 }
672 }
673 result = append(result, c)
674 if st == siblingNext || st == siblingPrev {
675
676 return
677 }
678 }
679 return
680 }
681
682
683 func getParentNodes(nodes []*html.Node) []*html.Node {
684 return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
685 if n.Parent != nil && n.Parent.Type == html.ElementNode {
686 return []*html.Node{n.Parent}
687 }
688 return nil
689 })
690 }
691
692
693
694
695
696 func mapNodes(nodes []*html.Node, f func(int, *html.Node) []*html.Node) (result []*html.Node) {
697 set := make(map[*html.Node]bool)
698 for i, n := range nodes {
699 if vals := f(i, n); len(vals) > 0 {
700 result = appendWithoutDuplicates(result, vals, set)
701 }
702 }
703 return result
704 }
705
View as plain text