Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Continuations #145

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
}
Loading