Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 13d62fb

Browse files
[3.13] gh-157406: Report all document type declarations in the Python XMLParser (GH-157408) (GH-157410)
The Python implementation of XMLParser only reported a document type declaration with an external identifier. Use the Expat handler, like the C implementation does. (cherry picked from commit f802d2d) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 593fe91 commit 13d62fb

3 files changed

Lines changed: 29 additions & 33 deletions

File tree

Lib/test/test_xml_etree.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4000,6 +4000,21 @@ def close(self):
40004000
('html', '-//W3C//DTD XHTML 1.0 Transitional//EN',
40014001
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'))
40024002

4003+
for doctype, expected in [
4004+
('<!DOCTYPE html>', ('html', None, None)),
4005+
('<!DOCTYPE html [<!ENTITY e "v">]>', ('html', None, None)),
4006+
('<!DOCTYPE html SYSTEM "a.dtd">', ('html', None, 'a.dtd')),
4007+
('<!DOCTYPE html SYSTEM "a.dtd" [<!ENTITY e "v">]>',
4008+
('html', None, 'a.dtd')),
4009+
('<!DOCTYPE html PUBLIC "-//P" "a.dtd">', ('html', '-//P', 'a.dtd')),
4010+
("<!DOCTYPE\nhtml\nPUBLIC\n'-//P'\n'a.dtd'\n>",
4011+
('html', '-//P', 'a.dtd')),
4012+
]:
4013+
with self.subTest(doctype=doctype):
4014+
parser = ET.XMLParser(target=DoctypeParser())
4015+
parser.feed(doctype + '<html/>')
4016+
self.assertEqual(parser.close(), expected)
4017+
40034018
def test_builder_lookup_errors(self):
40044019
class RaisingBuilder:
40054020
def __init__(self, raise_in=None, what=ValueError):

Lib/xml/etree/ElementTree.py

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,10 +1568,10 @@ def __init__(self, *, target=None, encoding=None):
15681568
parser.CommentHandler = target.comment
15691569
if hasattr(target, 'pi'):
15701570
parser.ProcessingInstructionHandler = target.pi
1571+
parser.StartDoctypeDeclHandler = self._start_doctype
15711572
# Configure pyexpat: buffering, new-style attribute handling.
15721573
parser.buffer_text = 1
15731574
parser.ordered_attributes = 1
1574-
self._doctype = None
15751575
self.entity = {}
15761576
try:
15771577
self.version = "Expat %d.%d.%d" % expat.version_info
@@ -1690,38 +1690,15 @@ def _default(self, text):
16901690
err.lineno = self.parser.ErrorLineNumber
16911691
err.offset = self.parser.ErrorColumnNumber
16921692
raise err
1693-
elif prefix == "<" and text[:9] == "<!DOCTYPE":
1694-
self._doctype = [] # inside a doctype declaration
1695-
elif self._doctype is not None:
1696-
# parse doctype contents
1697-
if prefix == ">":
1698-
self._doctype = None
1699-
return
1700-
text = text.strip(_XML_WHITESPACE)
1701-
if not text:
1702-
return
1703-
self._doctype.append(text)
1704-
n = len(self._doctype)
1705-
if n > 2:
1706-
type = self._doctype[1]
1707-
if type == "PUBLIC" and n == 4:
1708-
name, type, pubid, system = self._doctype
1709-
if pubid:
1710-
pubid = pubid[1:-1]
1711-
elif type == "SYSTEM" and n == 3:
1712-
name, type, system = self._doctype
1713-
pubid = None
1714-
else:
1715-
return
1716-
if hasattr(self.target, "doctype"):
1717-
self.target.doctype(name, pubid, system[1:-1])
1718-
elif hasattr(self, "doctype"):
1719-
warnings.warn(
1720-
"The doctype() method of XMLParser is ignored. "
1721-
"Define doctype() method on the TreeBuilder target.",
1722-
RuntimeWarning)
1723-
1724-
self._doctype = None
1693+
1694+
def _start_doctype(self, name, system, pubid, has_internal_subset):
1695+
if hasattr(self.target, "doctype"):
1696+
self.target.doctype(name, pubid, system)
1697+
elif hasattr(self, "doctype"):
1698+
warnings.warn(
1699+
"The doctype() method of XMLParser is ignored. "
1700+
"Define doctype() method on the TreeBuilder target.",
1701+
RuntimeWarning)
17251702

17261703
def feed(self, data):
17271704
"""Feed encoded data to parser."""
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix the Python implementation of :class:`xml.etree.ElementTree.XMLParser`:
2+
the ``doctype()`` method of the target is now called for a document type
3+
declaration without an external identifier, like ``<!DOCTYPE html>``,
4+
as in the C implementation.

0 commit comments

Comments
 (0)