Closed
Description
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