diff --git a/query.go b/query.go index 81d65af..2a71734 100644 --- a/query.go +++ b/query.go @@ -201,6 +201,8 @@ func (a *ancestorQuery) Select(t iterator) NodeNavigator { func (a *ancestorQuery) Evaluate(t iterator) interface{} { a.Input.Evaluate(t) a.iterator = nil + // Reset the table when re-evaluating to ensure clean state + a.table = nil return a } @@ -829,6 +831,8 @@ func (f *filterQuery) Select(t iterator) NodeNavigator { func (f *filterQuery) Evaluate(t iterator) interface{} { f.Input.Evaluate(t) + // Reset the position map when re-evaluating to ensure clean state + f.positmap = nil return f } diff --git a/xpath_axes_test.go b/xpath_axes_test.go index 44475ab..4969385 100644 --- a/xpath_axes_test.go +++ b/xpath_axes_test.go @@ -65,6 +65,28 @@ func Test_ancestor_predicate(t *testing.T) { test_xpath_elements(t, doc, `//span/ancestor::section[2]`, 4, 9) } +func Test_ancestor_predicate_chain(t *testing.T) { + doc := createElement(0, "", + createElement(1, "html", + createElementAttr(2, "body", map[string]string{"itemscope": "", "itemtype": "Article"}, + createElement(3, "section", + createElementAttr(4, "span", map[string]string{"itemprop": "author"}), + createElementAttr(5, "div", map[string]string{"itemscope": "", "itemtype": "Comment"}, + createElementAttr(6, "span", map[string]string{"itemprop": "author"}), + createElement(7, "div", + createElementAttr(8, "span", map[string]string{"itemprop": "author"}), + ), + ), + ), + ), + ), + ) + + // Find elements marked as "author" property whose closest "itemscope" ancestor is of "Comment" type. + // This should find "span" elements on lines 6 and 8, but not line 4 since that one is under "Article". + test_xpath_elements(t, doc, `//*[@itemprop="author"][ancestor::*[@itemscope][1][@itemtype="Comment"]]`, 6, 8) +} + func Test_ancestor_or_self(t *testing.T) { // Expected the value is [2, 3, 8, 13], but got [3, 2, 8, 13] test_xpath_elements(t, employee_example, `//employee/ancestor-or-self::*`, 3, 2, 8, 13) diff --git a/xpath_test.go b/xpath_test.go index 6d7de07..4d107f8 100644 --- a/xpath_test.go +++ b/xpath_test.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "math" + "reflect" "sort" "strings" "testing" @@ -41,10 +42,14 @@ func (t testQuery) Properties() queryProp { func test_xpath_elements(t *testing.T, root *TNode, expr string, expected ...int) { result := selectNodes(root, expr) - assertEqual(t, len(expected), len(result)) - for i := 0; i < len(expected); i++ { - assertEqual(t, expected[i], result[i].lines) + var gotLines []int + for i := 0; i < len(result); i++ { + gotLines = append(gotLines, result[i].lines) + } + + if !reflect.DeepEqual(gotLines, expected) { + t.Fatalf("expected lines %+v, got %+v", expected, gotLines) } } @@ -587,6 +592,14 @@ func (n *TNode) getAttribute(key string) string { return "" } +func createElementAttr(line int, name string, attrs map[string]string, children ...*TNode) *TNode { + el := createElement(line, name, children...) + for k, v := range attrs { + el.addAttribute(k, v) + } + return el +} + func createElement(line int, name string, children ...*TNode) *TNode { nodeType := ElementNode if name == "" {