Skip to content
Merged
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
23 changes: 19 additions & 4 deletions src/emeraldtree/ElementPath.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
33 changes: 21 additions & 12 deletions src/emeraldtree/tests/test_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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'
Expand Down
3 changes: 2 additions & 1 deletion src/emeraldtree/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down