Skip to content

Commit 4354d63

Browse files
committed
Add continuation function support during element creation
Introduced the Element.Create function and CreateContinuation type.
1 parent 65fc6ef commit 4354d63

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

etree.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,13 +751,38 @@ func (e *Element) findTermCharDataIndex(start int) int {
751751
}
752752

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

761+
// CreateContinuation is a continuation-passing interface for building
762+
// XML documents in a more nested manner. See the description of its
763+
// use in the Element Create function.
764+
type CreateContinuation func(e *Element)
765+
766+
// Create creates a new element with the specified tag (i.e., name) and adds
767+
// it as the last child token of the element e. The tag may include a prefix
768+
// followed by a colon. After creating the element, Create calls the
769+
// continuation function to perform additional actions on the created child
770+
// element.
771+
//
772+
// This method of creating elements is useful when building nested XML
773+
// document from code. For example:
774+
//
775+
// doc.Create("organization", func(e *Element) {
776+
// e.Create("person", func(e *Element) {
777+
// e.CreateAttr("name", "Mary")
778+
// e.CreateAttr("age", "30")
779+
// e.CreateAttr("hair", "brown")
780+
// })
781+
// })
782+
func (e *Element) Create(tag string, f CreateContinuation) {
783+
f(e.CreateElement(tag))
784+
}
785+
761786
// AddChild adds the token 't' as the last child of the element. If token 't'
762787
// was already the child of another element, it is first removed from its
763788
// parent element.

etree_test.go

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

0 commit comments

Comments
 (0)