Skip to content

Commit

Permalink
Add CreateChild to create elements with continuations
Browse files Browse the repository at this point in the history
Introduced the Element.CreateChild function to support the
creation of child elements with continuation functions.
  • Loading branch information
beevik committed Jan 28, 2025
1 parent 8965a48 commit 2f54d4f
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 2 deletions.
25 changes: 23 additions & 2 deletions etree.go
Original file line number Diff line number Diff line change
Expand Up @@ -752,13 +752,34 @@ 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
// prefix followed by a colon.
// adds it as the last child of 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)
}

// CreateChild 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.CreateChild("organization", func(e *Element) {
// e.CreateComment("Mary")
// e.CreateChild("person", func(e *Element) {
// e.CreateAttr("name", "Mary")
// e.CreateAttr("age", "30")
// e.CreateAttr("hair", "brown")
// })
// })
func (e *Element) CreateChild(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.CreateChild("root", func(e *Element) {
e.CreateChild("child1", func(e *Element) {
e.CreateComment("Grandchildren of child #1")
e.CreateChild("grandchild1", func(e *Element) {
e.CreateAttr("attr1", "1")
e.CreateAttr("attr2", "2")
})
e.CreateChild("grandchild2", func(e *Element) {
e.CreateAttr("attr1", "3")
e.CreateAttr("attr2", "4")
})
})
e.CreateChild("child2", func(e *Element) {
e.CreateComment("Grandchildren of child #2")
e.CreateChild("grandchild1", func(e *Element) {
e.CreateAttr("attr1", "5")
e.CreateAttr("attr2", "6")
})
e.CreateChild("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 2f54d4f

Please sign in to comment.