summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Bendersky <eliben@gmail.com>2013-08-04 00:47:47 (GMT)
committerEli Bendersky <eliben@gmail.com>2013-08-04 00:47:47 (GMT)
commit2acc525a972b2b6b071eb5b9596ed1390d6d98e0 (patch)
tree84b50e968dab06dba7229eef4046f286c56cd53e
parent3ceaff0777059c770836e817160f6a81b60c7b18 (diff)
downloadcpython-2acc525a972b2b6b071eb5b9596ed1390d6d98e0.zip
cpython-2acc525a972b2b6b071eb5b9596ed1390d6d98e0.tar.gz
cpython-2acc525a972b2b6b071eb5b9596ed1390d6d98e0.tar.bz2
Issue #17011: Fix caching of xpath path when namespaces are present.
Thanks to Stefan Behnel for the report and proposed solution & test.
-rw-r--r--Lib/test/test_xml_etree.py14
-rw-r--r--Lib/xml/etree/ElementPath.py6
2 files changed, 18 insertions, 2 deletions
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index 4c2e26f..402bc2d 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -1679,6 +1679,20 @@ class ElementFindTest(unittest.TestCase):
summarize_list(e.findall(".//{http://effbot.org/ns}tag")),
['{http://effbot.org/ns}tag'] * 3)
+ def test_findall_different_nsmaps(self):
+ root = ET.XML('''
+ <a xmlns:x="X" xmlns:y="Y">
+ <x:b><c/></x:b>
+ <b/>
+ <c><x:b/><b/></c><y:b/>
+ </a>''')
+ nsmap = {'xx': 'X'}
+ self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
+ self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
+ nsmap = {'xx': 'Y'}
+ self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1)
+ self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
+
def test_bad_find(self):
e = ET.XML(SAMPLE_XML)
with self.assertRaisesRegex(SyntaxError, 'cannot use absolute path'):
diff --git a/Lib/xml/etree/ElementPath.py b/Lib/xml/etree/ElementPath.py
index 52e65f0..e7015c7 100644
--- a/Lib/xml/etree/ElementPath.py
+++ b/Lib/xml/etree/ElementPath.py
@@ -246,10 +246,12 @@ class _SelectorContext:
def iterfind(elem, path, namespaces=None):
# compile selector pattern
+ cache_key = (path, None if namespaces is None
+ else tuple(sorted(namespaces.items())))
if path[-1:] == "/":
path = path + "*" # implicit all (FIXME: keep this?)
try:
- selector = _cache[path]
+ selector = _cache[cache_key]
except KeyError:
if len(_cache) > 100:
_cache.clear()
@@ -269,7 +271,7 @@ def iterfind(elem, path, namespaces=None):
token = next()
except StopIteration:
break
- _cache[path] = selector
+ _cache[cache_key] = selector
# execute selector pattern
result = [elem]
context = _SelectorContext(elem)