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, "