Skip to content

Commit 1292a27

Browse files
committed
gh-156667: Add DOM Level 3 names to minidom
1 parent 03503dc commit 1292a27

3 files changed

Lines changed: 135 additions & 8 deletions

File tree

Lib/test/test_minidom.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,59 @@ def checkWholeText(self, node, s):
5959
t = node.wholeText
6060
self.assertEqual(t, s, "looking for %r, found %r" % (s, t))
6161

62+
def testDOMLevel3GetFeature(self):
63+
impl = getDOMImplementation()
64+
doc = impl.createDocument(None, "doc", None)
65+
node = doc.documentElement
66+
67+
self.assertIs(impl.getFeature("Core", "2.0"), impl)
68+
self.assertIs(node.getFeature("Core", "2.0"), node)
69+
self.assertIsNone(impl.getFeature("Core", "3.0"))
70+
self.assertIsNone(node.getFeature("Core", "3.0"))
71+
72+
# The names from the working draft are kept for compatibility.
73+
self.assertIs(impl.getInterface("Core"), impl)
74+
self.assertIs(node.getInterface("Core"), node)
75+
76+
def testDOMLevel3AttributeNames(self):
77+
doc = Document()
78+
pairs = (
79+
("actualEncoding", "inputEncoding", "us-ascii", "utf-8"),
80+
("encoding", "xmlEncoding", "utf-8", "utf-16"),
81+
("standalone", "xmlStandalone", False, True),
82+
("version", "xmlVersion", "1.0", "1.1"),
83+
)
84+
for old_name, new_name, old_value, new_value in pairs:
85+
with self.subTest(node="Document", name=new_name):
86+
setattr(doc, old_name, old_value)
87+
self.assertEqual(getattr(doc, new_name), old_value)
88+
setattr(doc, new_name, new_value)
89+
self.assertEqual(getattr(doc, old_name), new_value)
90+
91+
entity = xml.dom.minidom.Entity("entity", None, None, None)
92+
pairs = (
93+
("actualEncoding", "inputEncoding", "us-ascii", "utf-8"),
94+
("encoding", "xmlEncoding", "utf-8", "utf-16"),
95+
("version", "xmlVersion", "1.0", "1.1"),
96+
)
97+
for old_name, new_name, old_value, new_value in pairs:
98+
with self.subTest(node="Entity", name=new_name):
99+
setattr(entity, old_name, old_value)
100+
self.assertEqual(getattr(entity, new_name), old_value)
101+
setattr(entity, new_name, new_value)
102+
self.assertEqual(getattr(entity, old_name), new_value)
103+
104+
doc = parseString(
105+
"<!DOCTYPE doc ["
106+
"<!ELEMENT doc (child)>"
107+
"<!ELEMENT child EMPTY>"
108+
"]><doc> <child/></doc>"
109+
)
110+
text = doc.documentElement.firstChild
111+
self.assertTrue(text.isElementContentWhitespace)
112+
self.assertEqual(text.isElementContentWhitespace,
113+
text.isWhitespaceInElementContent)
114+
62115
def testDocumentAsyncAttr(self):
63116
doc = Document()
64117
self.assertFalse(doc.async_)
@@ -1555,12 +1608,14 @@ def testSchemaType(self):
15551608
# DTD-based namespace is right. The names can vary by loader
15561609
# since each supports a different level of DTD information.
15571610
t = elem.schemaType
1611+
self.assertIs(elem.schemaTypeInfo, t)
15581612
self.confirm(t.name is None
15591613
and t.namespace == xml.dom.EMPTY_NAMESPACE)
15601614
names = "id notid text enum ref refs ent ents nm nms".split()
15611615
for name in names:
15621616
a = elem.getAttributeNode(name)
15631617
t = a.schemaType
1618+
self.assertEqual(a.schemaTypeInfo, t)
15641619
self.confirm(hasattr(t, "name")
15651620
and t.namespace == xml.dom.EMPTY_NAMESPACE)
15661621

Lib/xml/dom/minidom.py

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -227,17 +227,20 @@ def _get_localName(self):
227227
# Overridden in Element and Attr where localName can be Non-Null
228228
return None
229229

230-
# Node interfaces from Level 3 (WD 9 April 2002)
230+
# Node interfaces from DOM Level 3
231231

232232
def isSameNode(self, other):
233233
return self is other
234234

235-
def getInterface(self, feature):
236-
if self.isSupported(feature, None):
235+
def getFeature(self, feature, version):
236+
if self.isSupported(feature, version):
237237
return self
238238
else:
239239
return None
240240

241+
def getInterface(self, feature):
242+
return self.getFeature(feature, None)
243+
241244
# The "user data" functions use a dictionary that is only present
242245
# if some user data has been set, so be careful not to assume it
243246
# exists.
@@ -504,9 +507,12 @@ def _get_schemaType(self):
504507
else:
505508
return info.getAttributeType(self.nodeName)
506509

510+
_get_schemaTypeInfo = _get_schemaType
511+
507512
defproperty(Attr, "isId", doc="True if this attribute is an ID.")
508513
defproperty(Attr, "localName", doc="Namespace-local name of this attribute.")
509514
defproperty(Attr, "schemaType", doc="Schema type for this attribute.")
515+
defproperty(Attr, "schemaTypeInfo", doc="Schema type for this attribute.")
510516

511517

