diff --git a/src/emeraldtree/ElementPath.py b/src/emeraldtree/ElementPath.py index 55b9952..72166ed 100644 --- a/src/emeraldtree/ElementPath.py +++ b/src/emeraldtree/ElementPath.py @@ -106,6 +106,10 @@ def select(context, result): if parent_map is None: context.parent_map = parent_map = {} for p in context.root.iter(): + try: + iter(p) + except TypeError: + continue for e in p: parent_map[e] = p for elem in result: @@ -146,10 +150,21 @@ def select(context, result): token = next() if token[0] != "]": raise SyntaxError("invalid node predicate") - def select(context, result): - for elem in result: - if elem.find(tag) is not None: - yield elem + try: + index = int(tag) + except ValueError: + def select(context, result): + for elem in result: + if elem.find(tag) is not None: + yield elem + else: + if index < 1: + raise SyntaxError("XPath position >= 1 expected") + def select(context, result): + for i, elem in enumerate(result): + if i + 1 == index: + yield elem + break else: raise SyntaxError("invalid predicate") return select diff --git a/src/emeraldtree/tests/test_tree.py b/src/emeraldtree/tests/test_tree.py index 5aff12e..22b52a5 100644 --- a/src/emeraldtree/tests/test_tree.py +++ b/src/emeraldtree/tests/test_tree.py @@ -170,21 +170,25 @@ def test_Element_findall_bracketed_tag(): assert result[0] is b1 # b1 has 'c' childs def test_Element_findall_dotdot(): - pytest.skip('broken') - c1 = Element('c') - c2 = Element('c') + d1 = Element('d') + d2 = Element('d') text = "text" - b1 = Element('b', children=(c1, text, c2)) - b2 = Element('b') - a1 = Element('a', children=(b1, b2, )) - + c1 = Element('c', children=(d1, text, d2)) + b1 = Element('b') + a1 = Element('a', children=(b1, c1, )) + + # this is something we can not support. + # we do not have parent pointers and also we only have a context starting from c1 here. + # we give an empty result, similar to stdlib elementree, which has the same limitation. result = list(c1.findall('../c')) - assert len(result) == 2 + assert len(result) == 0 + + # this is something we can support as we start at a higher element. + result = list(a1.findall('b/../c')) + assert len(result) == 1 assert result[0] is c1 - assert result[1] is c2 def test_Element_findall_slashslash(): - pytest.skip('broken') c1 = Element('c') c2 = Element('c') text = "text" @@ -199,7 +203,6 @@ def test_Element_findall_slashslash(): assert result[1] is c2 def test_Element_findall_dotslashslash(): - pytest.skip('broken') c1 = Element('c') c2 = Element('c') text = "text" @@ -235,7 +238,6 @@ def test_Element_findall_attribute(): assert len(result) == 0 def test_Element_findall_position(): - pytest.skip('not supported') c1 = Element('c') c2 = Element('c') text = "text" @@ -251,6 +253,13 @@ def test_Element_findall_position(): assert len(result) == 1 assert result[0] is c2 +def test_Element_findall_position_invalid(): + b1 = Element('b') + with pytest.raises(SyntaxError): + list(b1.findall('c[0]')) + with pytest.raises(SyntaxError): + list(b1.findall('c[-1]')) + def test_Element_findtext_default(): elem = Element('a') default_text = 'defaulttext' diff --git a/src/emeraldtree/tree.py b/src/emeraldtree/tree.py index b2ebff7..82783c5 100644 --- a/src/emeraldtree/tree.py +++ b/src/emeraldtree/tree.py @@ -355,7 +355,8 @@ def iter(self, tag=None): for e in e.iter(tag): yield e else: - yield e + if tag is None: + yield e ## # Creates a text iterator. The iterator loops over this element