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 }