github.com/avicd/go-utilx@v0.1.0/xmlx/context.go (about)

     1  package xmlx
     2  
     3  import (
     4  	"github.com/avicd/go-utilx/refx"
     5  	"go/ast"
     6  	"strings"
     7  )
     8  
     9  type SelectType uint
    10  
    11  const (
    12  	SelectAll SelectType = iota
    13  	SelectFirst
    14  )
    15  
    16  type xpathContext struct {
    17  	binds map[string]any
    18  	xnd   *XNode
    19  }
    20  
    21  func newEvalCtx(xnd *XNode) *xpathContext {
    22  	ctx := &xpathContext{binds: map[string]any{}, xnd: xnd}
    23  	ctx.bind("self", xnd)
    24  	return ctx
    25  }
    26  
    27  func (ctx *xpathContext) bind(name string, value any) {
    28  	ctx.binds[name] = value
    29  }
    30  
    31  func (ctx *xpathContext) ValueOf(ident string) (any, bool) {
    32  	if val, ok := ctx.binds[ident]; ok {
    33  		return val, ok
    34  	}
    35  	if strings.HasPrefix(ident, xpathAttr) {
    36  		ident = strings.TrimPrefix(ident, xpathAttr)
    37  		return ctx.xnd.AttrString(ident), true
    38  	} else {
    39  		var target *Node
    40  		xnd := NewXpathNode(ctx.xnd.Node)
    41  		xnd.setCheckin(func(node *Node) bool {
    42  			target = node
    43  			return false
    44  		})
    45  		xnd.Child(ident)
    46  		if target != nil {
    47  			return target.InnerText(), true
    48  		}
    49  	}
    50  	return nil, false
    51  }
    52  
    53  func (ctx *xpathContext) MethodOf(ident string) (any, bool) {
    54  	return refx.MethodOfId(ctx.xnd, ident)
    55  }
    56  
    57  func (ctx *xpathContext) CacheOf(text string) (ast.Expr, bool) {
    58  	return nil, false
    59  }
    60  
    61  func (ctx *xpathContext) Cache(text string, expr ast.Expr) {
    62  
    63  }
    64  
    65  // parent->child->index
    66  type indexPool struct {
    67  	cache map[*Node]map[*Node]int
    68  }
    69  
    70  func (c *indexPool) cacheIndex(node *Node) {
    71  	pool := c.cache[node.ParentNode]
    72  	if pool == nil {
    73  		pool = map[*Node]int{}
    74  		c.cache[node.ParentNode] = pool
    75  	}
    76  	if _, ok := pool[node]; !ok {
    77  		pool[node] = len(pool) + 1
    78  	}
    79  }
    80  
    81  func (c *indexPool) GetIndex(node *Node) int {
    82  	pool := c.cache[node.ParentNode]
    83  	if pool == nil {
    84  		pool = map[*Node]int{}
    85  		c.cache[node.ParentNode] = pool
    86  	}
    87  	if val, ok := pool[node]; ok {
    88  		return val
    89  	}
    90  	return -1
    91  }