Skip to content

Commit

Permalink
Add AddElement function with continuation support
Browse files Browse the repository at this point in the history
Introduced the Element.AddElement function to support the
creation of child elements with continuation functions.
  • Loading branch information
beevik committed Jan 21, 2025
1 parent 8965a48 commit 0da9e6a
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
22 changes: 21 additions & 1 deletion etree.go
Original file line number Diff line number Diff line change
Expand Up @@ -752,13 +752,33 @@ func (e *Element) findTermCharDataIndex(start int) int {
}

// CreateElement creates a new element with the specified tag (i.e., name) and
// adds it as the last child token of this element. The tag may include a
// adds it as the last child token of the element e. The tag may include a
// prefix followed by a colon.
func (e *Element) CreateElement(tag string) *Element {
space, stag := spaceDecompose(tag)
return newElement(space, stag, e)
}

// AddElement performs the same task as CreateElement but calls a continuation
// function after the child element is created, allowing additional actions to
// be performed on the child element before returning.
//
// This method of element creation is particularly useful when building nested
// XML documents from code. For example:
//
// org := doc.AddElement("organization", func(e *Element) {
// e.AddElement("person", func(e *Element) {
// e.CreateAttr("name", "Mary")
// e.CreateAttr("age", "30")
// e.CreateAttr("hair", "brown")
// })
// })
func (e *Element) AddElement(tag string, cont func(e *Element)) *Element {
child := e.CreateElement(tag)
cont(child)
return child
}

// AddChild adds the token 't' as the last child of the element. If token 't'
// was already the child of another element, it is first removed from its
// parent element.
Expand Down
53 changes: 53 additions & 0 deletions etree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1629,3 +1629,56 @@ func TestSiblingElement(t *testing.T) {
}
}
}

func TestContinuations(t *testing.T) {
doc := NewDocument()
root := doc.AddElement("root", func(e *Element) {
e.AddElement("child1", func(e *Element) {
e.CreateComment("Grandchildren of child #1")
e.AddElement("grandchild1", func(e *Element) {
e.CreateAttr("attr1", "1")
e.CreateAttr("attr2", "2")
})
e.AddElement("grandchild2", func(e *Element) {
e.CreateAttr("attr1", "3")
e.CreateAttr("attr2", "4")
})
})
e.AddElement("child2", func(e *Element) {
e.CreateComment("Grandchildren of child #2")
e.AddElement("grandchild1", func(e *Element) {
e.CreateAttr("attr1", "5")
e.CreateAttr("attr2", "6")
})
e.AddElement("grandchild2", func(e *Element) {
e.CreateAttr("attr1", "7")
e.CreateAttr("attr2", "8")
})
})
})
checkStrEq(t, root.Tag, "root")

// Serialize the document to a string
doc.IndentTabs()
s, err := doc.WriteToString()
if err != nil {
t.Error("etree: failed to serialize document")
}

// Make sure the serialized XML matches expectation.
expected := `<root>
<child1>
<!--Grandchildren of child #1-->
<grandchild1 attr1="1" attr2="2"/>
<grandchild2 attr1="3" attr2="4"/>
</child1>
<child2>
<!--Grandchildren of child #2-->
<grandchild1 attr1="5" attr2="6"/>
<grandchild2 attr1="7" attr2="8"/>
</child2>
</root>
`

checkStrEq(t, s, expected)
}

0 comments on commit 0da9e6a

Please sign in to comment.