Skip to content

Commit 4615956

Browse files
committed
Add continuation function support during element creation
Introduced the Element.Create function and CreateContinuation type.
1 parent 8965a48 commit 4615956

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

etree.go

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

etree_test.go

+48
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)