diff options
author | Eli Bendersky <eliben@gmail.com> | 2013-08-04 00:47:47 (GMT) |
---|---|---|
committer | Eli Bendersky <eliben@gmail.com> | 2013-08-04 00:47:47 (GMT) |
commit | 2acc525a972b2b6b071eb5b9596ed1390d6d98e0 (patch) | |
tree | 84b50e968dab06dba7229eef4046f286c56cd53e | |
parent | 3ceaff0777059c770836e817160f6a81b60c7b18 (diff) | |
download | cpython-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.py | 14 | ||||
-rw-r--r-- | Lib/xml/etree/ElementPath.py | 6 |
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) |