完成部分xml格式解析方法

master
徐俊杰 10 months ago
parent 249e749e6c
commit fe2cdb4f21

@ -9,6 +9,7 @@ package simpleRequest
import (
"bytes"
"encoding/json"
"encoding/xml"
"fmt"
"io"
"mime/multipart"
@ -17,9 +18,11 @@ import (
"strings"
)
// 通用类型解析器
var bodyEntryParsers = map[string]IBodyEntryParser{
jsonContentType: new(JsonParser),
formDataType: new(FormDataParser),
xmlDataType: new(XmlParser),
}
type IBodyEntryParser interface {
@ -138,3 +141,30 @@ func multipartCommonParse(BodyEntry map[string]any) (reader io.Reader, contentTy
}
return body, formWriter.FormDataContentType()
}
type XmlParser struct{}
func (f XmlParser) Unmarshal(bodyType EntryMark, BodyEntry map[string]any) (body io.Reader) {
switch bodyType {
case MapEntryType:
xmlData, err := xml.Marshal(BodyEntry[bodyType.string()])
if err == nil {
return bytes.NewReader(xmlData)
} else {
return strings.NewReader("")
}
case ModelEntryType:
xmlData, err := xml.Marshal(BodyEntry[bodyType.string()])
if err == nil {
return bytes.NewReader(xmlData)
} else {
return strings.NewReader("")
}
case StringEntryType:
return strings.NewReader(BodyEntry[StringEntryType.string()].(string))
case BytesEntryType:
return bytes.NewReader(BodyEntry[BytesEntryType.string()].([]byte))
default:
return strings.NewReader("")
}
}

@ -251,64 +251,90 @@ func (s *SimpleRequest) TRACE(url string) (body []byte, err error) {
// 这里数据
func (s *SimpleRequest) initBody() {
contentTypeData := s.headers.Get(hdrContentTypeKey)
switch {
case IsJSONType(contentTypeData):
var parser, ok = s.bodyEntryParsers[jsonContentType]
if !ok {
parser = new(JsonParser)
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
case strings.Contains(contentTypeData, formDataType):
var parser, ok = s.bodyEntryParsers[formDataType]
if !ok {
parser = new(FormDataParser)
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
fdParser := parser.(*FormDataParser)
s.headers.Set("Content-Type", fdParser.ContentType)
case IsXMLType(contentTypeData):
//application/soap+xml ,application/xml
var parser, ok = s.bodyEntryParsers[xmlDataType]
if !ok {
data, _ := s.BodyEntries[StringEntryType.string()].(string)
s.body = strings.NewReader(data)
return
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
case strings.Contains(contentTypeData, "text") || strings.Contains(contentTypeData, javaScriptType):
var parser, ok = s.bodyEntryParsers[textPlainType]
if !ok {
data, _ := s.BodyEntries[StringEntryType.string()].(string)
s.body = strings.NewReader(data)
return
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
case contentTypeData == "" && s.BodyEntryMark == BytesEntryType:
s.body = bytes.NewReader(s.BodyEntries[BytesEntryType.string()].([]byte))
if contentTypeData != "" {
switch {
case IsJSONType(contentTypeData):
var parser, ok = s.bodyEntryParsers[jsonContentType]
if !ok {
parser = new(JsonParser)
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
case contentTypeData == "" || strings.Contains(contentTypeData, "form-urlencoded"):
//default header type is "x-www-form-urlencoded"
var parser, ok = s.bodyEntryParsers["form-urlencoded"]
if !ok {
case strings.Contains(contentTypeData, formDataType):
var parser, ok = s.bodyEntryParsers[formDataType]
if !ok {
parser = new(FormDataParser)
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
fdParser := parser.(*FormDataParser)
s.headers.Set("Content-Type", fdParser.ContentType)
case IsXMLType(contentTypeData):
//application/soap+xml ,application/xml
var parser, ok = s.bodyEntryParsers[xmlDataType]
if !ok {
data, _ := s.BodyEntries[StringEntryType.string()].(string)
s.body = strings.NewReader(data)
return
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
case strings.Contains(contentTypeData, "text") || strings.Contains(contentTypeData, javaScriptType):
var parser, ok = s.bodyEntryParsers[textPlainType]
if !ok {
data, _ := s.BodyEntries[StringEntryType.string()].(string)
s.body = strings.NewReader(data)
return
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
case strings.Contains(contentTypeData, "form-urlencoded"):
//default header type is "x-www-form-urlencoded"
var parser, ok = s.bodyEntryParsers["form-urlencoded"]
if !ok {
tmpData := url.Values{}
for k, v := range s.BodyEntries {
tmpData.Set(k, fmt.Sprintf("%v", v))
}
s.body = strings.NewReader(tmpData.Encode())
s.Headers().ConentType_formUrlencoded()
return
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
default:
//todo Automatically determine the data type
tmpData := url.Values{}
for k, v := range s.BodyEntries {
for k, v := range tmpData {
if strings.HasPrefix(k, FormFilePathKey.string()) {
k = k[len(FormFilePathKey):]
}
tmpData.Set(k, fmt.Sprintf("%v", v))
}
s.body = strings.NewReader(tmpData.Encode())
s.Headers().ConentType_formUrlencoded()
return
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
default:
//todo Automatically determine the data type
tmpData := url.Values{}
for k, v := range tmpData {
tmpData.Set(k, fmt.Sprintf("%v", v))
} else {
switch s.BodyEntryMark {
case BytesEntryType:
s.body = bytes.NewReader(s.BodyEntries[BytesEntryType.string()].([]byte))
case StringEntryType:
s.body = strings.NewReader(s.BodyEntries[BytesEntryType.string()].(string))
default:
var parser, ok = s.bodyEntryParsers["form-urlencoded"]
if !ok {
tmpData := url.Values{}
for k, v := range s.BodyEntries {
if strings.HasPrefix(k, FormFilePathKey.string()) {
k = k[len(FormFilePathKey):]
}
tmpData.Set(k, fmt.Sprintf("%v", v))
}
s.body = strings.NewReader(tmpData.Encode())
s.Headers().ConentType_formUrlencoded()
return
}
s.body = parser.Unmarshal(s.BodyEntryMark, s.BodyEntries)
}
s.body = strings.NewReader(tmpData.Encode())
}
}

@ -7,6 +7,11 @@
package simpleRequest
import (
"encoding/xml"
"fmt"
)
func IsJSONType(ct string) bool {
return jsonCheck.MatchString(ct)
}
@ -24,3 +29,84 @@ func IsInArray(arr []string, str string) bool {
}
return false
}
type xmlMapEntry struct {
XMLName xml.Name
Value interface{} `xml:",chardata"`
}
// func MapToXml(data map[string]any) ([]byte, error) {
// xmlData, err := mapToXML(data)
// if err != nil {
// return nil, err
// }
// return xml.MarshalIndent(xmlData, "", " ")
// }
//
// func mapToXML(m map[string]interface{}) (xmlMap map[string]xmlMapEntry, err error) {
// if len(m) > 1 {
// return nil, errors.New("xml format must have a root name,the map value must like this: map[string]interface{}{\"rootName\":map[string]interface{}{}}")
// }
// xmlMap = make(map[string]xmlMapEntry)
// var rootName string
// for root, data := range m {
// rootName = root
// for k, v := range data.(map[string]interface{}) {
// switch typeV := v.(type) {
// case map[string]interface{}:
// subXmlMap, err := mapToXML(typeV)
// if err != nil {
// return
// }
//
// default:
// entry := xmlMapEntry{XMLName: xml.Name{Local: k}, Value: v}
// xmlMap[k] = entry
// }
// }
// }
//
// xmlData := struct {
// XMLName xml.Name
// Data []xmlMapEntry `xml:",any"`
// }{
// XMLName: xml.Name{Local: rootName},
// Data: make([]xmlMapEntry, 0, len(xmlMap)),
// }
//
// for _, v := range xmlMap {
// xmlData.Data = append(xmlData.Data, v)
// }
//
// return xml.MarshalIndent(xmlData, "", " ")
// }
func mapToXML(m map[string]interface{}) ([]byte, error) {
xmlData := make([]xmlNode, 0)
for k, v := range m {
node := xmlNode{
XMLName: xml.Name{Local: k},
}
switch value := v.(type) {
case map[string]interface{}:
childXML, err := mapToXML(value)
if err != nil {
return nil, err
}
node.Data = childXML
default:
node.Data = []byte(fmt.Sprintf("%v", v))
}
xmlData = append(xmlData, node)
}
return xml.MarshalIndent(xmlData, "", " ")
}
type xmlNode struct {
XMLName xml.Name
Data []byte `xml:",innerxml"`
}

@ -0,0 +1,82 @@
// Package simpleRequest -----------------------------
// @file : utils_test.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2023/11/17 16:37
// -------------------------------------------
package simpleRequest
import (
"fmt"
"testing"
)
func Test_mapToXML(t *testing.T) {
type args struct {
m map[string]interface{}
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "多级xml测试",
args: args{
m: map[string]interface{}{
"UserInfo": map[string]any{
"Name": "JJXu",
"Age": 18,
"isTrueMan": true,
"assets": map[string]any{
"car": "BMW",
"house": "shanghai",
},
},
},
},
want: "<UserInfo>\n<Age>18</Age>\n<isTrueMan>true</isTrueMan>\n<assets></assets>\n<Name>JJXu</Name>\n</UserInfo>",
wantErr: false,
},
{
name: "错误格式测试",
args: args{},
want: "",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := mapToXML(tt.args.m)
if (err != nil) != tt.wantErr {
t.Errorf("mapToXML() error = %v, wantErr %v", err, tt.wantErr)
return
}
if string(got) != tt.want {
t.Errorf("mapToXML() got = %v, want %v", string(got), tt.want)
}
})
}
}
func Test_mapToXML2(t *testing.T) {
person := map[string]interface{}{
"userInfo": map[string]interface{}{
"name": "John",
"age": 30,
"address": map[string]interface{}{
"street": "123 Main St",
"city": "New York",
},
},
}
xmlBytes, err := mapToXML(person)
if err != nil {
fmt.Println("Error:", err)
return
}
xmlString := string(xmlBytes)
fmt.Println(xmlString)
}
Loading…
Cancel
Save