-
Notifications
You must be signed in to change notification settings - Fork 8k
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