mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
新增gxml解析xml,开发中
This commit is contained in:
@ -7,7 +7,7 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 这是一个使用go进行json语法解析的解析器,效率没有官方的json解析高,仅作学习参考
|
||||
// 这是一个自己开发的,使用go进行json语法解析的解析器,效率没有官方的json解析高,仅作学习参考
|
||||
|
||||
const (
|
||||
gJSON_CHAR_BRACE_LEFT = rune('{')
|
||||
232
g/encoding/gxml/gxml.go
Normal file
232
g/encoding/gxml/gxml.go
Normal file
@ -0,0 +1,232 @@
|
||||
package gxml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"strconv"
|
||||
"io/ioutil"
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
// xml解析结果存放数组
|
||||
type Xml struct {
|
||||
// 注意这是一个指针
|
||||
value *interface{}
|
||||
}
|
||||
|
||||
// 一个xml变量
|
||||
type XmlVar interface{}
|
||||
|
||||
// 编码go变量为xml字符串,并返回xml字符串指针
|
||||
func Encode (v interface{}) ([]byte, error) {
|
||||
return xml.Marshal(v)
|
||||
}
|
||||
|
||||
// 解码字符串为interface{}变量
|
||||
func Decode (b []byte) (interface{}, error) {
|
||||
var v interface{}
|
||||
if err := DecodeTo(b, &v); err == nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 解析xml字符串为go变量,注意第二个参数为指针
|
||||
func DecodeTo (b []byte, v interface{}) error {
|
||||
return xml.Unmarshal(b, v)
|
||||
}
|
||||
|
||||
// 解析xml字符串为gxml.Xml对象,并返回操作对象指针
|
||||
func DecodeToXml (b []byte) (*Xml, error) {
|
||||
if v, err := Decode(b); err != nil {
|
||||
return &Xml{&v}, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 加载xml文件内容,并转换为xml对象
|
||||
func Load (path string) (*Xml, error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var result interface{}
|
||||
if err := xml.Unmarshal(data, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Xml{ &result }, nil
|
||||
}
|
||||
|
||||
// 将变量转换为Xml对象进行处理,该变量至少应当是一个map或者array,否者转换没有意义
|
||||
func NewXml(v *interface{}) *Xml {
|
||||
return &Xml{ v }
|
||||
}
|
||||
|
||||
// 将指定的xml内容转换为指定结构返回,查找失败或者转换失败,目标对象转换为nil
|
||||
// 注意第二个参数需要给的是变量地址
|
||||
func (p *Xml) GetToVar(pattern string, v interface{}) error {
|
||||
r := p.Get(pattern)
|
||||
if r != nil {
|
||||
if t, err := Encode(r); err == nil {
|
||||
return DecodeTo(t, v)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
v = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获得一个键值对关联数组/哈希表,方便操作,不需要自己做类型转换
|
||||
// 注意,如果获取的值不存在,或者类型与xml类型不匹配,那么将会返回nil
|
||||
func (p *Xml) GetMap(pattern string) map[string]interface{} {
|
||||
result := p.Get(pattern)
|
||||
if result != nil {
|
||||
if r, ok := result.(map[string]interface{}); ok {
|
||||
return r
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 将检索值转换为Xml对象指针返回
|
||||
func (p *Xml) GetXml(pattern string) *Xml {
|
||||
result := p.Get(pattern)
|
||||
if result != nil {
|
||||
return &Xml{&result}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获得一个数组[]interface{},方便操作,不需要自己做类型转换
|
||||
// 注意,如果获取的值不存在,或者类型与xml类型不匹配,那么将会返回nil
|
||||
func (p *Xml) GetArray(pattern string) []interface{} {
|
||||
result := p.Get(pattern)
|
||||
if result != nil {
|
||||
if r, ok := result.([]interface{}); ok {
|
||||
return r
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 返回指定xml中的string
|
||||
func (p *Xml) GetString(pattern string) string {
|
||||
result := p.Get(pattern)
|
||||
if result != nil {
|
||||
if r, ok := result.(string); ok {
|
||||
return r
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 返回指定xml中的bool
|
||||
func (p *Xml) GetBool(pattern string) bool {
|
||||
result := p.Get(pattern)
|
||||
if result != nil {
|
||||
str := fmt.Sprintf("%v", result)
|
||||
if str != "" && str != "0" && str != "false" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 返回指定xml中的float64
|
||||
func (p *Xml) GetFloat64(pattern string) float64 {
|
||||
result := p.Get(pattern)
|
||||
if result != nil {
|
||||
if r, ok := result.(float64); ok {
|
||||
return r
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 返回指定xml中的float64->int
|
||||
func (p *Xml) GetInt(pattern string) int {
|
||||
return int(p.GetFloat64(pattern))
|
||||
}
|
||||
|
||||
// 返回指定xml中的float64->int64
|
||||
func (p *Xml) GetInt64(pattern string) int64 {
|
||||
return int64(p.GetFloat64(pattern))
|
||||
}
|
||||
|
||||
// 根据约定字符串方式访问xml解析数据,参数形如: "items.name.first", "list.0"
|
||||
// 返回的结果类型的interface{},因此需要自己做类型转换
|
||||
// 如果找不到对应节点的数据,返回nil
|
||||
func (p *Xml) Get(pattern string) interface{} {
|
||||
var result interface{}
|
||||
pointer := p.value
|
||||
array := strings.Split(pattern, ".")
|
||||
length := len(array)
|
||||
for i:= 0; i < length; i++ {
|
||||
switch (*pointer).(type) {
|
||||
case map[string]interface{}:
|
||||
if v, ok := (*pointer).(map[string]interface{})[array[i]]; ok {
|
||||
if i == length - 1 {
|
||||
result = v
|
||||
} else {
|
||||
pointer = &v
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case []interface{}:
|
||||
if isNumeric(array[i]) {
|
||||
n, err := strconv.Atoi(array[i])
|
||||
if err == nil && len((*pointer).([]interface{})) > n {
|
||||
if i == length - 1 {
|
||||
result = (*pointer).([]interface{})[n]
|
||||
break;
|
||||
} else {
|
||||
pointer = &(*pointer).([]interface{})[n]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 转换为map[string]interface{}类型,如果转换失败,返回nil
|
||||
func (p *Xml) ToMap() map[string]interface{} {
|
||||
pointer := p.value
|
||||
switch (*pointer).(type) {
|
||||
case map[string]interface{}:
|
||||
return (*pointer).(map[string]interface{})
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// 转换为[]interface{}类型,如果转换失败,返回nil
|
||||
func (p *Xml) ToArray() []interface{} {
|
||||
pointer := p.value
|
||||
switch (*pointer).(type) {
|
||||
case []interface{}:
|
||||
return (*pointer).([]interface{})
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 判断所给字符串是否为数字
|
||||
func isNumeric(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] < byte('0') || s[i] > byte('9') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
32
g/encoding/gxml/gxml_test.go
Normal file
32
g/encoding/gxml/gxml_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
package gxml_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"fmt"
|
||||
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
var content = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<servers version="1">
|
||||
<server>
|
||||
<serverName>Shanghai_VPN</serverName>
|
||||
<serverIP>127.0.0.1</serverIP>
|
||||
</server>
|
||||
<server>
|
||||
<serverName>Beijing_VPN</serverName>
|
||||
<serverIP>127.0.0.2</serverIP>
|
||||
</server>
|
||||
</servers>`
|
||||
func Test_Xml(t *testing.T) {
|
||||
//xml, err := gxml.Decode(bytes.TrimSpace([]byte(content)))
|
||||
//if err != nil {
|
||||
// glog.Error(err)
|
||||
//}
|
||||
|
||||
//v := make(map[string]interface{})
|
||||
v := make([]interface{}, 0)
|
||||
e := xml.Unmarshal([]byte(content), &v)
|
||||
fmt.Println(e)
|
||||
fmt.Println(v)
|
||||
}
|
||||
@ -1,5 +1,44 @@
|
||||
// 通用数据验证工具
|
||||
// 本来打算取名gvalidator的,名字太长了,缩写一下
|
||||
/*
|
||||
参考:https://laravel.com/docs/5.5/validation#available-validation-rules
|
||||
规则如下:
|
||||
required 格式:required 说明:必需参数
|
||||
required_if 格式:required_if:field,value,... 说明:必需参数(当给定字段值与所给任意值相等时)
|
||||
required_with 格式:required_with:foo,bar,... 说明:必需参数(当所给定任意字段值不为空时)
|
||||
required_with_all 格式:required_with_all:foo,bar,... 说明:必须参数(当所给定所有字段值都不为空时)
|
||||
date 格式:date 说明:参数为常用日期类型,格式:2006-01-02, 20060102, 2006.01.02
|
||||
date_format 格式:date_format:format 说明:判断日期是否为指定的日期格式,format为Go日期格式(可以包含时间)
|
||||
email 格式:email 说明:EMAIL邮箱地址
|
||||
phone 格式:phone 说明:手机号
|
||||
telephone 格式:telephone 说明:国内座机电话号码,"XXXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"、"XXXXXXXX"
|
||||
passport 格式:passport 说明:通用帐号规则(字母开头,只能包含字母、数字和下划线,长度在6~18之间)
|
||||
password 格式:password 说明:通用密码(任意可见字符,长度在6~18之间)
|
||||
password2 格式:password2 说明:中等强度密码(在弱密码的基础上,必须包含大小写字母和数字)
|
||||
password3 格式:password3 说明:强等强度密码(在弱密码的基础上,必须包含大小写字母、数字和特殊字符)
|
||||
postcode 格式:id_number 说明:中国邮政编码
|
||||
id_number 格式:id_number 说明:公民身份证号码
|
||||
qq 格式:qq 说明:腾讯QQ号码
|
||||
ip 格式:ip 说明:IP地址(IPv4)
|
||||
mac 格式:mac 说明:MAC地址
|
||||
url 格式:url 说明:URL
|
||||
length 格式:length:min,max 说明:参数长度为min到max
|
||||
min_length 格式:min_length:min 说明:参数长度最小为min
|
||||
max_length 格式:max_length:max 说明:参数长度最大为max
|
||||
between 格式:between:min,max 说明:参数大小为min到max
|
||||
min 格式:min:min 说明:参数最小为min
|
||||
max 格式:max:max 说明:参数最大为max
|
||||
json 格式:json 说明:判断数据格式为JSON
|
||||
xml 格式:xml 说明:判断数据格式为XML
|
||||
integer 格式:integer 说明:整数
|
||||
float 格式:float 说明:浮点数
|
||||
boolean 格式:boolean 说明:布尔值(1,true,on,yes:true | 0,false,off,no,"":false)
|
||||
same 格式:same:field 说明:参数值必需与field参数的值相同
|
||||
different 格式:different:field 说明:参数值不能与field参数的值相同
|
||||
in 格式:in:foo,bar,... 说明:参数值应该在foo,bar,...中
|
||||
not_in 格式:not_in:foo,bar,... 说明:参数值不应该在foo,bar,...中
|
||||
regex 格式:regex:pattern 说明:参数值应当满足正则匹配规则pattern(使用preg_match判断)
|
||||
*/
|
||||
package gvalid
|
||||
|
||||
import (
|
||||
@ -70,56 +109,104 @@ func CheckRule(value, rule string, values...map[string]string) map[string]string
|
||||
match = !(value == "")
|
||||
break
|
||||
|
||||
//// 必须字段(当给定字段值与所给任意值相等时)
|
||||
//case "required_if":
|
||||
// array := strings.Split(strings.TrimSpace(ruleval), ",")
|
||||
// for _, v := range array {
|
||||
// if strings.Compare(value, strings.TrimSpace(v)) == 0 {
|
||||
// match = true
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// break
|
||||
//
|
||||
//// 必须字段(当所给定任意字段值不为空时)
|
||||
//case "required_with":
|
||||
// $ruleMatch = false;
|
||||
// $tmpArray = explode(',', $ruleAttr);
|
||||
// foreach ($tmpArray as $v) {
|
||||
//if (!empty(self::$_currentData[$v])) {
|
||||
//$ruleMatch = true;
|
||||
//break
|
||||
//}
|
||||
//}
|
||||
// break
|
||||
//
|
||||
// // 必须字段(当所给定所有字段值都不为空时)
|
||||
//case "required_with_all":
|
||||
// $tmpArray = explode(',', $ruleAttr);
|
||||
// foreach ($tmpArray as $v) {
|
||||
//if (empty(self::$_currentData[$v])) {
|
||||
//$ruleMatch = false;
|
||||
//break
|
||||
//}
|
||||
//}
|
||||
// break
|
||||
// 必须字段(当给定字段值与所给任意值相等时)
|
||||
case "required_if":
|
||||
required := false
|
||||
array := strings.Split(strings.TrimSpace(ruleval), ",")
|
||||
// 必须为偶数,才能是键值对匹配
|
||||
if len(array)%2 == 0 {
|
||||
for i := 0; i < len(array); {
|
||||
tk := array[i]
|
||||
tv := array[i + 1]
|
||||
if v, ok := params[tk]; ok {
|
||||
if strings.Compare(tv, v) == 0 {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
}
|
||||
i += 2
|
||||
}
|
||||
}
|
||||
if required {
|
||||
match = !(value == "")
|
||||
} else {
|
||||
match = true
|
||||
}
|
||||
break
|
||||
|
||||
// 必须字段(当所给定任意字段值不为空时)
|
||||
case "required_with":
|
||||
required := false
|
||||
array := strings.Split(strings.TrimSpace(ruleval), ",")
|
||||
for i := 0; i < len(array); i++ {
|
||||
if v, ok := params[array[i]]; ok {
|
||||
if v != "" {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if required {
|
||||
match = !(value == "")
|
||||
} else {
|
||||
match = true
|
||||
}
|
||||
break
|
||||
|
||||
// 必须字段(当所给定所有字段值都不为空时)
|
||||
case "required_with_all":
|
||||
required := true
|
||||
array := strings.Split(strings.TrimSpace(ruleval), ",")
|
||||
for i := 0; i < len(array); i++ {
|
||||
if v, ok := params[array[i]]; ok {
|
||||
if v == "" {
|
||||
required = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if required {
|
||||
match = !(value == "")
|
||||
} else {
|
||||
match = true
|
||||
}
|
||||
break
|
||||
|
||||
// 日期格式,
|
||||
case "date":
|
||||
for _, v := range []string{"2006-01-02", "20060102", "2006.01.02"} {
|
||||
if _, err := gtime.StrToTime(value, v); err == nil {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
// 日期格式,需要给定日期格式
|
||||
case "date":
|
||||
case "date_format":
|
||||
if _, err := gtime.StrToTime(value, ruleval); err == nil {
|
||||
match = true
|
||||
}
|
||||
break
|
||||
|
||||
// // 两字段值应相同(非敏感字符判断,非类型判断)
|
||||
//case "same":
|
||||
// $ruleMatch = (isset(self::$_currentData[$ruleAttr]) && $value == self::$_currentData[$ruleAttr]);
|
||||
// break
|
||||
//
|
||||
// // 两字段值不应相同(非敏感字符判断,非类型判断)
|
||||
//case "different":
|
||||
// $ruleMatch = (!isset(self::$_currentData[$ruleAttr]) || $value != self::$_currentData[$ruleAttr]);
|
||||
// break
|
||||
// 两字段值应相同(非敏感字符判断,非类型判断)
|
||||
case "same":
|
||||
if v, ok := params[ruleval]; ok {
|
||||
if strings.Compare(value, v) == 0 {
|
||||
match = true
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
// 两字段值不应相同(非敏感字符判断,非类型判断)
|
||||
case "different":
|
||||
match = true
|
||||
if v, ok := params[ruleval]; ok {
|
||||
if strings.Compare(value, v) == 0 {
|
||||
match = false
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
// 字段值应当在指定范围中
|
||||
case "in":
|
||||
@ -161,9 +248,7 @@ func CheckRule(value, rule string, values...map[string]string) map[string]string
|
||||
match = gregx.IsMatchString(`^13[\d]{9}$|^14[5,7]{1}\d{8}$|^15[^4]{1}\d{8}$|^17[0,3,5,6,7,8]{1}\d{8}$|^18[\d]{9}$`, value)
|
||||
break
|
||||
|
||||
/*
|
||||
* 国内座机电话号码:"XXXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"、"XXXXXXXX"
|
||||
*/
|
||||
// 国内座机电话号码:"XXXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"、"XXXXXXXX"
|
||||
case "telephone":
|
||||
match = gregx.IsMatchString(`^((\d{3,4})|\d{3,4}-)?\d{7,8}$`, value)
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user