@@ -10,8 +10,11 @@ package xml
1010
1111import (
1212 "encoding/xml"
13+ "fmt"
1314 "github.com/xfali/gobatis/logging"
1415 "github.com/xfali/gobatis/parsing"
16+ "github.com/xfali/gobatis/reflection"
17+ "strconv"
1518 "strings"
1619 "unicode"
1720)
@@ -23,6 +26,7 @@ type Foreach struct {
2326 Index string `xml:"index,attr"`
2427 Open string `xml:"open,attr"`
2528 Close string `xml:"close,attr"`
29+ Data string `xml:",chardata"`
2630}
2731
2832type Sql struct {
@@ -43,7 +47,7 @@ type Include struct {
4347
4448type If struct {
4549 Test string `xml:"test,attr"`
46- Date string `xml:",chardata"`
50+ Data string `xml:",chardata"`
4751}
4852
4953type Where struct {
@@ -60,7 +64,7 @@ type When struct {
6064}
6165
6266type Otherwise struct {
63- Date string `xml:",chardata"`
67+ Data string `xml:",chardata"`
6468}
6569
6670type Choose struct {
@@ -91,15 +95,15 @@ func (de *If) Format(getFunc func(key string) string) string {
9195 return ""
9296 }
9397 }
94- return strings .TrimSpace (de .Date )
98+ return strings .TrimSpace (de .Data )
9599 }
96100
97101 ret := false
98102 if len (orStrs ) != 0 {
99103 for _ , v := range orStrs {
100104 ret = Compare (v , getFunc )
101105 if ret == true {
102- return strings .TrimSpace (de .Date )
106+ return strings .TrimSpace (de .Data )
103107 }
104108 }
105109 if ret == false {
@@ -242,11 +246,42 @@ func (de *Choose) Format(getFunc func(key string) string) string {
242246 }
243247 retStr := ret .String ()
244248 if retStr == "" {
245- retStr = strings .TrimSpace (de .Otherwise .Date )
249+ retStr = strings .TrimSpace (de .Otherwise .Data )
246250 }
247251 return retStr
248252}
249253
254+ func (de * Foreach ) Format (getFunc func (key string ) string ) string {
255+ if de .Collection == "" {
256+ return ""
257+ }
258+
259+ listStr := getValueFromFunc (de .Collection , getFunc )
260+ if listStr == "" || listStr == "nil" {
261+ return ""
262+ }
263+
264+ elems := reflection .ParseSliceParamString (listStr )
265+ ret := strings.Builder {}
266+ ret .WriteString (de .Open )
267+ itemStr := fmt .Sprintf ("#{%s}" , de .Item )
268+ indexStr := fmt .Sprintf ("#{%s}" , de .Index )
269+ length := len (elems )
270+ originData := strings .TrimSpace (de .Data )
271+ realStr := ""
272+ for i , v := range elems {
273+ realStr = strings .Replace (originData , itemStr , v , - 1 )
274+ realStr = strings .Replace (realStr , indexStr , strconv .Itoa (i ), - 1 )
275+ ret .WriteString (realStr )
276+ if i < length - 1 {
277+ ret .WriteString (de .Separator )
278+ }
279+ }
280+ ret .WriteString (de .Close )
281+
282+ return ret .String ()
283+ }
284+
250285func escape (src string ) string {
251286 src = strings .Replace (src , "<" , "<" , - 1 )
252287 src = strings .Replace (src , ">" , ">" , - 1 )
@@ -266,13 +301,15 @@ type WhereProcessor string
266301type SetProcessor string
267302type IncludeProcessor string
268303type ChooseProcessor string
304+ type ForeachProcessor string
269305
270306var gProcessorMap = map [string ]typeProcessor {
271307 "if" : IfProcessor ("if" ),
272308 "where" : WhereProcessor ("where" ),
273309 "set" : SetProcessor ("set" ),
274310 "include" : IncludeProcessor ("include" ),
275311 "choose" : ChooseProcessor ("choose" ),
312+ "foreach" : ForeachProcessor ("foreach" ),
276313}
277314
278315func (d IfProcessor ) EndStr () string {
@@ -335,6 +372,18 @@ func (d ChooseProcessor) Parse(src string) parsing.DynamicElement {
335372 return & v
336373}
337374
375+ func (d ForeachProcessor ) EndStr () string {
376+ return "</" + string (d ) + ">"
377+ }
378+
379+ func (d ForeachProcessor ) Parse (src string ) parsing.DynamicElement {
380+ v := Foreach {}
381+ if xml .Unmarshal ([]byte (src ), & v ) != nil {
382+ logging .Warn ("parse if element failed" )
383+ }
384+ return & v
385+ }
386+
338387func ParseDynamic (src string , sqls []Sql ) (* parsing.DynamicData , error ) {
339388 src = escape (src )
340389
0 commit comments