There were specific reasons for it tho I can't recall all the details
off the top of my head. Part of it related to the underlying structures
of attributes and namespace nodes not being the same and cannot be user
interchangeable in the code, unless only inspected at the nodeptr level.
Trying to manipulate namespace nodes as attributes will cause memory
corruption so they need to be handled differently. I don't remember if
this was the only reason or there was more for the special class but
while I agree with basic DOM usage no one should ever need to be dealing
directly with namespace declarations but once you get into more complex
situation, especially that involve xpath, xslt, canonicalization and
even interoperability this starts coming into play and is quite
important to deal with namespace declarations directly.

Also some of the examples in previous messages are way overly simplistic
so the conclusions are not 100% accurate. i.e. removeAttributeNS. I am
assuming that its just due to overly aggressive namespace reconciliation
happening and removing the declaration since its no longer in use. With
a nested document which uses the namespace in child nodes I would expect
the namespace declaration to remain, tho possible it may be moved to the
first child using it (been a while since I looked at that code).

My recommendation would be to tread lightly here, look at every method
any changes to namespace declaration nodes would touch and make sure
they are all handle properly otherwise you run the risk of introducing
memory corruption issues which is far worse than some inconsistency for
supposedly unused and unneeded functionality ;)

BTW I have recently started looking at the libxml code base again and
considering getting more involved here again, assuming the toxicity
level has gone done from the past. Not sure this is the first thing I
would look at but feel free to shoot over any questions.

Rob

On 3/12/19 1:50 AM, Pierre Joye wrote:
> Hi,
>
> Only adding Rob just in case :)
>
> best,
>
> On Wed, Mar 13, 2019, 5:54 AM Benjamin Eberlei <kont...@beberlei.de
> <mailto:kont...@beberlei.de>> wrote:
>
>     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
>

Reply via email to