Fix the value fetcher to deal with NT_TEXT nodes.
Due to the introduction of the NT_TEXT nodes, all of the simple value fetchers broke. To fix, make a GetValue function fetch all NT_TEXT nodes for NT_ELEMENT nodes, and put them together, using string.TrimSpace to remove extra, maintaining compatibility. Then change the .S function to use GetValue to fetch a node's content. Also, make all the other value fetchers use .S to get a string representation to convert, centralizing the implementation. Use .S to centralize the handling of a not found node. Also, implement a series of tests to verify all the fetcher's functionality. The test is based on the test produced by Tim Jurcka.
This commit is contained in:
parent
d5a758279d
commit
38e440df97
99
node.go
99
node.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -54,20 +55,32 @@ func (this *Node) Unmarshal(obj interface{}) error {
|
||||||
return xml.NewDecoder(bytes.NewBuffer(this.bytes())).Decode(obj)
|
return xml.NewDecoder(bytes.NewBuffer(this.bytes())).Decode(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Node) GetValue() string {
|
||||||
|
res := ""
|
||||||
|
for _, node := range this.Children {
|
||||||
|
if node.Type == NT_TEXT {
|
||||||
|
res += strings.TrimSpace(node.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
// Get node value as string
|
// Get node value as string
|
||||||
func (this *Node) S(namespace, name string) string {
|
func (this *Node) S(namespace, name string) string {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
foundNode := rec_SelectNode(this, namespace, name)
|
||||||
if node != nil {
|
if foundNode == nil {
|
||||||
return node.Value
|
return ""
|
||||||
|
} else {
|
||||||
|
return foundNode.GetValue()
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get node value as int
|
// Get node value as int
|
||||||
func (this *Node) I(namespace, name string) int {
|
func (this *Node) I(namespace, name string) int {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseInt(node.Value, 10, 0)
|
n, _ := strconv.ParseInt(value, 10, 0)
|
||||||
return int(n)
|
return int(n)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -75,9 +88,9 @@ func (this *Node) I(namespace, name string) int {
|
||||||
|
|
||||||
// Get node value as int8
|
// Get node value as int8
|
||||||
func (this *Node) I8(namespace, name string) int8 {
|
func (this *Node) I8(namespace, name string) int8 {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseInt(node.Value, 10, 8)
|
n, _ := strconv.ParseInt(value, 10, 8)
|
||||||
return int8(n)
|
return int8(n)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -85,9 +98,9 @@ func (this *Node) I8(namespace, name string) int8 {
|
||||||
|
|
||||||
// Get node value as int16
|
// Get node value as int16
|
||||||
func (this *Node) I16(namespace, name string) int16 {
|
func (this *Node) I16(namespace, name string) int16 {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseInt(node.Value, 10, 16)
|
n, _ := strconv.ParseInt(value, 10, 16)
|
||||||
return int16(n)
|
return int16(n)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -95,9 +108,9 @@ func (this *Node) I16(namespace, name string) int16 {
|
||||||
|
|
||||||
// Get node value as int32
|
// Get node value as int32
|
||||||
func (this *Node) I32(namespace, name string) int32 {
|
func (this *Node) I32(namespace, name string) int32 {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseInt(node.Value, 10, 32)
|
n, _ := strconv.ParseInt(value, 10, 32)
|
||||||
return int32(n)
|
return int32(n)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -105,9 +118,9 @@ func (this *Node) I32(namespace, name string) int32 {
|
||||||
|
|
||||||
// Get node value as int64
|
// Get node value as int64
|
||||||
func (this *Node) I64(namespace, name string) int64 {
|
func (this *Node) I64(namespace, name string) int64 {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseInt(node.Value, 10, 64)
|
n, _ := strconv.ParseInt(value, 10, 64)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -115,9 +128,9 @@ func (this *Node) I64(namespace, name string) int64 {
|
||||||
|
|
||||||
// Get node value as uint
|
// Get node value as uint
|
||||||
func (this *Node) U(namespace, name string) uint {
|
func (this *Node) U(namespace, name string) uint {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseUint(node.Value, 10, 0)
|
n, _ := strconv.ParseUint(value, 10, 0)
|
||||||
return uint(n)
|
return uint(n)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -125,9 +138,9 @@ func (this *Node) U(namespace, name string) uint {
|
||||||
|
|
||||||
// Get node value as uint8
|
// Get node value as uint8
|
||||||
func (this *Node) U8(namespace, name string) uint8 {
|
func (this *Node) U8(namespace, name string) uint8 {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseUint(node.Value, 10, 8)
|
n, _ := strconv.ParseUint(value, 10, 8)
|
||||||
return uint8(n)
|
return uint8(n)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -135,9 +148,9 @@ func (this *Node) U8(namespace, name string) uint8 {
|
||||||
|
|
||||||
// Get node value as uint16
|
// Get node value as uint16
|
||||||
func (this *Node) U16(namespace, name string) uint16 {
|
func (this *Node) U16(namespace, name string) uint16 {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseUint(node.Value, 10, 16)
|
n, _ := strconv.ParseUint(value, 10, 16)
|
||||||
return uint16(n)
|
return uint16(n)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -145,9 +158,9 @@ func (this *Node) U16(namespace, name string) uint16 {
|
||||||
|
|
||||||
// Get node value as uint32
|
// Get node value as uint32
|
||||||
func (this *Node) U32(namespace, name string) uint32 {
|
func (this *Node) U32(namespace, name string) uint32 {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseUint(node.Value, 10, 32)
|
n, _ := strconv.ParseUint(value, 10, 32)
|
||||||
return uint32(n)
|
return uint32(n)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -155,9 +168,9 @@ func (this *Node) U32(namespace, name string) uint32 {
|
||||||
|
|
||||||
// Get node value as uint64
|
// Get node value as uint64
|
||||||
func (this *Node) U64(namespace, name string) uint64 {
|
func (this *Node) U64(namespace, name string) uint64 {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseUint(node.Value, 10, 64)
|
n, _ := strconv.ParseUint(value, 10, 64)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -165,9 +178,9 @@ func (this *Node) U64(namespace, name string) uint64 {
|
||||||
|
|
||||||
// Get node value as float32
|
// Get node value as float32
|
||||||
func (this *Node) F32(namespace, name string) float32 {
|
func (this *Node) F32(namespace, name string) float32 {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseFloat(node.Value, 32)
|
n, _ := strconv.ParseFloat(value, 32)
|
||||||
return float32(n)
|
return float32(n)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -175,9 +188,9 @@ func (this *Node) F32(namespace, name string) float32 {
|
||||||
|
|
||||||
// Get node value as float64
|
// Get node value as float64
|
||||||
func (this *Node) F64(namespace, name string) float64 {
|
func (this *Node) F64(namespace, name string) float64 {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseFloat(node.Value, 64)
|
n, _ := strconv.ParseFloat(value, 64)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -185,9 +198,9 @@ func (this *Node) F64(namespace, name string) float64 {
|
||||||
|
|
||||||
// Get node value as bool
|
// Get node value as bool
|
||||||
func (this *Node) B(namespace, name string) bool {
|
func (this *Node) B(namespace, name string) bool {
|
||||||
node := rec_SelectNode(this, namespace, name)
|
value := this.S(namespace, name)
|
||||||
if node != nil && node.Value != "" {
|
if value != "" {
|
||||||
n, _ := strconv.ParseBool(node.Value)
|
n, _ := strconv.ParseBool(value)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
67
xmlx_test.go
67
xmlx_test.go
|
@ -176,3 +176,70 @@ func TestStringEscaping(t *testing.T) {
|
||||||
t.Fatalf("expected: %s\ngot: %s\n", expected, got)
|
t.Fatalf("expected: %s\ngot: %s\n", expected, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestElementNodeValueFetch(t *testing.T) {
|
||||||
|
data := `<car><color>
|
||||||
|
r<cool />
|
||||||
|
ed</color><brand>BMW</brand><price>50
|
||||||
|
<cheap />.25</price><count>6
|
||||||
|
<small />2
|
||||||
|
</count><available>
|
||||||
|
Tr
|
||||||
|
<found />
|
||||||
|
ue</available></car>`
|
||||||
|
doc := New()
|
||||||
|
|
||||||
|
if err := doc.LoadString(data, nil); nil != err {
|
||||||
|
t.Fatalf("LoadString(): %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
carN := doc.SelectNode("", "car")
|
||||||
|
if v := carN.S("", "brand"); v != "BMW" {
|
||||||
|
t.Errorf("Failed to get brand as string, got: '%s', wanted: 'BMW'", v)
|
||||||
|
}
|
||||||
|
if v := carN.S("", "color"); v != "red" {
|
||||||
|
t.Errorf("Failed to get color as string, got: '%s', wanted: 'red'", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := carN.I("", "count"); v != 62 {
|
||||||
|
t.Errorf("Failed to get count using I, got: %v, wanted: 62", v)
|
||||||
|
}
|
||||||
|
if v := carN.I8("", "count"); v != 62 {
|
||||||
|
t.Errorf("Failed to get count using I8, got: %v, wanted: 62", v)
|
||||||
|
}
|
||||||
|
if v := carN.I16("", "count"); v != 62 {
|
||||||
|
t.Errorf("Failed to get count using I16, got: %v, wanted: 62", v)
|
||||||
|
}
|
||||||
|
if v := carN.I32("", "count"); v != 62 {
|
||||||
|
t.Errorf("Failed to get count using I32, got: %v, wanted: 62", v)
|
||||||
|
}
|
||||||
|
if v := carN.I64("", "count"); v != 62 {
|
||||||
|
t.Errorf("Failed to get count using I64, got: %v, wanted: 62", v)
|
||||||
|
}
|
||||||
|
if v := carN.U("", "count"); v != 62 {
|
||||||
|
t.Errorf("Failed to get count using U, got: %v, wanted: 62", v)
|
||||||
|
}
|
||||||
|
if v := carN.U8("", "count"); v != 62 {
|
||||||
|
t.Errorf("Failed to get count using U8, got: %v, wanted: 62", v)
|
||||||
|
}
|
||||||
|
if v := carN.U16("", "count"); v != 62 {
|
||||||
|
t.Errorf("Failed to get count using U16, got: %v, wanted: 62", v)
|
||||||
|
}
|
||||||
|
if v := carN.U32("", "count"); v != 62 {
|
||||||
|
t.Errorf("Failed to get count using U32, got: %v, wanted: 62", v)
|
||||||
|
}
|
||||||
|
if v := carN.U64("", "count"); v != 62 {
|
||||||
|
t.Errorf("Failed to get count using U64, got: %v, wanted: 62", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := carN.F32("", "price"); v != 50.25 {
|
||||||
|
t.Errorf("Failed to get price using F32, got: %v, wanted: 50.25", v)
|
||||||
|
}
|
||||||
|
if v := carN.F64("", "price"); v != 50.25 {
|
||||||
|
t.Errorf("Failed to get price using F64, got: %v, wanted: 50.25", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := carN.B("", "available"); v != true {
|
||||||
|
t.Errorf("Failed to get availability using B, got: %v, wanted: true", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue