Skip to content

Commit cc099d9

Browse files
committed
Add NextSibling and PrevSibling element functions
These functions make it easier to traverse sibling elements sharing the same parent element.
1 parent cda5fc4 commit cc099d9

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

etree.go

+28
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,34 @@ func (e *Element) dup(parent *Element) Token {
12741274
return ne
12751275
}
12761276

1277+
// NextSibling returns this element's next sibling element. It returns nil if
1278+
// there is no next sibling element.
1279+
func (e *Element) NextSibling() *Element {
1280+
if e.parent == nil {
1281+
return nil
1282+
}
1283+
for i := e.index + 1; i < len(e.parent.Child); i++ {
1284+
if s, ok := e.parent.Child[i].(*Element); ok {
1285+
return s
1286+
}
1287+
}
1288+
return nil
1289+
}
1290+
1291+
// PrevSibling returns this element's preceding sibling element. It returns
1292+
// nil if there is no preceding sibling element.
1293+
func (e *Element) PrevSibling() *Element {
1294+
if e.parent == nil {
1295+
return nil
1296+
}
1297+
for i := e.index - 1; i >= 0; i-- {
1298+
if s, ok := e.parent.Child[i].(*Element); ok {
1299+
return s
1300+
}
1301+
}
1302+
return nil
1303+
}
1304+
12771305
// Parent returns this element's parent element. It returns nil if this
12781306
// element has no parent.
12791307
func (e *Element) Parent() *Element {

etree_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -1587,3 +1587,46 @@ func TestValidateInput(t *testing.T) {
15871587
}
15881588
t.Run("ReadFromFile", func(t *testing.T) { runTests(t, readFromFile) })
15891589
}
1590+
1591+
func TestSiblingElement(t *testing.T) {
1592+
doc := newDocumentFromString(t, `<root><a/><b> <b1/> </b> <!--test--> <c/></root>`)
1593+
1594+
root := doc.SelectElement("root")
1595+
a := root.SelectElement("a")
1596+
b := root.SelectElement("b")
1597+
c := root.SelectElement("c")
1598+
b1 := b.SelectElement("b1")
1599+
1600+
tests := []struct {
1601+
e *Element
1602+
next *Element
1603+
prev *Element
1604+
}{
1605+
{root, nil, nil},
1606+
{a, b, nil},
1607+
{b, c, a},
1608+
{c, nil, b},
1609+
{b1, nil, nil},
1610+
}
1611+
1612+
toString := func(e *Element) string {
1613+
if e == nil {
1614+
return "nil"
1615+
}
1616+
return e.Tag
1617+
}
1618+
1619+
for i, test := range tests {
1620+
next := test.e.NextSibling()
1621+
if next != test.next {
1622+
t.Errorf("etree: test #%d unexpected NextSibling result.\n Expected: %s\n Received: %s\n",
1623+
i, toString(next), toString(test.next))
1624+
}
1625+
1626+
prev := test.e.PrevSibling()
1627+
if prev != test.prev {
1628+
t.Errorf("etree: test #%d unexpected PrevSibling result.\n Expected: %s\n Received: %s\n",
1629+
i, toString(prev), toString(test.prev))
1630+
}
1631+
}
1632+
}

0 commit comments

Comments
 (0)