From 17e1b696207a3149c34f7d95f862913a2108ac67 Mon Sep 17 00:00:00 2001 From: Guido Witmond Date: Mon, 5 Jan 2015 17:13:46 +0100 Subject: [PATCH 1/2] Added Node.SetValue(string) method. SetValue replaces all children of the current node with a single NT_TEXT node and sets its Value to the given parameter. This lets us replace node values before writing out the document. --- node.go | 7 +++++ xmlx_test.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/node.go b/node.go index 5972d05..3add181 100644 --- a/node.go +++ b/node.go @@ -66,6 +66,13 @@ func (this *Node) GetValue() string { return res } +func (this *Node) SetValue(val string) { + t := NewNode(NT_TEXT) + t.Value = string([]byte(val)) + t.Parent = this + this.Children = []*Node{t} // brutally replace all other children +} + // Get node value as string func (this *Node) S(namespace, name string) string { foundNode := rec_SelectNode(this, namespace, name) diff --git a/xmlx_test.go b/xmlx_test.go index 1da420b..2f50fbd 100644 --- a/xmlx_test.go +++ b/xmlx_test.go @@ -251,3 +251,78 @@ func TestElementNodeValueFetch(t *testing.T) { t.Errorf("Failed to get availability using B, got: %v, wanted: true", v) } } + +func TestElementNodeValueFetchAndSet(t *testing.T) { + IndentPrefix = "" + + data := ` + r + edBMW50 + .256 + 2 + + Tr + + ue` + doc := New() + + if err := doc.LoadString(data, nil); nil != err { + t.Fatalf("LoadString(): %s", err) + } + + carN := doc.SelectNode("", "car") + if carN == nil { + t.Fatalf("Failed to get the car, got nil, wanted Node{car}") + } + + colorNode := carN.SelectNode("", "color") + if colorNode == nil { + t.Fatalf("Failed to get the color, got nil, wanted Node{color}") + } + + colorVal := colorNode.GetValue() + if colorVal != "red" { + t.Fatalf("Failed to get the color, got %v, wanted 'red'", colorVal) + } + + colorNode.SetValue("blue") + + expected := `blueBMW50 + .256 + 2 + + Tr + + ue` + + + if got := doc.Root.String(); got != expected { + t.Fatalf("expected: \n%s\ngot: \n%s\n", expected, got) + } + + // now set the brand + brandNode := carN.SelectNode("", "brand") + if brandNode == nil { + t.Fatalf("Failed to get the color, got nil, wanted Node{brand}") + } + + brandVal := brandNode.GetValue() + if brandVal != "BMW" { + t.Fatalf("Failed to get the brand, got %v, wanted 'BMW'", brandVal) + } + + brandNode.SetValue("Trabant") + + // Notice, we lose the tag in BMW, that's intentional + expected = `blueTrabant50 + .256 + 2 + + Tr + + ue` + + if got := doc.Root.String(); got != expected { + t.Fatalf("expected: \n%s\ngot: \n%s\n", expected, got) + } +} From 305e0dc0dadbf14b5a67d013d5838cd894156b39 Mon Sep 17 00:00:00 2001 From: Guido Witmond Date: Mon, 5 Jan 2015 20:54:53 +0100 Subject: [PATCH 2/2] Fixed a needless conversion to byte and string. Added comment to show the purpose. Added testcase. --- node.go | 4 +++- xmlx_test.go | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/node.go b/node.go index 3add181..e18df87 100644 --- a/node.go +++ b/node.go @@ -66,9 +66,11 @@ func (this *Node) GetValue() string { return res } +// SetValue sets the value of the node to the given parameter. +// It deletes all children of the node so the old data does not get back at node.GetValue func (this *Node) SetValue(val string) { t := NewNode(NT_TEXT) - t.Value = string([]byte(val)) + t.Value = val t.Parent = this this.Children = []*Node{t} // brutally replace all other children } diff --git a/xmlx_test.go b/xmlx_test.go index 2f50fbd..192aa20 100644 --- a/xmlx_test.go +++ b/xmlx_test.go @@ -4,7 +4,10 @@ package xmlx -import "testing" +import ( + "testing" + "encoding/xml" +) func TestLoadLocal(t *testing.T) { doc := New() @@ -252,6 +255,45 @@ func TestElementNodeValueFetch(t *testing.T) { } } +// node.SetValue(x); x == node.GetValue +func TestElementNodeValueFetchAndSetIdentity (t *testing.T) { + // Setup: xyzzy + // The xmlx parser creates a nameless NT_TEXT node containing the value 'xyzzy' + rootN := NewNode(NT_ROOT) + rootN.Name = xml.Name{Space: "", Local: "root"} + textN := NewNode(NT_ELEMENT) + textN.Name = xml.Name{Space: "", Local: "text"} + namelessN := NewNode(NT_TEXT) + namelessN.Value = "xyzzy" + rootN.AddChild(textN) + textN.AddChild(namelessN) + + targetN := rootN.SelectNode("", "text") // selects textN + if (targetN != textN) { + t.Errorf("Failed to get the correct textN, got %#v", targetN) + } + + // targetN.Value is empty (as the value lives in the childNode) + if (targetN.Value != "") { + t.Errorf("Failed to prepare correctly, TargetN.Value is not empty, it contains %#v", targetN.Value) + } + + // Test correct retrieval + if v := rootN.S("", "text"); v != "xyzzy" { + t.Errorf("Failed to get value as string, got: '%s', wanted: 'xyzzy'", v) + } + + // Set the value of the nameless child + targetN.SetValue("plugh") + + // Test correct retrieval + if v := rootN.S("", "text"); v != "plugh" { + t.Errorf("Failed to get value as string, got: '%s', wanted: 'plugh'", v) + } +} + +// Test as it could be used to read in a XML file, change some values and write it out again. +// For example, a HTML/XML proxy service. func TestElementNodeValueFetchAndSet(t *testing.T) { IndentPrefix = ""