@@ -45,28 +45,9 @@ type builder struct {
45
45
46
46
// axisPredicate creates a predicate to predicating for this axis node.
47
47
func axisPredicate (root * axisNode ) func (NodeNavigator ) bool {
48
- // get current axix node type.
49
- typ := ElementNode
50
- switch root .AxeType {
51
- case "attribute" :
52
- typ = AttributeNode
53
- case "self" , "parent" :
54
- typ = allNode
55
- default :
56
- switch root .Prop {
57
- case "comment" :
58
- typ = CommentNode
59
- case "text" :
60
- typ = TextNode
61
- // case "processing-instruction":
62
- // typ = ProcessingInstructionNode
63
- case "node" :
64
- typ = allNode
65
- }
66
- }
67
48
nametest := root .LocalName != "" || root .Prefix != ""
68
49
predicate := func (n NodeNavigator ) bool {
69
- if typ == n .NodeType () || typ == allNode {
50
+ if root . typeTest == n .NodeType () || root . typeTest == allNode {
70
51
if nametest {
71
52
type namespaceURL interface {
72
53
NamespaceURL () string
@@ -102,42 +83,35 @@ func (b *builder) processAxis(root *axisNode, flags flag, props *builderProp) (q
102
83
* props = builderProps .None
103
84
} else {
104
85
inputFlags := flagsEnum .None
105
- if root .AxeType == "child" && (root .Input .Type () == nodeAxis ) {
106
- if input := root .Input .(* axisNode ); input .AxeType == "descendant-or-self" {
107
- var qyGrandInput query
108
- if input .Input != nil {
109
- qyGrandInput , err = b .processNode (input .Input , flagsEnum .SmartDesc , props )
110
- if err != nil {
111
- return nil , err
86
+ if (flags & flagsEnum .Filter ) == 0 {
87
+ if root .AxisType == "child" && (root .Input .Type () == nodeAxis ) {
88
+ if input := root .Input .(* axisNode ); input .AxisType == "descendant-or-self" {
89
+ var qyGrandInput query
90
+ if input .Input != nil {
91
+ qyGrandInput , err = b .processNode (input .Input , flagsEnum .SmartDesc , props )
92
+ if err != nil {
93
+ return nil , err
94
+ }
95
+ } else {
96
+ qyGrandInput = & contextQuery {}
112
97
}
113
- } else {
114
- qyGrandInput = & contextQuery {}
98
+ qyOutput = & descendantQuery {name : root .LocalName , Input : qyGrandInput , Predicate : predicate , Self : false }
99
+ * props |= builderProps .NonFlat
100
+ return qyOutput , nil
115
101
}
116
- // fix #20: https://github.com/antchfx/htmlquery/issues/20
117
- filter := func (n NodeNavigator ) bool {
118
- v := predicate (n )
119
- switch root .Prop {
120
- case "text" :
121
- v = v && n .NodeType () == TextNode
122
- case "comment" :
123
- v = v && n .NodeType () == CommentNode
124
- }
125
- return v
126
- }
127
- qyOutput = & descendantQuery {name : root .LocalName , Input : qyGrandInput , Predicate : filter , Self : false }
128
- * props |= builderProps .NonFlat
129
- return qyOutput , nil
130
102
}
131
- } else if ((flags & flagsEnum .Filter ) == 0 ) && (root .AxeType == "descendant" || root .AxeType == "descendant-or-self" ) {
132
- inputFlags |= flagsEnum .SmartDesc
103
+ if root .AxisType == "descendant" || root .AxisType == "descendant-or-self" {
104
+ inputFlags |= flagsEnum .SmartDesc
105
+ }
133
106
}
107
+
134
108
qyInput , err = b .processNode (root .Input , inputFlags , props )
135
109
if err != nil {
136
110
return nil , err
137
111
}
138
112
}
139
113
140
- switch root .AxeType {
114
+ switch root .AxisType {
141
115
case "ancestor" :
142
116
qyOutput = & ancestorQuery {name : root .LocalName , Input : qyInput , Predicate : predicate }
143
117
* props |= builderProps .NonFlat
@@ -147,22 +121,10 @@ func (b *builder) processAxis(root *axisNode, flags flag, props *builderProp) (q
147
121
case "attribute" :
148
122
qyOutput = & attributeQuery {name : root .LocalName , Input : qyInput , Predicate : predicate }
149
123
case "child" :
150
- filter := func (n NodeNavigator ) bool {
151
- v := predicate (n )
152
- switch root .Prop {
153
- case "text" :
154
- v = v && n .NodeType () == TextNode
155
- case "node" :
156
- v = v && (n .NodeType () == ElementNode || n .NodeType () == TextNode )
157
- case "comment" :
158
- v = v && n .NodeType () == CommentNode
159
- }
160
- return v
161
- }
162
124
if (* props & builderProps .NonFlat ) == 0 {
163
- qyOutput = & childQuery {name : root .LocalName , Input : qyInput , Predicate : filter }
125
+ qyOutput = & childQuery {name : root .LocalName , Input : qyInput , Predicate : predicate }
164
126
} else {
165
- qyOutput = & cachedChildQuery {name : root .LocalName , Input : qyInput , Predicate : filter }
127
+ qyOutput = & cachedChildQuery {name : root .LocalName , Input : qyInput , Predicate : predicate }
166
128
}
167
129
case "descendant" :
168
130
if (flags & flagsEnum .SmartDesc ) != flagsEnum .None {
@@ -195,7 +157,7 @@ func (b *builder) processAxis(root *axisNode, flags flag, props *builderProp) (q
195
157
case "namespace" :
196
158
// haha,what will you do someting??
197
159
default :
198
- err = fmt .Errorf ("unknown axe type: %s" , root .AxeType )
160
+ err = fmt .Errorf ("unknown axe type: %s" , root .AxisType )
199
161
return nil , err
200
162
}
201
163
return qyOutput , nil
@@ -238,24 +200,22 @@ func (b *builder) processFilter(root *filterNode, flags flag, props *builderProp
238
200
* props |= builderProps .PosFilter
239
201
}
240
202
241
- merge := (qyInput .Properties () & queryProps .Merge ) != 0
242
203
if (propsCond & builderProps .HasPosition ) != builderProps .None {
243
204
if (propsCond & builderProps .HasLast ) != 0 {
244
205
// https://github.com/antchfx/xpath/issues/76
245
206
// https://github.com/antchfx/xpath/issues/78
246
207
if qyFunc , ok := cond .(* functionQuery ); ok {
247
208
switch qyFunc .Input .(type ) {
248
209
case * filterQuery :
249
- cond = & lastQuery {Input : qyFunc .Input }
210
+ cond = & lastFuncQuery {Input : qyFunc .Input }
250
211
}
251
212
}
252
213
}
253
214
}
254
215
216
+ merge := (qyInput .Properties () & queryProps .Merge ) != 0
255
217
if first && firstInput != nil {
256
218
if merge && ((* props & builderProps .PosFilter ) != 0 ) {
257
- qyInput = & filterQuery {Input : qyInput , Predicate : cond , NoPosition : false }
258
-
259
219
var (
260
220
rootQuery = & contextQuery {}
261
221
parent query
@@ -318,10 +278,11 @@ func (b *builder) processFilter(root *filterNode, flags flag, props *builderProp
318
278
}
319
279
}
320
280
b .firstInput = nil
281
+ child := & filterQuery {Input : qyInput , Predicate : cond , NoPosition : false }
321
282
if parent != nil {
322
- return & mergeQuery {Input : parent , Child : qyInput }, nil
283
+ return & mergeQuery {Input : parent , Child : child }, nil
323
284
}
324
- return qyInput , nil
285
+ return child , nil
325
286
}
326
287
b .firstInput = nil
327
288
}
@@ -346,7 +307,7 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
346
307
if err != nil {
347
308
return nil , err
348
309
}
349
- qyOutput = & functionQuery {Input : arg , Func : lowerCaseFunc }
310
+ qyOutput = & functionQuery {Func : lowerCaseFunc ( arg ) }
350
311
case "starts-with" :
351
312
arg1 , err := b .processNode (root .Args [0 ], flagsEnum .None , props )
352
313
if err != nil {
@@ -453,16 +414,13 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
453
414
if len (root .Args ) > 0 {
454
415
arg = root .Args [0 ]
455
416
} else {
456
- arg = & axisNode {
457
- AxeType : "self" ,
458
- nodeType : nodeAxis ,
459
- }
417
+ arg = newAxisNode ("self" , allNode , "" , "" , "" , nil )
460
418
}
461
- argQuery , err := b .processNode (arg , flagsEnum .None , props )
419
+ arg1 , err := b .processNode (arg , flagsEnum .None , props )
462
420
if err != nil {
463
421
return nil , err
464
422
}
465
- qyOutput = & functionQuery {Input : argQuery , Func : normalizespaceFunc }
423
+ qyOutput = & functionQuery {Func : normalizespaceFunc ( arg1 ) }
466
424
case "replace" :
467
425
//replace( string , string, string )
468
426
if len (root .Args ) != 3 {
@@ -509,7 +467,7 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
509
467
if err != nil {
510
468
return nil , err
511
469
}
512
- qyOutput = & functionQuery {Input : argQuery , Func : notFunc }
470
+ qyOutput = & functionQuery {Func : notFunc ( argQuery ) }
513
471
case "name" , "local-name" , "namespace-uri" :
514
472
if len (root .Args ) > 1 {
515
473
return nil , fmt .Errorf ("xpath: %s function must have at most one parameter" , root .FuncName )
@@ -540,17 +498,10 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
540
498
},
541
499
}
542
500
case "last" :
543
- //switch typ := b.firstInput.(type) {
544
- //case *groupQuery, *filterQuery:
545
- // https://github.com/antchfx/xpath/issues/76
546
- // https://github.com/antchfx/xpath/issues/78
547
- //qyOutput = &lastQuery{Input: typ}
548
- //default:
549
- qyOutput = & functionQuery {Func : lastFunc }
550
- //}
501
+ qyOutput = & functionQuery {Input : b .firstInput , Func : lastFunc ()}
551
502
* props |= builderProps .HasLast
552
503
case "position" :
553
- qyOutput = & functionQuery {Func : positionFunc }
504
+ qyOutput = & functionQuery {Input : b . firstInput , Func : positionFunc () }
554
505
* props |= builderProps .HasPosition
555
506
case "boolean" , "number" , "string" :
556
507
var inp query
@@ -564,16 +515,14 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
564
515
}
565
516
inp = argQuery
566
517
}
567
- f := & functionQuery {Input : inp }
568
518
switch root .FuncName {
569
519
case "boolean" :
570
- f . Func = booleanFunc
520
+ qyOutput = & functionQuery { Func : booleanFunc ( inp )}
571
521
case "string" :
572
- f . Func = stringFunc
522
+ qyOutput = & functionQuery { Func : stringFunc ( inp )}
573
523
case "number" :
574
- f . Func = numberFunc
524
+ qyOutput = & functionQuery { Func : numberFunc ( inp )}
575
525
}
576
- qyOutput = f
577
526
case "count" :
578
527
if len (root .Args ) == 0 {
579
528
return nil , fmt .Errorf ("xpath: count(node-sets) function must with have parameters node-sets" )
@@ -582,7 +531,7 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
582
531
if err != nil {
583
532
return nil , err
584
533
}
585
- qyOutput = & functionQuery {Input : argQuery , Func : countFunc }
534
+ qyOutput = & functionQuery {Func : countFunc ( argQuery ) }
586
535
case "sum" :
587
536
if len (root .Args ) == 0 {
588
537
return nil , fmt .Errorf ("xpath: sum(node-sets) function must with have parameters node-sets" )
@@ -591,7 +540,7 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
591
540
if err != nil {
592
541
return nil , err
593
542
}
594
- qyOutput = & functionQuery {Input : argQuery , Func : sumFunc }
543
+ qyOutput = & functionQuery {Func : sumFunc ( argQuery ) }
595
544
case "ceiling" , "floor" , "round" :
596
545
if len (root .Args ) == 0 {
597
546
return nil , fmt .Errorf ("xpath: ceiling(node-sets) function must with have parameters node-sets" )
@@ -600,16 +549,14 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
600
549
if err != nil {
601
550
return nil , err
602
551
}
603
- f := & functionQuery {Input : argQuery }
604
552
switch root .FuncName {
605
553
case "ceiling" :
606
- f . Func = ceilingFunc
554
+ qyOutput = & functionQuery { Func : ceilingFunc ( argQuery )}
607
555
case "floor" :
608
- f . Func = floorFunc
556
+ qyOutput = & functionQuery { Func : floorFunc ( argQuery )}
609
557
case "round" :
610
- f . Func = roundFunc
558
+ qyOutput = & functionQuery { Func : roundFunc ( argQuery )}
611
559
}
612
- qyOutput = f
613
560
case "concat" :
614
561
if len (root .Args ) < 2 {
615
562
return nil , fmt .Errorf ("xpath: concat() must have at least two arguments" )
@@ -636,22 +583,18 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
636
583
if len (root .Args ) != 2 {
637
584
return nil , fmt .Errorf ("xpath: string-join(node-sets, separator) function requires node-set and argument" )
638
585
}
639
- argQuery , err := b .processNode (root .Args [0 ], flagsEnum .None , props )
586
+ input , err := b .processNode (root .Args [0 ], flagsEnum .None , props )
640
587
if err != nil {
641
588
return nil , err
642
589
}
643
590
arg1 , err := b .processNode (root .Args [1 ], flagsEnum .None , props )
644
591
if err != nil {
645
592
return nil , err
646
593
}
647
- qyOutput = & functionQuery {Input : argQuery , Func : stringJoinFunc (arg1 )}
594
+ qyOutput = & functionQuery {Func : stringJoinFunc (input , arg1 )}
648
595
default :
649
596
return nil , fmt .Errorf ("not yet support this function %s()" , root .FuncName )
650
597
}
651
-
652
- if funcQuery , ok := qyOutput .(* functionQuery ); ok && funcQuery .Input == nil {
653
- funcQuery .Input = b .firstInput
654
- }
655
598
return qyOutput , nil
656
599
}
657
600
0 commit comments