packer-plugin-xenserver/vendor/github.com/nilshell/xmlrpc/result.go
Phus Lu addd20360c Add Godeps
Signed-off-by: Phus Lu <phus.lu@citrix.com>
2016-07-15 09:44:41 -07:00

217 lines
4.1 KiB
Go

package xmlrpc
import (
"bytes"
"encoding/xml"
"fmt"
"strconv"
"strings"
"time"
)
// TIME_LAYOUT defines time template defined by iso8601, used to encode/decode time values.
const TIME_LAYOUT = "20060102T15:04:05"
func parseValue(valueXml []byte) (result interface{}, err error) {
parser := xml.NewDecoder(bytes.NewReader(valueXml))
result, err = getValue(parser)
return
}
func getValue(parser *xml.Decoder) (result interface{}, err error) {
var token xml.Token
token, err = parser.Token()
if err != nil {
return nil, err
}
for {
switch t := token.(type) {
case xml.StartElement:
switch t.Name.Local {
case "boolean":
return getBooleanValue(parser)
case "dateTime.iso8601":
return getDateValue(parser)
case "double":
return getDoubleValue(parser)
case "int", "i4", "i8":
return getIntValue(parser)
case "base64":
return getBase64Value(parser)
case "string":
return getStringValue(parser)
case "struct":
result, err = getStructValue(parser)
case "array":
result, err = getArrayValue(parser)
default:
// Move on
}
case xml.EndElement:
if t.Name.Local == "value" {
return result, nil
}
case xml.CharData:
cdata := strings.TrimSpace(string(t))
if cdata != "" {
result = cdata
}
}
token, err = parser.Token()
if err != nil {
return nil, err
}
}
return
}
func getBooleanValue(parser *xml.Decoder) (result interface{}, err error) {
var value string
value, err = getElementValue(parser)
switch value {
case "0":
return false, nil
case "1":
return true, nil
}
return nil, fmt.Errorf("Parse error: invalid boolean value (%s).", value)
}
func getDateValue(parser *xml.Decoder) (result interface{}, err error) {
var value string
value, err = getElementValue(parser)
result, err = time.Parse(TIME_LAYOUT, value)
return
}
func getDoubleValue(parser *xml.Decoder) (interface{}, error) {
value, _ := getElementValue(parser)
return strconv.ParseFloat(value, 64)
}
func getIntValue(parser *xml.Decoder) (interface{}, error) {
value, _ := getElementValue(parser)
var number int64
number, err := strconv.ParseInt(value, 0, 64)
return number, err
}
func getBase64Value(parser *xml.Decoder) (string, error) {
return getElementValue(parser)
}
func getStringValue(parser *xml.Decoder) (string, error) {
return getElementValue(parser)
}
func getStructValue(parser *xml.Decoder) (result interface{}, err error) {
var token xml.Token
token, err = parser.Token()
result = Struct{}
for {
switch t := token.(type) {
case xml.StartElement:
member := getStructMember(parser)
result.(Struct)[member["name"].(string)] = member["value"]
case xml.EndElement:
if t.Name.Local == "struct" {
return result, err
}
}
token, err = parser.Token()
}
return
}
func getStructMember(parser *xml.Decoder) (member Struct) {
var token xml.Token
token, _ = parser.Token()
member = Struct{}
for {
switch t := token.(type) {
case xml.StartElement:
if t.Name.Local == "name" {
member["name"], _ = getElementValue(parser)
}
if t.Name.Local == "value" {
member["value"], _ = getValue(parser)
}
case xml.EndElement:
if t.Name.Local == "member" {
return member
}
}
token, _ = parser.Token()
}
return
}
func getElementValue(parser *xml.Decoder) (value string, err error) {
var token xml.Token
token, err = parser.Token()
processing := true
for processing {
switch token.(type) {
case xml.CharData:
value = strings.TrimSpace(string(token.(xml.CharData)))
if value != "" {
processing = false
}
case xml.EndElement:
processing = false
}
token, err = parser.Token()
}
return
}
func getArrayValue(parser *xml.Decoder) (result interface{}, err error) {
var token xml.Token
token, err = parser.Token()
result = []interface{}{}
for {
switch t := token.(type) {
case xml.StartElement:
if t.Name.Local == "value" {
var value interface{}
value, err = getValue(parser)
result = append(result.([]interface{}), value)
}
case xml.EndElement:
if t.Name.Local == "array" {
return result, err
}
}
token, err = parser.Token()
}
return
}