@@ -45,28 +45,9 @@ type builder struct {
4545
4646// axisPredicate creates a predicate to predicating for this axis node.
4747func 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- }
6748 nametest := root .LocalName != "" || root .Prefix != ""
6849 predicate := func (n NodeNavigator ) bool {
69- if typ == n .NodeType () || typ == allNode {
50+ if root . typeTest == n .NodeType () || root . typeTest == allNode {
7051 if nametest {
7152 type namespaceURL interface {
7253 NamespaceURL () string
@@ -102,42 +83,35 @@ func (b *builder) processAxis(root *axisNode, flags flag, props *builderProp) (q
10283 * props = builderProps .None
10384 } else {
10485 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 {}
11297 }
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
115101 }
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
130102 }
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+ }
133106 }
107+
134108 qyInput , err = b .processNode (root .Input , inputFlags , props )
135109 if err != nil {
136110 return nil , err
137111 }
138112 }
139113
140- switch root .AxeType {
114+ switch root .AxisType {
141115 case "ancestor" :
142116 qyOutput = & ancestorQuery {name : root .LocalName , Input : qyInput , Predicate : predicate }
143117 * props |= builderProps .NonFlat
@@ -147,22 +121,10 @@ func (b *builder) processAxis(root *axisNode, flags flag, props *builderProp) (q
147121 case "attribute" :
148122 qyOutput = & attributeQuery {name : root .LocalName , Input : qyInput , Predicate : predicate }
149123 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- }
162124 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 }
164126 } else {
165- qyOutput = & cachedChildQuery {name : root .LocalName , Input : qyInput , Predicate : filter }
127+ qyOutput = & cachedChildQuery {name : root .LocalName , Input : qyInput , Predicate : predicate }
166128 }
167129 case "descendant" :
168130 if (flags & flagsEnum .SmartDesc ) != flagsEnum .None {
@@ -195,7 +157,7 @@ func (b *builder) processAxis(root *axisNode, flags flag, props *builderProp) (q
195157 case "namespace" :
196158 // haha,what will you do someting??
197159 default :
198- err = fmt .Errorf ("unknown axe type: %s" , root .AxeType )
160+ err = fmt .Errorf ("unknown axe type: %s" , root .AxisType )
199161 return nil , err
200162 }
201163 return qyOutput , nil
@@ -238,24 +200,22 @@ func (b *builder) processFilter(root *filterNode, flags flag, props *builderProp
238200 * props |= builderProps .PosFilter
239201 }
240202
241- merge := (qyInput .Properties () & queryProps .Merge ) != 0
242203 if (propsCond & builderProps .HasPosition ) != builderProps .None {
243204 if (propsCond & builderProps .HasLast ) != 0 {
244205 // https://github.com/antchfx/xpath/issues/76
245206 // https://github.com/antchfx/xpath/issues/78
246207 if qyFunc , ok := cond .(* functionQuery ); ok {
247208 switch qyFunc .Input .(type ) {
248209 case * filterQuery :
249- cond = & lastQuery {Input : qyFunc .Input }
210+ cond = & lastFuncQuery {Input : qyFunc .Input }
250211 }
251212 }
252213 }
253214 }
254215
216+ merge := (qyInput .Properties () & queryProps .Merge ) != 0
255217 if first && firstInput != nil {
256218 if merge && ((* props & builderProps .PosFilter ) != 0 ) {
257- qyInput = & filterQuery {Input : qyInput , Predicate : cond , NoPosition : false }
258-
259219 var (
260220 rootQuery = & contextQuery {}
261221 parent query
@@ -318,10 +278,11 @@ func (b *builder) processFilter(root *filterNode, flags flag, props *builderProp
318278 }
319279 }
320280 b .firstInput = nil
281+ child := & filterQuery {Input : qyInput , Predicate : cond , NoPosition : false }
321282 if parent != nil {
322- return & mergeQuery {Input : parent , Child : qyInput }, nil
283+ return & mergeQuery {Input : parent , Child : child }, nil
323284 }
324- return qyInput , nil
285+ return child , nil
325286 }
326287 b .firstInput = nil
327288 }
@@ -346,7 +307,7 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
346307 if err != nil {
347308 return nil , err
348309 }
349- qyOutput = & functionQuery {Input : arg , Func : lowerCaseFunc }
310+ qyOutput = & functionQuery {Func : lowerCaseFunc ( arg ) }
350311 case "starts-with" :
351312 arg1 , err := b .processNode (root .Args [0 ], flagsEnum .None , props )
352313 if err != nil {
@@ -453,16 +414,13 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
453414 if len (root .Args ) > 0 {
454415 arg = root .Args [0 ]
455416 } else {
456- arg = & axisNode {
457- AxeType : "self" ,
458- nodeType : nodeAxis ,
459- }
417+ arg = newAxisNode ("self" , allNode , "" , "" , "" , nil )
460418 }
461- argQuery , err := b .processNode (arg , flagsEnum .None , props )
419+ arg1 , err := b .processNode (arg , flagsEnum .None , props )
462420 if err != nil {
463421 return nil , err
464422 }
465- qyOutput = & functionQuery {Input : argQuery , Func : normalizespaceFunc }
423+ qyOutput = & functionQuery {Func : normalizespaceFunc ( arg1 ) }
466424 case "replace" :
467425 //replace( string , string, string )
468426 if len (root .Args ) != 3 {
@@ -509,7 +467,7 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
509467 if err != nil {
510468 return nil , err
511469 }
512- qyOutput = & functionQuery {Input : argQuery , Func : notFunc }
470+ qyOutput = & functionQuery {Func : notFunc ( argQuery ) }
513471 case "name" , "local-name" , "namespace-uri" :
514472 if len (root .Args ) > 1 {
515473 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
540498 },
541499 }
542500 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 ()}
551502 * props |= builderProps .HasLast
552503 case "position" :
553- qyOutput = & functionQuery {Func : positionFunc }
504+ qyOutput = & functionQuery {Input : b . firstInput , Func : positionFunc () }
554505 * props |= builderProps .HasPosition
555506 case "boolean" , "number" , "string" :
556507 var inp query
@@ -564,16 +515,14 @@ func (b *builder) processFunction(root *functionNode, props *builderProp) (query
564515 }
565516 inp = argQuery
566517 }
567- f := & functionQuery {Input : inp }
568518 switch root .FuncName {
569519 case "boolean" :
570- f . Func = booleanFunc
520+ qyOutput = & functionQuery { Func : booleanFunc ( inp )}
571521 case "string" :
572- f . Func = stringFunc
522+ qyOutput = & functionQuery { Func : stringFunc ( inp )}
573523 case "number" :
574- f . Func = numberFunc
524+ qyOutput = & functionQuery { Func : numberFunc ( inp )}
575525 }
576- qyOutput = f
577526 case "count" :
578527 if len (root .Args ) == 0 {
579528 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
582531 if err != nil {
583532 return nil , err
584533 }
585- qyOutput = & functionQuery {Input : argQuery , Func : countFunc }
534+ qyOutput = & functionQuery {Func : countFunc ( argQuery ) }
586535 case "sum" :
587536 if len (root .Args ) == 0 {
588537 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
591540 if err != nil {
592541 return nil , err
593542 }
594- qyOutput = & functionQuery {Input : argQuery , Func : sumFunc }
543+ qyOutput = & functionQuery {Func : sumFunc ( argQuery ) }
595544 case "ceiling" , "floor" , "round" :
596545 if len (root .Args ) == 0 {
597546 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
600549 if err != nil {
601550 return nil , err
602551 }
603- f := & functionQuery {Input : argQuery }
604552 switch root .FuncName {
605553 case "ceiling" :
606- f . Func = ceilingFunc
554+ qyOutput = & functionQuery { Func : ceilingFunc ( argQuery )}
607555 case "floor" :
608- f . Func = floorFunc
556+ qyOutput = & functionQuery { Func : floorFunc ( argQuery )}
609557 case "round" :
610- f . Func = roundFunc
558+ qyOutput = & functionQuery { Func : roundFunc ( argQuery )}
611559 }
612- qyOutput = f
613560 case "concat" :
614561 if len (root .Args ) < 2 {
615562 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
636583 if len (root .Args ) != 2 {
637584 return nil , fmt .Errorf ("xpath: string-join(node-sets, separator) function requires node-set and argument" )
638585 }
639- argQuery , err := b .processNode (root .Args [0 ], flagsEnum .None , props )
586+ input , err := b .processNode (root .Args [0 ], flagsEnum .None , props )
640587 if err != nil {
641588 return nil , err
642589 }
643590 arg1 , err := b .processNode (root .Args [1 ], flagsEnum .None , props )
644591 if err != nil {
645592 return nil , err
646593 }
647- qyOutput = & functionQuery {Input : argQuery , Func : stringJoinFunc (arg1 )}
594+ qyOutput = & functionQuery {Func : stringJoinFunc (input , arg1 )}
648595 default :
649596 return nil , fmt .Errorf ("not yet support this function %s()" , root .FuncName )
650597 }
651-
652- if funcQuery , ok := qyOutput .(* functionQuery ); ok && funcQuery .Input == nil {
653- funcQuery .Input = b .firstInput
654- }
655598 return qyOutput , nil
656599}
657600
0 commit comments