-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcxpath.go
111 lines (99 loc) · 2.4 KB
/
cxpath.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package cxpath
import (
"io"
"iter"
"os"
"github.com/speedata/goxpath"
)
// A Context stores the current state of the XPath parser.
type Context struct {
P *goxpath.Parser
Seq goxpath.Sequence
Error error
}
// NewFromFile returns a new context from a file name.
func NewFromFile(filename string) (*Context, error) {
r, err := os.Open(filename)
if err != nil {
return nil, err
}
return NewFromReader(r)
}
// NewFromReader returns a new context from a reader.
func NewFromReader(r io.Reader) (*Context, error) {
p, err := goxpath.NewParser(r)
if err != nil {
return nil, err
}
ctx := Context{
P: p,
}
return &ctx, nil
}
func (ctx *Context) String() string {
return ctx.Seq.Stringvalue()
}
// Int returns the number value as an integer
func (ctx *Context) Int() int {
i, err := ctx.Seq.IntValue()
if err != nil {
ctx.Error = err
}
return i
}
// Bool returns the boolean value of the sequence.
func (ctx *Context) Bool() bool {
b, err := goxpath.BooleanValue(ctx.Seq)
if err != nil {
ctx.Error = err
}
return b
}
// SetNamespace sets a prefix/URI pair for XPath queries.
func (ctx *Context) SetNamespace(prefix, uri string) *Context {
ctx.P.Ctx.Namespaces[prefix] = uri
return ctx
}
// Root returns the top most element of the XML file.
func (ctx *Context) Root() *Context {
newContext := Context{
P: &goxpath.Parser{
Ctx: goxpath.CopyContext(ctx.P.Ctx),
},
}
newContext.Seq, newContext.Error = newContext.P.Ctx.Root()
return &newContext
}
// Each can be used as an iterator which returns a Context for each item in the
// resulting sequence.
func (ctx *Context) Each(eval string) iter.Seq[*Context] {
p := &goxpath.Parser{
Ctx: goxpath.CopyContext(ctx.P.Ctx),
}
seq, _ := p.Evaluate(eval)
return func(yield func(*Context) bool) {
for _, itm := range seq {
newContext := Context{
P: &goxpath.Parser{
Ctx: goxpath.CopyContext(ctx.P.Ctx),
},
Seq: goxpath.Sequence{itm},
}
newContext.P.Ctx.SetContextSequence(newContext.Seq)
if !yield(&newContext) {
return
}
}
}
}
// Eval executes the given XPath expression relative to the current context. It
// returns a new Context, so the old one is still available for further use.
func (ctx *Context) Eval(eval string) *Context {
newContext := Context{
P: &goxpath.Parser{
Ctx: goxpath.CopyContext(ctx.P.Ctx),
},
}
newContext.Seq, newContext.Error = newContext.P.Evaluate(eval)
return &newContext
}