From 50cf86ee613f95d93bcb5fad63ffd495c5a3c3a2 Mon Sep 17 00:00:00 2001 From: zhengchun Date: Thu, 3 Jun 2021 16:16:35 +0800 Subject: [PATCH] add `groupQuery`, supports grouping node query, (xpath expression). fix #https://github.com/antchfx/htmlquery/issues/42 --- build.go | 6 ++++++ parse.go | 18 ++++++++++++++++++ query.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/build.go b/build.go index 2edafb8..58d8f31 100644 --- a/build.go +++ b/build.go @@ -515,6 +515,12 @@ func (b *builder) processNode(root node) (q query, err error) { q, err = b.processFunctionNode(root.(*functionNode)) case nodeOperator: q, err = b.processOperatorNode(root.(*operatorNode)) + case nodeGroup: + q, err = b.processNode(root.(*groupNode).Input) + if err != nil { + return + } + q = &groupQuery{Input: q} } return } diff --git a/parse.go b/parse.go index fb9abe3..acb0db9 100644 --- a/parse.go +++ b/parse.go @@ -65,6 +65,7 @@ const ( nodeOperator nodeVariable nodeConstantOperand + nodeGroup ) type parser struct { @@ -104,6 +105,10 @@ func newFilterNode(n, m node) node { return &filterNode{nodeType: nodeFilter, Input: n, Condition: m} } +func newGroupNode(n node) node { + return &groupNode{nodeType: nodeGroup, Input: n} +} + // newRootNode returns a root node. func newRootNode(s string) node { return &rootNode{nodeType: nodeRoot, slash: s} @@ -492,6 +497,9 @@ func (p *parser) parsePrimaryExpr(n node) (opnd node) { case itemLParens: p.next() opnd = p.parseExpression(n) + if opnd.Type() != nodeConstantOperand { + opnd = newGroupNode(opnd) + } p.skipItem(itemRParens) case itemName: if p.r.canBeFunc && !isNodeType(p.r) { @@ -587,6 +595,16 @@ func (o *operandNode) String() string { return fmt.Sprintf("%v", o.Val) } +// groupNode holds a set of node expression +type groupNode struct { + nodeType + Input node +} + +func (g *groupNode) String() string { + return fmt.Sprintf("%s", g.Input) +} + // filterNode holds a condition filter. type filterNode struct { nodeType diff --git a/query.go b/query.go index 47f8076..6e99ce5 100644 --- a/query.go +++ b/query.go @@ -669,6 +669,35 @@ func (c *constantQuery) Clone() query { return c } +type groupQuery struct { + posit int + + Input query +} + +func (g *groupQuery) Select(t iterator) NodeNavigator { + for { + node := g.Input.Select(t) + if node == nil { + return nil + } + g.posit++ + return node.Copy() + } +} + +func (g *groupQuery) Evaluate(t iterator) interface{} { + return g.Input.Evaluate(t) +} + +func (g *groupQuery) Clone() query { + return &groupQuery{Input: g.Input} +} + +func (g *groupQuery) position() int { + return g.posit +} + // logicalQuery is an XPath logical expression. type logicalQuery struct { Left, Right query