Skip to content

DOM: Removing XMLNS namespace node results in invalid default: prefix #12616

Closed
@veewee

Description

@veewee

Description

The following code:

https://3v4l.org/lOrNb

<?php

$doc = new DOMDocument();
$doc->loadXML(
    <<<XML
    <container xmlns="http://symfony.com/schema/dic/services">
      CHILDREN
    </container>
    XML
);

//
// Remove xmlns Attribute + Validate it is actually gone.
// As you can see, it still remembers a 'xmlns' DOMNameSpaceNode with an empty namespaceURI (which basically is invalid!)
// The same happens when you prefix the declaration. For example xmlns:prefixed="...."
//
$doc->documentElement->removeAttributeNS('http://symfony.com/schema/dic/services', '');
var_dump($doc->documentElement->getAttributeNode('xmlns'));
$namespaces = [...(new DOMXPath($doc))->query('./namespace::*', $doc->documentElement)];

//
// Yet when saving the XML : there is no problem, the namespaces are gone.
//
echo $doc->saveXML();
var_dump($namespaces);


//
// However ...
// When importing the node in a new document, it gets prefixed by <default:container ...> without any xmlns:default declaration
//

$new = new DOMDocument();
$new->append(
    $new->importNode($doc->documentElement, true)
);

echo $new->saveXML();

// Resulting in invalid XML obviously:
$previousErrorReporting = libxml_use_internal_errors(true);
libxml_clear_errors();

$parsedAgain = new DOMDocument();
$parsedAgain->loadXML($new->saveXML());
$errors = libxml_get_errors();

libxml_clear_errors();
libxml_use_internal_errors($previousErrorReporting);

var_dump($errors);

Resulted in this output:

object(DOMNameSpaceNode)#3 (8) {
  ["nodeName"]=>
  string(5) "xmlns"
  ["nodeValue"]=>
  NULL
  ["nodeType"]=>
  int(18)
  ["prefix"]=>
  string(0) ""
  ["localName"]=>
  string(5) "xmlns"
  ["namespaceURI"]=>
  NULL
  ["ownerDocument"]=>
  string(22) "(object value omitted)"
  ["parentNode"]=>
  string(22) "(object value omitted)"
}
<?xml version="1.0"?>
<container>
  CHILDREN
</container>
array(2) {
  [0]=>
  object(DOMNameSpaceNode)#4 (8) {
    ["nodeName"]=>
    string(9) "xmlns:xml"
    ["nodeValue"]=>
    string(36) "http://www.w3.org/XML/1998/namespace"
    ["nodeType"]=>
    int(18)
    ["prefix"]=>
    string(3) "xml"
    ["localName"]=>
    string(3) "xml"
    ["namespaceURI"]=>
    string(36) "http://www.w3.org/XML/1998/namespace"
    ["ownerDocument"]=>
    string(22) "(object value omitted)"
    ["parentNode"]=>
    string(22) "(object value omitted)"
  }
  [1]=>
  object(DOMNameSpaceNode)#5 (8) {
    ["nodeName"]=>
    string(5) "xmlns"
    ["nodeValue"]=>
    NULL
    ["nodeType"]=>
    int(18)
    ["prefix"]=>
    string(0) ""
    ["localName"]=>
    string(5) "xmlns"
    ["namespaceURI"]=>
    NULL
    ["ownerDocument"]=>
    string(22) "(object value omitted)"
    ["parentNode"]=>
    string(22) "(object value omitted)"
  }
}
<?xml version="1.0"?>
<default:container>
  CHILDREN
</default:container>
array(1) {
  [0]=>
  object(LibXMLError)#7 (6) {
    ["level"]=>
    int(2)
    ["code"]=>
    int(201)
    ["column"]=>
    int(19)
    ["message"]=>
    string(53) "Namespace prefix default on container is not defined
"
    ["file"]=>
    string(0) ""
    ["line"]=>
    int(2)
  }
}

But I expected this output instead:

<default:container>
  CHILDREN
</default:container>

Should be

<container>
  CHILDREN
<container>

This namespace node should not be there, since it is invalid because there is a NULL namespaceURI:

object(DOMNameSpaceNode)#5 (8) {
    ["nodeName"]=>
    string(5) "xmlns"
    ["nodeValue"]=>
    NULL
    ["nodeType"]=>
    int(18)
    ["prefix"]=>
    string(0) ""
    ["localName"]=>
    string(5) "xmlns"
    ["namespaceURI"]=>
    NULL
    ["ownerDocument"]=>
    string(22) "(object value omitted)"
    ["parentNode"]=>
    string(22) "(object value omitted)"
  }

More context:

PHP Version

PHP >8 >7 >??

Operating System

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions