Skip to content

Commit 88db8bd

Browse files
authored
bpo-36831: Do not apply default namespace to unprefixed attributes in ElementPath. (#13201)
Also provide better grouping of the tokenizer tests.
1 parent 3aca40d commit 88db8bd

File tree

2 files changed

+29
-11
lines changed

2 files changed

+29
-11
lines changed

Lib/test/test_xml_etree.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,14 +1144,9 @@ def check(p, expected, namespaces=None):
11441144

11451145
# tests from the xml specification
11461146
check("*", ['*'])
1147-
check("{ns}*", ['{ns}*'])
1148-
check("{}*", ['{}*'])
1149-
check("{*}tag", ['{*}tag'])
1150-
check("{*}*", ['{*}*'])
11511147
check("text()", ['text', '()'])
11521148
check("@name", ['@', 'name'])
11531149
check("@*", ['@', '*'])
1154-
check("@{ns}attr", ['@', '{ns}attr'])
11551150
check("para[1]", ['para', '[', '1', ']'])
11561151
check("para[last()]", ['para', '[', 'last', '()', ']'])
11571152
check("*/para", ['*', '/', 'para'])
@@ -1163,19 +1158,39 @@ def check(p, expected, namespaces=None):
11631158
check("//olist/item", ['//', 'olist', '/', 'item'])
11641159
check(".", ['.'])
11651160
check(".//para", ['.', '//', 'para'])
1166-
check(".//{*}tag", ['.', '//', '{*}tag'])
11671161
check("..", ['..'])
11681162
check("../@lang", ['..', '/', '@', 'lang'])
11691163
check("chapter[title]", ['chapter', '[', 'title', ']'])
11701164
check("employee[@secretary and @assistant]", ['employee',
11711165
'[', '@', 'secretary', '', 'and', '', '@', 'assistant', ']'])
11721166

11731167
# additional tests
1168+
check("@{ns}attr", ['@', '{ns}attr'])
11741169
check("{http://spam}egg", ['{http://spam}egg'])
11751170
check("./spam.egg", ['.', '/', 'spam.egg'])
11761171
check(".//{http://spam}egg", ['.', '//', '{http://spam}egg'])
1172+
1173+
# wildcard tags
1174+
check("{ns}*", ['{ns}*'])
1175+
check("{}*", ['{}*'])
1176+
check("{*}tag", ['{*}tag'])
1177+
check("{*}*", ['{*}*'])
1178+
check(".//{*}tag", ['.', '//', '{*}tag'])
1179+
1180+
# namespace prefix resolution
11771181
check("./xsd:type", ['.', '/', '{http://www.w3.org/2001/XMLSchema}type'],
11781182
{'xsd': 'http://www.w3.org/2001/XMLSchema'})
1183+
check("type", ['{http://www.w3.org/2001/XMLSchema}type'],
1184+
{'': 'http://www.w3.org/2001/XMLSchema'})
1185+
check("@xsd:type", ['@', '{http://www.w3.org/2001/XMLSchema}type'],
1186+
{'xsd': 'http://www.w3.org/2001/XMLSchema'})
1187+
check("@type", ['@', 'type'],
1188+
{'': 'http://www.w3.org/2001/XMLSchema'})
1189+
check("@{*}type", ['@', '{*}type'],
1190+
{'': 'http://www.w3.org/2001/XMLSchema'})
1191+
check("@{ns}attr", ['@', '{ns}attr'],
1192+
{'': 'http://www.w3.org/2001/XMLSchema',
1193+
'ns': 'http://www.w3.org/2001/XMLSchema'})
11791194

11801195
def test_processinginstruction(self):
11811196
# Test ProcessingInstruction directly

Lib/xml/etree/ElementPath.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,23 +72,27 @@
7272

7373
def xpath_tokenizer(pattern, namespaces=None):
7474
default_namespace = namespaces.get('') if namespaces else None
75+
parsing_attribute = False
7576
for token in xpath_tokenizer_re.findall(pattern):
76-
tag = token[1]
77+
ttype, tag = token
7778
if tag and tag[0] != "{":
7879
if ":" in tag:
7980
prefix, uri = tag.split(":", 1)
8081
try:
8182
if not namespaces:
8283
raise KeyError
83-
yield token[0], "{%s}%s" % (namespaces[prefix], uri)
84+
yield ttype, "{%s}%s" % (namespaces[prefix], uri)
8485
except KeyError:
8586
raise SyntaxError("prefix %r not found in prefix map" % prefix) from None
86-
elif default_namespace:
87-
yield token[0], "{%s}%s" % (default_namespace, tag)
87+
elif default_namespace and not parsing_attribute:
88+
yield ttype, "{%s}%s" % (default_namespace, tag)
8889
else:
8990
yield token
91+
parsing_attribute = False
9092
else:
9193
yield token
94+
parsing_attribute = ttype == '@'
95+
9296

9397
def get_parent_map(context):
9498
parent_map = context.parent_map
@@ -100,7 +104,6 @@ def get_parent_map(context):
100104
return parent_map
101105

102106

103-
104107
def _is_wildcard_tag(tag):
105108
return tag[:3] == '{*}' or tag[-2:] == '}*'
106109

0 commit comments

Comments
 (0)