512518
class NamedNodeMap(object):
@@ -712,7 +718,7 @@ class Element(Node):
712718
'nextSibling', 'previousSibling')
713719
nodeType = Node.ELEMENT_NODE
714720
nodeValue = None
715-
schemaType = _no_type
721+
schemaType = schemaTypeInfo = _no_type
716722

717723
_magic_id_nodes = 0
718724

@@ -1220,9 +1226,14 @@ def _get_isWhitespaceInElementContent(self):
12201226
else:
12211227
return info.isElementContent()
12221228

1229+
_get_isElementContentWhitespace = _get_isWhitespaceInElementContent
1230+
12231231
defproperty(Text, "isWhitespaceInElementContent",
12241232
doc="True iff this text node contains only whitespace"
12251233
" and is in element content.")
1234+
defproperty(Text, "isElementContentWhitespace",
1235+
doc="True iff this text node contains only whitespace"
1236+
" and is in element content.")
12261237
defproperty(Text, "wholeText",
12271238
doc="The text of all logically-adjacent text nodes.")
12281239

@@ -1429,12 +1440,36 @@ def __init__(self, name, publicId, systemId, notation):
14291440
def _get_actualEncoding(self):
14301441
return self.actualEncoding
14311442

1443+
def _get_inputEncoding(self):
1444+
return self.actualEncoding
1445+
1446+
def _set_inputEncoding(self, value):
1447+
self.actualEncoding = value
1448+
1449+
inputEncoding = property(_get_inputEncoding, _set_inputEncoding)
1450+
14321451
def _get_encoding(self):
14331452
return self.encoding
14341453

1454+
def _get_xmlEncoding(self):
1455+
return self.encoding
1456+
1457+
def _set_xmlEncoding(self, value):
1458+
self.encoding = value
1459+
1460+
xmlEncoding = property(_get_xmlEncoding, _set_xmlEncoding)
1461+
14351462
def _get_version(self):
14361463
return self.version
14371464

1465+
def _get_xmlVersion(self):
1466+
return self.version
1467+
1468+
def _set_xmlVersion(self, value):
1469+
self.version = value
1470+
1471+
xmlVersion = property(_get_xmlVersion, _set_xmlVersion)
1472+
14381473
def appendChild(self, newChild):
14391474
raise xml.dom.HierarchyRequestErr(
14401475
"cannot append children to an entity node")
@@ -1567,14 +1602,17 @@ def createDocumentType(self, qualifiedName, publicId, systemId):
15671602
doctype.systemId = systemId
15681603
return doctype
15691604

1570-
# DOM Level 3 (WD 9 April 2002)
1605+
# DOM Level 3
15711606

1572-
def getInterface(self, feature):
1573-
if self.hasFeature(feature, None):
1607+
def getFeature(self, feature, version):
1608+
if self.hasFeature(feature, version):
15741609
return self
15751610
else:
15761611
return None
15771612

1613+
def getInterface(self, feature):
1614+
return self.getFeature(feature, None)
1615+
15781616
# internal
15791617
def _create_document(self):
15801618
return Document()
@@ -1644,7 +1682,7 @@ class Document(Node, DocumentLS):
16441682
previousSibling = nextSibling = None
16451683

16461684

1647-
# Document attributes from Level 3 (WD 9 April 2002)
1685+
# Document attributes from DOM Level 3
16481686

16491687
actualEncoding = None
16501688
encoding = None
@@ -1675,6 +1713,14 @@ def _get_elem_info(self, element):
16751713
def _get_actualEncoding(self):
16761714
return self.actualEncoding
16771715

1716+
def _get_inputEncoding(self):
1717+
return self.actualEncoding
1718+
1719+
def _set_inputEncoding(self, value):
1720+
self.actualEncoding = value
1721+
1722+
inputEncoding = property(_get_inputEncoding, _set_inputEncoding)
1723+
16781724
def _get_doctype(self):
16791725
return self.doctype
16801726

@@ -1684,18 +1730,42 @@ def _get_documentURI(self):
16841730
def _get_encoding(self):
16851731
return self.encoding
16861732

1733+
def _get_xmlEncoding(self):
1734+
return self.encoding
1735+
1736+
def _set_xmlEncoding(self, value):
1737+
self.encoding = value
1738+
1739+
xmlEncoding = property(_get_xmlEncoding, _set_xmlEncoding)
1740+
16871741
def _get_errorHandler(self):
16881742
return self.errorHandler
16891743

16901744
def _get_standalone(self):
16911745
return self.standalone
16921746

1747+
def _get_xmlStandalone(self):
1748+
return self.standalone
1749+
1750+
def _set_xmlStandalone(self, value):
1751+
self.standalone = value
1752+
1753+
xmlStandalone = property(_get_xmlStandalone, _set_xmlStandalone)
1754+
16931755
def _get_strictErrorChecking(self):
16941756
return self.strictErrorChecking
16951757

16961758
def _get_version(self):
16971759
return self.version
16981760

1761+
def _get_xmlVersion(self):
1762+
return self.version
1763+
1764+
def _set_xmlVersion(self, value):
1765+
self.version = value
1766+
1767+
xmlVersion = property(_get_xmlVersion, _set_xmlVersion)
1768+
16991769
def _check_new_child(self, newChild, oldChild=None):
17001770
Node._check_new_child(self, newChild, oldChild)
17011771
# A document can have only one element and only one document type.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add the DOM Level 3 Recommendation names for methods and attributes in
2+
:mod:`xml.dom.minidom`. Keep the names from earlier working drafts as aliases.

0 commit comments

Comments
 (0)