Skip to content

DOMDocument::savexml and friends ommit xmlns="" declaration for null namespace, creating incorrect xml representation of the DOM #11404

Closed
@theseer

Description

@theseer

Description

The following code:

<?php declare(strict_types = 1);

$dom1 = new DOMDocument;
$dom1->loadXML('<?xml version="1.0" ?><with xmlns="some:ns" />');

$dom2 = new DOMDocument;
$dom2->loadXML('<?xml version="1.0" ?><none />');

$dom1->documentElement->append(
    $dom1->importNode(
        $dom2->documentElement
    )
);

echo $dom1->saveXML();

Resulted in this output:

<?xml version="1.0"?>
<with xmlns="some:ns"><none/></with>

That is incorrect. The imported node none is in no namespace, the correct serialization to XML thus has to explicitly set the xmlns to "". Otherwise parsing the the generated XML back into a DOM places the node none into the same namespace as its parent with. Adding the following to the above example demonstrates that:

var_dump(
    $dom1->getElementsByTagName('with')->item(0)->namespaceURI,
    $dom1->getElementsByTagName('none')->item(0)->namespaceURI
);

$dom3 = new DOMDocument;
$dom3->loadXML(
    $dom1->saveXML()
);

var_dump(
    $dom3->getElementsByTagName('with')->item(0)->namespaceURI,
    $dom3->getElementsByTagName('none')->item(0)->namespaceURI
);

Output:

string(7) "some:ns"
NULL
string(7) "some:ns"
string(7) "some:ns"

The correct XML serialization of the DOM is:

<?xml version="1.0"?>
<with xmlns="some:ns"><none xmlns="" /></with>

A simple test in JavaScript shows the correct result at least in Firefox:

const parser = new DOMParser;

const dom1 = parser.parseFromString('<?xml version="1.0" ?><with xmlns="some:ns" />', 'text/xml');
const dom2 = parser.parseFromString('<?xml version="1.0" ?><none />', 'text/xml');

dom1.documentElement.appendChild(
        dom1.importNode(
                dom2.documentElement,
                true
        )
);

console.log(
         (new XMLSerializer).serializeToString(dom1)
);
 <?xml version="1.0" encoding="UTF-8"?>
<with xmlns="some:ns"><none xmlns=""/></with>

PHP Version

PHP 8.2.7 / PHP 8.1.20 / PHP 8.0.29 / PHP 7.4.33

Operating System

Fedora Linux 38 x86_64

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions