Skip to content

Commit

Permalink
Add NextSibling and PrevSibling element functions
Browse files Browse the repository at this point in the history
These functions make it easier to traverse sibling elements sharing the
same parent element.
  • Loading branch information
beevik committed May 3, 2024
1 parent cda5fc4 commit cc099d9
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
28 changes: 28 additions & 0 deletions etree.go
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,34 @@ func (e *Element) dup(parent *Element) Token {
return ne
}

// NextSibling returns this element's next sibling element. It returns nil if
// there is no next sibling element.
func (e *Element) NextSibling() *Element {
if e.parent == nil {
return nil
}
for i := e.index + 1; i < len(e.parent.Child); i++ {
if s, ok := e.parent.Child[i].(*Element); ok {
return s
}
}
return nil
}

// PrevSibling returns this element's preceding sibling element. It returns
// nil if there is no preceding sibling element.
func (e *Element) PrevSibling() *Element {
if e.parent == nil {
return nil
}
for i := e.index - 1; i >= 0; i-- {
if s, ok := e.parent.Child[i].(*Element); ok {
return s
}
}
return nil
}

// Parent returns this element's parent element. It returns nil if this
// element has no parent.
func (e *Element) Parent() *Element {
Expand Down
43 changes: 43 additions & 0 deletions etree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1587,3 +1587,46 @@ func TestValidateInput(t *testing.T) {
}
t.Run("ReadFromFile", func(t *testing.T) { runTests(t, readFromFile) })
}

func TestSiblingElement(t *testing.T) {
doc := newDocumentFromString(t, `<root><a/><b> <b1/> </b> <!--test--> <c/></root>`)

root := doc.SelectElement("root")
a := root.SelectElement("a")
b := root.SelectElement("b")
c := root.SelectElement("c")
b1 := b.SelectElement("b1")

tests := []struct {
e *Element
next *Element
prev *Element
}{
{root, nil, nil},
{a, b, nil},
{b, c, a},
{c, nil, b},
{b1, nil, nil},
}

toString := func(e *Element) string {
if e == nil {
return "nil"
}
return e.Tag
}

for i, test := range tests {
next := test.e.NextSibling()
if next != test.next {
t.Errorf("etree: test #%d unexpected NextSibling result.\n Expected: %s\n Received: %s\n",
i, toString(next), toString(test.next))
}

prev := test.e.PrevSibling()
if prev != test.prev {
t.Errorf("etree: test #%d unexpected PrevSibling result.\n Expected: %s\n Received: %s\n",
i, toString(prev), toString(test.prev))
}
}
}

0 comments on commit cc099d9

Please sign in to comment.