github.com/wangyougui/gf/v2@v2.6.5/encoding/gxml/gxml.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 // Package gxml provides accessing and converting for XML content. 8 package gxml 9 10 import ( 11 "strings" 12 13 "github.com/clbanning/mxj/v2" 14 15 "github.com/wangyougui/gf/v2/encoding/gcharset" 16 "github.com/wangyougui/gf/v2/errors/gerror" 17 "github.com/wangyougui/gf/v2/text/gregex" 18 ) 19 20 // Decode parses `content` into and returns as map. 21 func Decode(content []byte) (map[string]interface{}, error) { 22 res, err := convert(content) 23 if err != nil { 24 return nil, err 25 } 26 m, err := mxj.NewMapXml(res) 27 if err != nil { 28 err = gerror.Wrapf(err, `mxj.NewMapXml failed`) 29 } 30 return m, err 31 } 32 33 // DecodeWithoutRoot parses `content` into a map, and returns the map without root level. 34 func DecodeWithoutRoot(content []byte) (map[string]interface{}, error) { 35 res, err := convert(content) 36 if err != nil { 37 return nil, err 38 } 39 m, err := mxj.NewMapXml(res) 40 if err != nil { 41 err = gerror.Wrapf(err, `mxj.NewMapXml failed`) 42 return nil, err 43 } 44 for _, v := range m { 45 if r, ok := v.(map[string]interface{}); ok { 46 return r, nil 47 } 48 } 49 return m, nil 50 } 51 52 // Encode encodes map `m` to an XML format content as bytes. 53 // The optional parameter `rootTag` is used to specify the XML root tag. 54 func Encode(m map[string]interface{}, rootTag ...string) ([]byte, error) { 55 b, err := mxj.Map(m).Xml(rootTag...) 56 if err != nil { 57 err = gerror.Wrapf(err, `mxj.Map.Xml failed`) 58 } 59 return b, err 60 } 61 62 // EncodeWithIndent encodes map `m` to an XML format content as bytes with indent. 63 // The optional parameter `rootTag` is used to specify the XML root tag. 64 func EncodeWithIndent(m map[string]interface{}, rootTag ...string) ([]byte, error) { 65 b, err := mxj.Map(m).XmlIndent("", "\t", rootTag...) 66 if err != nil { 67 err = gerror.Wrapf(err, `mxj.Map.XmlIndent failed`) 68 } 69 return b, err 70 } 71 72 // ToJson converts `content` as XML format into JSON format bytes. 73 func ToJson(content []byte) ([]byte, error) { 74 res, err := convert(content) 75 if err != nil { 76 return nil, err 77 } 78 mv, err := mxj.NewMapXml(res) 79 if err == nil { 80 return mv.Json() 81 } 82 err = gerror.Wrap(err, `mxj.NewMapXml failed`) 83 return nil, err 84 } 85 86 // convert does convert the encoding of given XML content from XML root tag into UTF-8 encoding content. 87 func convert(xml []byte) (res []byte, err error) { 88 var ( 89 patten = `<\?xml.*encoding\s*=\s*['|"](.*?)['|"].*\?>` 90 matchStr, _ = gregex.MatchString(patten, string(xml)) 91 xmlEncode = "UTF-8" 92 ) 93 if len(matchStr) == 2 { 94 xmlEncode = matchStr[1] 95 } 96 xmlEncode = strings.ToUpper(xmlEncode) 97 res, err = gregex.Replace(patten, []byte(""), xml) 98 if err != nil { 99 return nil, err 100 } 101 if xmlEncode != "UTF-8" && xmlEncode != "UTF8" { 102 dst, err := gcharset.Convert("UTF-8", xmlEncode, string(res)) 103 if err != nil { 104 return nil, err 105 } 106 res = []byte(dst) 107 } 108 return res, nil 109 }