package processor import ( "strings" "testing" "github.com/antchfx/xmlquery" ) func TestXMLProcessor_Process_TextNodes(t *testing.T) { // Test XML file with price tags that we want to modify testXML := ` Gambardella, Matthew XML Developer's Guide Computer 44.95 2000-10-01 Ralls, Kim Midnight Rain Fantasy 5.95 2000-12-16 ` // Create an XML processor processor := NewXMLProcessor(&TestLogger{}) // Process the XML content directly to double all prices xpathExpr := "//price/text()" modifiedXML, modCount, matchCount, err := processor.ProcessContent(testXML, xpathExpr, "v1 = v1 * 2", "*2") if err != nil { t.Fatalf("Failed to process XML content: %v", err) } // Check that we found and modified the correct number of nodes if matchCount != 2 { t.Errorf("Expected to match 2 nodes, got %d", matchCount) } if modCount != 2 { t.Errorf("Expected to modify 2 nodes, got %d", modCount) } // Check that prices were doubled if !strings.Contains(modifiedXML, "89.9") { t.Errorf("Modified content does not contain doubled price 89.9") } if !strings.Contains(modifiedXML, "11.9") { t.Errorf("Modified content does not contain doubled price 11.9") } // Verify we can parse the XML after modification _, err = xmlquery.Parse(strings.NewReader(modifiedXML)) if err != nil { t.Errorf("Modified XML is not valid: %v", err) } } func TestXMLProcessor_Process_Elements(t *testing.T) { // Test XML file with elements that we want to modify attributes of testXML := ` ` // Create an XML processor processor := NewXMLProcessor(&TestLogger{}) // Process the file to modify the value attribute // We'll create a more complex Lua script that deals with the node table luaScript := ` -- Get the current value attribute local valueAttr = node.attributes.value if valueAttr then -- Convert to number and add 50 local numValue = tonumber(valueAttr) if numValue then -- Update the value in the attributes table node.attributes.value = tostring(numValue + 50) end end ` // Process the XML content directly xpathExpr := "//item" modifiedXML, modCount, matchCount, err := processor.ProcessContent(testXML, xpathExpr, luaScript, "Add 50 to values") if err != nil { t.Fatalf("Failed to process XML content: %v", err) } // Check that we found and modified the correct number of nodes if matchCount != 3 { t.Errorf("Expected to match 3 item nodes, got %d", matchCount) } if modCount != 3 { t.Errorf("Expected to modify 3 nodes, got %d", modCount) } // Check that values were increased by 50 if !strings.Contains(modifiedXML, `value="150"`) { t.Errorf("Modified content does not contain updated value 150") } if !strings.Contains(modifiedXML, `value="250"`) { t.Errorf("Modified content does not contain updated value 250") } if !strings.Contains(modifiedXML, `value="350"`) { t.Errorf("Modified content does not contain updated value 350") } // Verify we can parse the XML after modification _, err = xmlquery.Parse(strings.NewReader(modifiedXML)) if err != nil { t.Errorf("Modified XML is not valid: %v", err) } } // New test for adding attributes to XML elements func TestXMLProcessor_AddAttributes(t *testing.T) { testXML := ` Content Another ` processor := NewXMLProcessor(&TestLogger{}) // Add a new attribute to each element luaScript := ` -- Add a new attribute node.attributes.status = "active" -- Also add another attribute with a sequential number node.attributes.index = tostring(_POSITION) ` xpathExpr := "//element" modifiedXML, modCount, matchCount, err := processor.ProcessContent(testXML, xpathExpr, luaScript, "Add attributes") if err != nil { t.Fatalf("Failed to process XML content: %v", err) } // Check counts if matchCount != 2 { t.Errorf("Expected to match 2 nodes, got %d", matchCount) } if modCount != 2 { t.Errorf("Expected to modify 2 nodes, got %d", modCount) } // Verify the new attributes if !strings.Contains(modifiedXML, `status="active"`) { t.Errorf("Modified content does not contain added status attribute") } if !strings.Contains(modifiedXML, `index="1"`) && !strings.Contains(modifiedXML, `index="2"`) { t.Errorf("Modified content does not contain added index attributes") } // Verify the XML is valid _, err = xmlquery.Parse(strings.NewReader(modifiedXML)) if err != nil { t.Errorf("Modified XML is not valid: %v", err) } } // Test for adding new child elements func TestXMLProcessor_AddChildElements(t *testing.T) { testXML := ` Product One 10.99 Product Two 20.99 ` processor := NewXMLProcessor(&TestLogger{}) // Add a new child element to each product luaScript := ` -- Create a new "discount" child element local discount = create_node("discount") -- Calculate discount as 10% of price local priceText = "" for _, child in ipairs(node.children) do if child.name == "price" and child.children[1] then priceText = child.children[1].data break end end local price = tonumber(priceText) or 0 local discountValue = price * 0.1 -- Add text content to the discount element discount.children[1] = {type="text", data=string.format("%.2f", discountValue)} -- Add the new element as a child add_child(node, discount) ` xpathExpr := "//product" modifiedXML, modCount, matchCount, err := processor.ProcessContent(testXML, xpathExpr, luaScript, "Add discount elements") if err != nil { t.Fatalf("Failed to process XML content: %v", err) } // Check counts if matchCount != 2 { t.Errorf("Expected to match 2 nodes, got %d", matchCount) } if modCount != 2 { t.Errorf("Expected to modify 2 nodes, got %d", modCount) } // Verify the new elements if !strings.Contains(modifiedXML, "1.10") { t.Errorf("Modified content does not contain first discount element") } if !strings.Contains(modifiedXML, "2.10") { t.Errorf("Modified content does not contain second discount element") } // Verify the XML is valid _, err = xmlquery.Parse(strings.NewReader(modifiedXML)) if err != nil { t.Errorf("Modified XML is not valid: %v", err) } } // Test for complex XML transformations func TestXMLProcessor_ComplexTransformation(t *testing.T) { testXML := ` ` processor := NewXMLProcessor(&TestLogger{}) // Complex transformation that changes attributes based on name luaScript := ` local name = node.attributes.name local value = node.attributes.value if name == "timeout" then -- Double the timeout node.attributes.value = tostring(tonumber(value) * 2) -- Add a unit attribute node.attributes.unit = "seconds" elseif name == "retries" then -- Increase retries by 2 node.attributes.value = tostring(tonumber(value) + 2) -- Add a comment element as sibling local comment = create_node("comment") comment.children[1] = {type="text", data="Increased for reliability"} -- We can't directly add siblings in this implementation -- But this would be the place to do it if supported elseif name == "enabled" and value == "true" then -- Add a priority attribute for enabled settings node.attributes.priority = "high" end ` xpathExpr := "//setting" modifiedXML, _, matchCount, err := processor.ProcessContent(testXML, xpathExpr, luaScript, "Transform settings") if err != nil { t.Fatalf("Failed to process XML content: %v", err) } // Check counts if matchCount != 3 { t.Errorf("Expected to match 3 nodes, got %d", matchCount) } // Verify the transformed attributes if !strings.Contains(modifiedXML, `value="60"`) { t.Errorf("Modified content does not have doubled timeout value") } if !strings.Contains(modifiedXML, `unit="seconds"`) { t.Errorf("Modified content does not have added unit attribute") } if !strings.Contains(modifiedXML, `value="5"`) { t.Errorf("Modified content does not have increased retries value") } if !strings.Contains(modifiedXML, `priority="high"`) { t.Errorf("Modified content does not have added priority attribute") } // Verify the XML is valid _, err = xmlquery.Parse(strings.NewReader(modifiedXML)) if err != nil { t.Errorf("Modified XML is not valid: %v", err) } } // Test for handling special XML characters func TestXMLProcessor_SpecialCharacters(t *testing.T) { testXML := ` "here"]]> Regular & text with markup ` processor := NewXMLProcessor(&TestLogger{}) // Process text nodes, being careful with special characters luaScript := ` -- For text nodes, replace & with & s1 = string.gsub(s1, "&([^;])", "&%1") ` xpathExpr := "//item/text()" modifiedXML, _, _, err := processor.ProcessContent(testXML, xpathExpr, luaScript, "Handle special chars") if err != nil { t.Fatalf("Failed to process XML content: %v", err) } // CDATA sections should be preserved if !strings.Contains(modifiedXML, "