-
Notifications
You must be signed in to change notification settings - Fork 0
/
xmlparserforeach.go
153 lines (127 loc) · 3.56 KB
/
xmlparserforeach.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package gobatis
import (
"errors"
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
"github.com/antonmedv/expr"
"github.com/antonmedv/expr/vm"
"github.com/beevik/etree"
)
type XmlParseForeach struct {
separatorAttr string
openAttr string
closeAttr string
indexAttr string
itemAttr string
collectionAttr string
index int
ptnParamIndex *regexp.Regexp
ptnParamItem *regexp.Regexp
convertedValue []KeyValue
outputValue map[string]interface{}
}
// 构造SQL
func (b *XmlParseForeach) Build(el *etree.Element, inputValue map[string]interface{}, outputValue map[string]interface{}) (string, error) {
b.getAttr(el)
if err := b.convertValue(inputValue); err != nil {
return "", err
}
b.outputValue = outputValue
b.ptnParamIndex = regexp.MustCompile(`[$#]{` + b.indexAttr + `}`)
b.ptnParamItem = regexp.MustCompile(`[$#]{` + b.itemAttr + `}`)
index := 0
arr := make([]string, len(b.convertedValue))
text := strings.TrimSpace(el.Text())
for _, v := range b.convertedValue {
str := b.replaceIndex(text, v.Key, v.Value)
str = b.replaceItem(str, v.Value)
arr[index] = str
index++
}
if index == 0 {
return "", nil
}
return b.openAttr + strings.Join(arr, b.separatorAttr) + b.closeAttr, nil
}
// 获取foreach上的属性
func (b *XmlParseForeach) getAttr(el *etree.Element) {
b.separatorAttr = el.SelectAttrValue("separator", "")
b.openAttr = el.SelectAttrValue("open", "")
b.closeAttr = el.SelectAttrValue("close", "")
b.indexAttr = el.SelectAttrValue("index", "")
b.itemAttr = el.SelectAttrValue("item", "")
b.collectionAttr = el.SelectAttrValue("collection", "")
}
// 将collection关联的值转换为[]KeyValue{}格式,方便处理
func (b *XmlParseForeach) convertValue(inputValue interface{}) error {
if b.collectionAttr == "" {
return errors.New("the attribute \"collection\" is not exists")
}
p, err := expr.Eval(b.collectionAttr, inputValue)
if err != nil {
return err
}
if p == nil {
logger.Warn("foreach \"", b.collectionAttr, "\" value is nil")
return nil
}
values := reflect.ValueOf(p)
b.convertedValue = make([]KeyValue, values.Len())
kind := reflect.TypeOf(p).Kind()
if kind == reflect.Map {
index := 0
for _, v := range values.MapKeys() {
b.convertedValue[index] = KeyValue{Key: v.String(), Value: values.MapIndex(v).Interface()}
index++
}
} else if kind == reflect.Slice {
for i := 0; i < values.Len(); i++ {
b.convertedValue[i] = KeyValue{Key: strconv.Itoa(i), Value: values.Index(i).Interface()}
}
}
return nil
}
// 替换index的标记
func (b *XmlParseForeach) replaceIndex(str string, key string, value interface{}) string {
if b.indexAttr == "" {
return str
}
return b.ptnParamIndex.ReplaceAllStringFunc(str, func(s string) string {
if s[0:1] == "$" {
return key
}
str := b.collectionAttr + "_" + key
b.outputValue[str] = value
return str
})
}
// 替换item的标记
func (b *XmlParseForeach) replaceItem(str string, value interface{}) string {
if b.itemAttr == "" {
return str
}
var p1 *vm.Program
return b.ptnParamItem.ReplaceAllStringFunc(str, func(s string) string {
input := s[2 : len(s)-1]
if p1 == nil {
var err error
if p1, err = expr.Compile(input); err != nil {
logger.Error("eval ", input, " error: ", err)
}
}
output, err := expr.Run(p1, map[string]interface{}{"item": value})
if err != nil {
logger.Error("run ", input, " error: ", err)
}
if s[0:1] == "$" {
return toStr(output)
}
tmp := fmt.Sprintf("%s_%d", b.collectionAttr, b.index)
b.index++
b.outputValue[tmp] = output
return ":" + tmp
})
}