python / python/cpython

ElementTree.find doesn't use registered namespaces when .find is called, and the inconsistency between ElementTree and ElementPath in how namespaces are defined

Open
#140,123 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

stdlib topic-XML type-bug
Dominant language
Python
Stars
77.2k
Forks
36k
PR merge metrics
PR metrics pending

Description

example xml: xml/example.xml

<root>

<h:title xmlns:h="http://www.w3.org/TR/html4/">
  <h:tr>
    <h:td>Apples</h:td>
    <h:td>Bananas</h:td>
  </h:tr>
</h:title>

<f:table xmlns:f="http://www.w3.org/TR/html4/">
  <f:name>African Coffee Table</f:name>
  <f:width>80</f:width>
  <f:length>120</f:length>
</f:table>

</root>

minimal example

import xml.etree.ElementTree as ET

ns = {"h": "http://www.w3.org/TR/html4/", "f": "http://www.w3.org/TR/html4/"}
for prefix, uri in ns.items():
    ET.register_namespace(prefix, uri)

tree = ET.parse("xml/example.xml")

print(tree._root) # <Element 'root' at 0x000002F6570FD940>

print(tree.find(".//{http://www.w3.org/TR/html4/}title")) # <Element '{http://www.w3.org/TR/html4/}title' at 0x000002F6570FD9E0>

print(tree.find(".//h:title", namespaces=ns)) # <Element '{http://www.w3.org/TR/html4/}title' at 0x000002F6570FD9E0>

print(tree.find(".//f:table", namespaces=ns)) # <Element '{http://www.w3.org/TR/html4/}table' at 0x000002F6570FDC60>

print(tree.find(".//f:table")) # SyntaxError: prefix 'f' not found in prefix map

When using the ET.register_namespace function the docstring mentions that it is global. But then when .find is used on a ElementTree instance the namespaces isn't passed on to the ElementPath that is used to find the element.

during the dig as to why the global register wasn't registering i also found an inconsistency in the way the namespaces are define between the ElementTree and the ElementPath:

https://github.com/python/cpython/blob/3490a99046078e4f9df7ac7570f62a0181bb3b89/Lib/xml/etree/ElementTree.py#L996
At the end of the register_namespace function:
_namespace_map[uri] = prefix

https://github.com/python/cpython/blob/3490a99046078e4f9df7ac7570f62a0181bb3b89/Lib/xml/etree/ElementPath.py#L85C46-L85C64
At the end of the xpath_tokenizer function:
namespaces[prefix]

the ElementTree also doesn't allow for multiple prefixes to point to the same URI where the ElementPath class has no issue with it, which i assume is a choice to allow for the serlization of the xml?

Linked PRs
  • gh-140364

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the namespace handling in Lib/xml/etree/ElementTree.py, especially register_namespace, and compare it with xpath_tokenizer in Lib/xml/etree/ElementPath.py. Review linked PR gh-140364 and the provided XML examples; done means the namespace behavior and prefix handling are consistent with the agreed resolution.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.