Hi everyone, While looking for things to work on in php-src my friend Thomas pointed me to a peculiar special case in ext/dom that leads to massive inconsistency problems in the API.
There is an undocumented class DOMNameSpaceNode that gets returned from DOMElement::getAttributeNode(NS) if you select an attribute that represents a namespace (xmlns). This special case is intentionally handled in the code, contrary to Pythons DOM Extension which doesn't do this and contrary to the DOM Specification, which does not have a special DOMNameSpaceNode. Its all DOMAttr. Problematically DOMNameSpaceNode doesn't extend from DOMAttr, you cannot pass this class to DOMElement::removeAttributeNode(DOMAttr $attr): Fatal error: Uncaught TypeError: Argument 1 passed to DOMElement::removeAttributeNode() must be an instance of DOMAttr, instance of DOMNameSpaceNode given Code example here: https://3v4l.org/jkC5s In addition the DOMNameSpaceNode renames all properties compared to DOMAttr, clearly violating the interface documented here http://php.net/manual/de/domelement.getattributenode.php Two potential fixes come to mind: 1. Have DOMNameSpaceNode extend DOMAttr - maybe this was the originally intended behavior, becuase the properties are all named differently? 2. Have DOMElement::removeAttributeNode accept also a DOMNameSpaceNode (3.) Remove the non standard DOMNameSpaceNode class and use a DOMAttr instead I think approach #1 is the right one from a BC perspective and also fixing the DOM API to be more consistent with the standard. But I am also not opposed to #3 in the longer term, looking at Github DOMNamespaceNode in the open source world is only used for one apc test, in PHP Compat and when dumping it in Symfony Var Dumper. I imagine its more deeply used in closed source code working deeply with XML. The second problem that this inconsistency creates is DOMElement::removeAttributeNS($namespaceUri, $localName). When you want to use it to remove a namespace attribute (xmlns). By default the xmlns namespace has the uri http://www.w3.org/2000/xmlns/. Hence removing xmlns:$name namespace would expected to be: DOMElement::removeAttributeNS("http://www.w3.org/2000/xmlns/", "foo") // removes xmlns:foo But thats not how it works, there is special code implemented that requires you to pick the URI from xmlns:foo value: <root xmlns:foo="urn:foo" /> DOMElement::removeAttributeNS("urn:foo", "foo"); But if your node has an attribute in this namespace with the same name, it gets removed as well: <root xmlns:foo="urn:foo" foo:foo="bar" /> Would incorrectly become this, removing 2 attributes: <root /> This is a bug that cannot be fixed in a BC way. I have no clue how to fix this completly broken behavior in a good way. I propose to break BC here and requiring "http://www.w3.org/2000/xmlns/" as namespaceURI from PHP 8.0 to delete a namespace (xmlns) attribute. Should I put both issues into an RFC or are these rather bugs that can be fixed without an RFC? greetings Benjamin