Skip to content

Commit 0da9e6a

Browse files
committed
Add AddElement function with continuation support
Introduced the Element.AddElement function to support the creation of child elements with continuation functions.
1 parent 8965a48 commit 0da9e6a

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

etree.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,13 +752,33 @@ func (e *Element) findTermCharDataIndex(start int) int {
752752
}
753753

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

762+
// AddElement performs the same task as CreateElement but calls a continuation
763+
// function after the child element is created, allowing additional actions to
764+
// be performed on the child element before returning.
765+
//
766+
// This method of element creation is particularly useful when building nested
767+
// XML documents from code. For example:
768+
//
769+
// org := doc.AddElement("organization", func(e *Element) {
770+
// e.AddElement("person", func(e *Element) {
771+
// e.CreateAttr("name", "Mary")
772+
// e.CreateAttr("age", "30")
773+
// e.CreateAttr("hair", "brown")
774+
// })
775+
// })
776+
func (e *Element) AddElement(tag string, cont func(e *Element)) *Element {
777+
child := e.CreateElement(tag)
778+
cont(child)
779+
return child
780+
}
781+
762782
// AddChild adds the token 't' as the last child of the element. If token 't'
763783
// was already the child of another element, it is first removed from its
764784
// parent element.

etree_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,3 +1629,56 @@ func TestSiblingElement(t *testing.T) {
16291629
}
16301630
}
16311631
}
1632+
1633+
func TestContinuations(t *testing.T) {
1634+
doc := NewDocument()
1635+
root := doc.AddElement("root", func(e *Element) {
1636+
e.AddElement("child1", func(e *Element) {
1637+
e.CreateComment("Grandchildren of child #1")
1638+
e.AddElement("grandchild1", func(e *Element) {
1639+
e.CreateAttr("attr1", "1")
1640+
e.CreateAttr("attr2", "2")
1641+
})
1642+
e.AddElement("grandchild2", func(e *Element) {
1643+
e.CreateAttr("attr1", "3")
1644+
e.CreateAttr("attr2", "4")
1645+
})
1646+
})
1647+
e.AddElement("child2", func(e *Element) {
1648+
e.CreateComment("Grandchildren of child #2")
1649+
e.AddElement("grandchild1", func(e *Element) {
1650+
e.CreateAttr("attr1", "5")
1651+
e.CreateAttr("attr2", "6")
1652+
})
1653+
e.AddElement("grandchild2", func(e *Element) {
1654+
e.CreateAttr("attr1", "7")
1655+
e.CreateAttr("attr2", "8")
1656+
})
1657+
})
1658+
})
1659+
checkStrEq(t, root.Tag, "root")
1660+
1661+
// Serialize the document to a string
1662+
doc.IndentTabs()
1663+
s, err := doc.WriteToString()
1664+
if err != nil {
1665+
t.Error("etree: failed to serialize document")
1666+
}
1667+
1668+
// Make sure the serialized XML matches expectation.
1669+
expected := `<root>
1670+
<child1>
1671+
<!--Grandchildren of child #1-->
1672+
<grandchild1 attr1="1" attr2="2"/>
1673+
<grandchild2 attr1="3" attr2="4"/>
1674+
</child1>
1675+
<child2>
1676+
<!--Grandchildren of child #2-->
1677+
<grandchild1 attr1="5" attr2="6"/>
1678+
<grandchild2 attr1="7" attr2="8"/>
1679+
</child2>
1680+
</root>
1681+
`
1682+
1683+
checkStrEq(t, s, expected)
1684+
}

0 commit comments

Comments
 (0)