Implement parsing xml to and from lua
A lot more complex than json.........
This commit is contained in:
235
processor/xml.go
235
processor/xml.go
@@ -59,68 +59,55 @@ func (p *XMLProcessor) ProcessContent(content string, path string, luaExpr strin
|
|||||||
}
|
}
|
||||||
log.Printf("%#v", result)
|
log.Printf("%#v", result)
|
||||||
|
|
||||||
// Apply modification
|
// Apply modification based on the result
|
||||||
// if node.Type == xmlquery.AttributeNode {
|
if updatedValue, ok := result.(string); ok {
|
||||||
// // For attribute nodes, update the attribute value
|
// If the result is a simple string, update the node value directly
|
||||||
// node.Parent.Attr = append([]xmlquery.Attr{}, node.Parent.Attr...)
|
xpath.Set(doc, path, updatedValue)
|
||||||
// for i, attr := range node.Parent.Attr {
|
} else if nodeData, ok := result.(map[string]interface{}); ok {
|
||||||
// if attr.Name.Local == node.Data {
|
// If the result is a map, apply more complex updates
|
||||||
// node.Parent.Attr[i].Value = newValue
|
updateNodeFromMap(node, nodeData)
|
||||||
// break
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else if node.Type == xmlquery.TextNode {
|
|
||||||
// // For text nodes, update the text content
|
|
||||||
// node.Data = newValue
|
|
||||||
// } else {
|
|
||||||
// // For element nodes, replace inner text
|
|
||||||
// // Simple approach: set the InnerText directly if there are no child elements
|
|
||||||
// if node.FirstChild == nil || (node.FirstChild != nil && node.FirstChild.Type == xmlquery.TextNode && node.FirstChild.NextSibling == nil) {
|
|
||||||
// if node.FirstChild != nil {
|
|
||||||
// node.FirstChild.Data = newValue
|
|
||||||
// } else {
|
|
||||||
// // Create a new text node and add it as the first child
|
|
||||||
// textNode := &xmlquery.Node{
|
|
||||||
// Type: xmlquery.TextNode,
|
|
||||||
// Data: newValue,
|
|
||||||
// }
|
|
||||||
// node.FirstChild = textNode
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// // Complex case: node has mixed content or child elements
|
|
||||||
// // Replace just the text content while preserving child elements
|
|
||||||
// // This is a simplified approach - more complex XML may need more robust handling
|
|
||||||
// for child := node.FirstChild; child != nil; child = child.NextSibling {
|
|
||||||
// if child.Type == xmlquery.TextNode {
|
|
||||||
// child.Data = newValue
|
|
||||||
// break // Update only the first text node
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
modCount++
|
modCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize the modified XML document to string
|
// Serialize the modified XML document to string
|
||||||
// if doc.FirstChild != nil && doc.FirstChild.Type == xmlquery.DeclarationNode {
|
if doc.FirstChild != nil && doc.FirstChild.Type == xmlquery.DeclarationNode {
|
||||||
// // If we have an XML declaration, start with it
|
// If we have an XML declaration, start with it
|
||||||
// declaration := doc.FirstChild.OutputXML(true)
|
declaration := doc.FirstChild.OutputXML(true)
|
||||||
// // Remove the firstChild (declaration) before serializing the rest of the document
|
// Remove the firstChild (declaration) before serializing the rest of the document
|
||||||
// doc.FirstChild = doc.FirstChild.NextSibling
|
doc.FirstChild = doc.FirstChild.NextSibling
|
||||||
// return declaration + doc.OutputXML(true), modCount, matchCount, nil
|
return declaration + doc.OutputXML(true), modCount, matchCount, nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
// return doc.OutputXML(true), modCount, matchCount, nil
|
return doc.OutputXML(true), modCount, matchCount, nil
|
||||||
return "", modCount, matchCount, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToLua converts XML node values to Lua variables
|
// ToLua converts XML node values to Lua variables
|
||||||
func (p *XMLProcessor) ToLua(L *lua.LState, data interface{}) error {
|
func (p *XMLProcessor) ToLua(L *lua.LState, data interface{}) error {
|
||||||
table, err := ToLua(L, data)
|
// Check if data is an xmlquery.Node
|
||||||
if err != nil {
|
node, ok := data.(*xmlquery.Node)
|
||||||
return err
|
if !ok {
|
||||||
|
return fmt.Errorf("expected xmlquery.Node, got %T", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a simple table with essential data
|
||||||
|
table := L.NewTable()
|
||||||
|
|
||||||
|
// For element nodes, just provide basic info
|
||||||
|
L.SetField(table, "type", lua.LString(nodeTypeToString(node.Type)))
|
||||||
|
L.SetField(table, "name", lua.LString(node.Data))
|
||||||
|
L.SetField(table, "value", lua.LString(node.InnerText()))
|
||||||
|
|
||||||
|
// Add attributes if any
|
||||||
|
if len(node.Attr) > 0 {
|
||||||
|
attrs := L.NewTable()
|
||||||
|
for _, attr := range node.Attr {
|
||||||
|
L.SetField(attrs, attr.Name.Local, lua.LString(attr.Value))
|
||||||
|
}
|
||||||
|
L.SetField(table, "attributes", attrs)
|
||||||
|
}
|
||||||
|
|
||||||
L.SetGlobal("v", table)
|
L.SetGlobal("v", table)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -128,5 +115,149 @@ func (p *XMLProcessor) ToLua(L *lua.LState, data interface{}) error {
|
|||||||
// FromLua gets modified values from Lua
|
// FromLua gets modified values from Lua
|
||||||
func (p *XMLProcessor) FromLua(L *lua.LState) (interface{}, error) {
|
func (p *XMLProcessor) FromLua(L *lua.LState) (interface{}, error) {
|
||||||
luaValue := L.GetGlobal("v")
|
luaValue := L.GetGlobal("v")
|
||||||
return FromLua(L, luaValue)
|
|
||||||
|
// Handle string values directly
|
||||||
|
if luaValue.Type() == lua.LTString {
|
||||||
|
return luaValue.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle tables (for attributes and more complex updates)
|
||||||
|
if luaValue.Type() == lua.LTTable {
|
||||||
|
return luaTableToMap(L, luaValue.(*lua.LTable)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return luaValue.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple helper to convert a Lua table to a Go map
|
||||||
|
func luaTableToMap(L *lua.LState, table *lua.LTable) map[string]interface{} {
|
||||||
|
result := make(map[string]interface{})
|
||||||
|
|
||||||
|
table.ForEach(func(k, v lua.LValue) {
|
||||||
|
if k.Type() == lua.LTString {
|
||||||
|
key := k.String()
|
||||||
|
|
||||||
|
if v.Type() == lua.LTTable {
|
||||||
|
result[key] = luaTableToMap(L, v.(*lua.LTable))
|
||||||
|
} else {
|
||||||
|
result[key] = v.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple helper to convert node type to string
|
||||||
|
func nodeTypeToString(nodeType xmlquery.NodeType) string {
|
||||||
|
switch nodeType {
|
||||||
|
case xmlquery.ElementNode:
|
||||||
|
return "element"
|
||||||
|
case xmlquery.TextNode:
|
||||||
|
return "text"
|
||||||
|
case xmlquery.AttributeNode:
|
||||||
|
return "attribute"
|
||||||
|
default:
|
||||||
|
return "other"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to update an XML node from a map
|
||||||
|
func updateNodeFromMap(node *xmlquery.Node, data map[string]interface{}) {
|
||||||
|
// Update node value if present
|
||||||
|
if value, ok := data["value"]; ok {
|
||||||
|
if strValue, ok := value.(string); ok {
|
||||||
|
// For element nodes, replace text content
|
||||||
|
if node.Type == xmlquery.ElementNode {
|
||||||
|
// Find the first text child if it exists
|
||||||
|
var textNode *xmlquery.Node
|
||||||
|
for child := node.FirstChild; child != nil; child = child.NextSibling {
|
||||||
|
if child.Type == xmlquery.TextNode {
|
||||||
|
textNode = child
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if textNode != nil {
|
||||||
|
// Update existing text node
|
||||||
|
textNode.Data = strValue
|
||||||
|
} else {
|
||||||
|
// Create new text node
|
||||||
|
newText := &xmlquery.Node{
|
||||||
|
Type: xmlquery.TextNode,
|
||||||
|
Data: strValue,
|
||||||
|
Parent: node,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert at beginning of children
|
||||||
|
if node.FirstChild != nil {
|
||||||
|
newText.NextSibling = node.FirstChild
|
||||||
|
node.FirstChild.PrevSibling = newText
|
||||||
|
node.FirstChild = newText
|
||||||
|
} else {
|
||||||
|
node.FirstChild = newText
|
||||||
|
node.LastChild = newText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if node.Type == xmlquery.TextNode {
|
||||||
|
// Directly update text node
|
||||||
|
node.Data = strValue
|
||||||
|
} else if node.Type == xmlquery.AttributeNode {
|
||||||
|
// Update attribute value
|
||||||
|
if node.Parent != nil {
|
||||||
|
for i, attr := range node.Parent.Attr {
|
||||||
|
if attr.Name.Local == node.Data {
|
||||||
|
node.Parent.Attr[i].Value = strValue
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update attributes if present
|
||||||
|
if attrs, ok := data["attributes"].(map[string]interface{}); ok && node.Type == xmlquery.ElementNode {
|
||||||
|
for name, value := range attrs {
|
||||||
|
if strValue, ok := value.(string); ok {
|
||||||
|
// Look for existing attribute
|
||||||
|
found := false
|
||||||
|
for i, attr := range node.Attr {
|
||||||
|
if attr.Name.Local == name {
|
||||||
|
node.Attr[i].Value = strValue
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new attribute if not found
|
||||||
|
if !found {
|
||||||
|
node.Attr = append(node.Attr, xmlquery.Attr{
|
||||||
|
Name: struct {
|
||||||
|
Space, Local string
|
||||||
|
}{Local: name},
|
||||||
|
Value: strValue,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to get a string representation of node type
|
||||||
|
func nodeTypeName(nodeType xmlquery.NodeType) string {
|
||||||
|
switch nodeType {
|
||||||
|
case xmlquery.ElementNode:
|
||||||
|
return "element"
|
||||||
|
case xmlquery.TextNode:
|
||||||
|
return "text"
|
||||||
|
case xmlquery.AttributeNode:
|
||||||
|
return "attribute"
|
||||||
|
case xmlquery.CommentNode:
|
||||||
|
return "comment"
|
||||||
|
case xmlquery.DeclarationNode:
|
||||||
|
return "declaration"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/antchfx/xmlquery"
|
||||||
|
lua "github.com/yuin/gopher-lua"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Helper function to normalize whitespace for comparison
|
// Helper function to normalize whitespace for comparison
|
||||||
@@ -56,7 +59,7 @@ func TestXMLProcessor_Process_NodeValues(t *testing.T) {
|
|||||||
</catalog>`
|
</catalog>`
|
||||||
|
|
||||||
p := &XMLProcessor{}
|
p := &XMLProcessor{}
|
||||||
result, modCount, matchCount, err := p.ProcessContent(content, "//price", "v = v * 2")
|
result, modCount, matchCount, err := p.ProcessContent(content, "//price", "v.value = v.value * 2")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error processing content: %v", err)
|
t.Fatalf("Error processing content: %v", err)
|
||||||
@@ -1530,3 +1533,267 @@ func TestXMLProcessor_Process_DeepPathNavigation(t *testing.T) {
|
|||||||
|
|
||||||
// Add more test cases for specific XML manipulation scenarios below
|
// Add more test cases for specific XML manipulation scenarios below
|
||||||
// These tests would cover additional functionality as the implementation progresses
|
// These tests would cover additional functionality as the implementation progresses
|
||||||
|
|
||||||
|
func TestXMLToLua(t *testing.T) {
|
||||||
|
// Sample XML to test with
|
||||||
|
xmlStr := `
|
||||||
|
<root id="1">
|
||||||
|
<person name="John" age="30">
|
||||||
|
<address type="home">
|
||||||
|
<street>123 Main St</street>
|
||||||
|
<city>Anytown</city>
|
||||||
|
<zip>12345</zip>
|
||||||
|
</address>
|
||||||
|
<contact type="email">john@example.com</contact>
|
||||||
|
</person>
|
||||||
|
<person name="Jane" age="28">
|
||||||
|
<address type="work">
|
||||||
|
<street>456 Business Ave</street>
|
||||||
|
<city>Worktown</city>
|
||||||
|
<zip>54321</zip>
|
||||||
|
</address>
|
||||||
|
<contact type="phone">555-1234</contact>
|
||||||
|
</person>
|
||||||
|
</root>
|
||||||
|
`
|
||||||
|
|
||||||
|
// Parse the XML
|
||||||
|
doc, err := xmlquery.Parse(strings.NewReader(xmlStr))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to parse XML: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Lua state
|
||||||
|
L := lua.NewState()
|
||||||
|
defer L.Close()
|
||||||
|
|
||||||
|
// Create an XML processor
|
||||||
|
processor := &XMLProcessor{}
|
||||||
|
|
||||||
|
// Test converting the root element to Lua
|
||||||
|
t.Run("RootElement", func(t *testing.T) {
|
||||||
|
// Find the root element
|
||||||
|
root := doc.SelectElement("root")
|
||||||
|
if root == nil {
|
||||||
|
t.Fatal("Failed to find root element")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to Lua
|
||||||
|
err := processor.ToLua(L, root)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to convert to Lua: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
luaTable := L.GetGlobal("v")
|
||||||
|
if luaTable.Type() != lua.LTTable {
|
||||||
|
t.Fatalf("Expected table, got %s", luaTable.Type().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check element type
|
||||||
|
typeVal := L.GetField(luaTable, "type")
|
||||||
|
if typeVal.String() != "element" {
|
||||||
|
t.Errorf("Expected type 'element', got '%s'", typeVal.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check name
|
||||||
|
nameVal := L.GetField(luaTable, "name")
|
||||||
|
if nameVal.String() != "root" {
|
||||||
|
t.Errorf("Expected name 'root', got '%s'", nameVal.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check attributes
|
||||||
|
attrsTable := L.GetField(luaTable, "attributes")
|
||||||
|
if attrsTable.Type() != lua.LTTable {
|
||||||
|
t.Fatalf("Expected attributes table, got %s", attrsTable.Type().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
idVal := L.GetField(attrsTable, "id")
|
||||||
|
if idVal.String() != "1" {
|
||||||
|
t.Errorf("Expected id '1', got '%s'", idVal.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we have children
|
||||||
|
childrenTable := L.GetField(luaTable, "children")
|
||||||
|
if childrenTable.Type() != lua.LTTable {
|
||||||
|
t.Fatalf("Expected children table, got %s", childrenTable.Type().String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test converting a nested element to Lua
|
||||||
|
t.Run("NestedElement", func(t *testing.T) {
|
||||||
|
// Find a nested element
|
||||||
|
street := doc.SelectElement("//street")
|
||||||
|
if street == nil {
|
||||||
|
t.Fatal("Failed to find street element")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to Lua
|
||||||
|
err := processor.ToLua(L, street)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to convert to Lua: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
luaTable := L.GetGlobal("v")
|
||||||
|
if luaTable.Type() != lua.LTTable {
|
||||||
|
t.Fatalf("Expected table, got %s", luaTable.Type().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check element type
|
||||||
|
typeVal := L.GetField(luaTable, "type")
|
||||||
|
if typeVal.String() != "element" {
|
||||||
|
t.Errorf("Expected type 'element', got '%s'", typeVal.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check name
|
||||||
|
nameVal := L.GetField(luaTable, "name")
|
||||||
|
if nameVal.String() != "street" {
|
||||||
|
t.Errorf("Expected name 'street', got '%s'", nameVal.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check value
|
||||||
|
valueVal := L.GetField(luaTable, "value")
|
||||||
|
if valueVal.String() != "123 Main St" {
|
||||||
|
t.Errorf("Expected value '123 Main St', got '%s'", valueVal.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test FromLua with a simple string update
|
||||||
|
t.Run("FromLuaString", func(t *testing.T) {
|
||||||
|
// Set up a Lua state with a string value
|
||||||
|
L := lua.NewState()
|
||||||
|
defer L.Close()
|
||||||
|
L.SetGlobal("v", lua.LString("New Value"))
|
||||||
|
|
||||||
|
// Convert from Lua
|
||||||
|
result, err := processor.FromLua(L)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to convert from Lua: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
strResult, ok := result.(string)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Expected string result, got %T", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strResult != "New Value" {
|
||||||
|
t.Errorf("Expected 'New Value', got '%s'", strResult)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test FromLua with a complex table update
|
||||||
|
t.Run("FromLuaTable", func(t *testing.T) {
|
||||||
|
// Set up a Lua state with a table value
|
||||||
|
L := lua.NewState()
|
||||||
|
defer L.Close()
|
||||||
|
|
||||||
|
table := L.NewTable()
|
||||||
|
L.SetField(table, "value", lua.LString("Updated Text"))
|
||||||
|
|
||||||
|
attrTable := L.NewTable()
|
||||||
|
L.SetField(attrTable, "id", lua.LString("new-id"))
|
||||||
|
L.SetField(attrTable, "class", lua.LString("highlight"))
|
||||||
|
|
||||||
|
L.SetField(table, "attributes", attrTable)
|
||||||
|
L.SetGlobal("v", table)
|
||||||
|
|
||||||
|
// Convert from Lua
|
||||||
|
result, err := processor.FromLua(L)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to convert from Lua: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
mapResult, ok := result.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Expected map result, got %T", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check value
|
||||||
|
if value, ok := mapResult["value"]; !ok || value != "Updated Text" {
|
||||||
|
t.Errorf("Expected value 'Updated Text', got '%v'", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check attributes
|
||||||
|
attrs, ok := mapResult["attributes"].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Expected attributes map, got %T", mapResult["attributes"])
|
||||||
|
}
|
||||||
|
|
||||||
|
if id, ok := attrs["id"]; !ok || id != "new-id" {
|
||||||
|
t.Errorf("Expected id 'new-id', got '%v'", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if class, ok := attrs["class"]; !ok || class != "highlight" {
|
||||||
|
t.Errorf("Expected class 'highlight', got '%v'", class)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test updateNodeFromMap with a simple value update
|
||||||
|
t.Run("UpdateNodeValue", func(t *testing.T) {
|
||||||
|
// Create a simple element to update
|
||||||
|
xmlStr := `<test>Original Text</test>`
|
||||||
|
doc, _ := xmlquery.Parse(strings.NewReader(xmlStr))
|
||||||
|
node := doc.SelectElement("test")
|
||||||
|
|
||||||
|
// Create update data
|
||||||
|
updateData := map[string]interface{}{
|
||||||
|
"value": "Updated Text",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the node
|
||||||
|
updateNodeFromMap(node, updateData)
|
||||||
|
|
||||||
|
// Verify the update
|
||||||
|
if node.InnerText() != "Updated Text" {
|
||||||
|
t.Errorf("Expected value 'Updated Text', got '%s'", node.InnerText())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test updateNodeFromMap with attribute updates
|
||||||
|
t.Run("UpdateNodeAttributes", func(t *testing.T) {
|
||||||
|
// Create an element with attributes
|
||||||
|
xmlStr := `<test id="old">Text</test>`
|
||||||
|
doc, _ := xmlquery.Parse(strings.NewReader(xmlStr))
|
||||||
|
node := doc.SelectElement("test")
|
||||||
|
|
||||||
|
// Create update data
|
||||||
|
updateData := map[string]interface{}{
|
||||||
|
"attributes": map[string]interface{}{
|
||||||
|
"id": "new",
|
||||||
|
"class": "added",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the node
|
||||||
|
updateNodeFromMap(node, updateData)
|
||||||
|
|
||||||
|
// Verify the id attribute was updated
|
||||||
|
idFound := false
|
||||||
|
classFound := false
|
||||||
|
for _, attr := range node.Attr {
|
||||||
|
if attr.Name.Local == "id" {
|
||||||
|
idFound = true
|
||||||
|
if attr.Value != "new" {
|
||||||
|
t.Errorf("Expected id 'new', got '%s'", attr.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if attr.Name.Local == "class" {
|
||||||
|
classFound = true
|
||||||
|
if attr.Value != "added" {
|
||||||
|
t.Errorf("Expected class 'added', got '%s'", attr.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !idFound {
|
||||||
|
t.Error("Expected to find 'id' attribute but didn't")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !classFound {
|
||||||
|
t.Error("Expected to find 'class' attribute but didn't")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user