diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2019-04-14 08:09:09 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-14 08:09:09 (GMT) |
commit | e9927e1820caea01e576141d9a623ea394d43dad (patch) | |
tree | 4f758ae025e9b5c1bb6198bb4524571da118489f /Lib/xml | |
parent | ffca16e25a70fd44a87b13b379b5ec0c7a11e926 (diff) | |
download | cpython-e9927e1820caea01e576141d9a623ea394d43dad.zip cpython-e9927e1820caea01e576141d9a623ea394d43dad.tar.gz cpython-e9927e1820caea01e576141d9a623ea394d43dad.tar.bz2 |
bpo-30485: support a default prefix mapping in ElementPath by passing None as prefix (#1823)
Diffstat (limited to 'Lib/xml')
-rw-r--r-- | Lib/xml/etree/ElementPath.py | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/Lib/xml/etree/ElementPath.py b/Lib/xml/etree/ElementPath.py index ef32917..0e3854f 100644 --- a/Lib/xml/etree/ElementPath.py +++ b/Lib/xml/etree/ElementPath.py @@ -71,16 +71,22 @@ xpath_tokenizer_re = re.compile( ) def xpath_tokenizer(pattern, namespaces=None): + default_namespace = namespaces.get(None) if namespaces else None for token in xpath_tokenizer_re.findall(pattern): tag = token[1] - if tag and tag[0] != "{" and ":" in tag: - try: + if tag and tag[0] != "{": + if ":" in tag: prefix, uri = tag.split(":", 1) - if not namespaces: - raise KeyError - yield token[0], "{%s}%s" % (namespaces[prefix], uri) - except KeyError: - raise SyntaxError("prefix %r not found in prefix map" % prefix) from None + try: + if not namespaces: + raise KeyError + yield token[0], "{%s}%s" % (namespaces[prefix], uri) + except KeyError: + raise SyntaxError("prefix %r not found in prefix map" % prefix) from None + elif default_namespace: + yield token[0], "{%s}%s" % (default_namespace, tag) + else: + yield token else: yield token @@ -264,10 +270,19 @@ 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?) + + cache_key = (path,) + if namespaces: + if '' in namespaces: + raise ValueError("empty namespace prefix must be passed as None, not the empty string") + if None in namespaces: + cache_key += (namespaces[None],) + tuple(sorted( + item for item in namespaces.items() if item[0] is not None)) + else: + cache_key += tuple(sorted(namespaces.items())) + try: selector = _cache[cache_key] except KeyError: |