diff --git a/NEWS b/NEWS
index c693d601c8d..13d668b7665 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,9 @@ PHP NEWS
. Fixed bug GH-11997 (ctype_alnum 5 times slower in PHP 8.1 or greater).
(nielsdos)
+- DOM:
+ . Restore old namespace reconciliation behaviour. (nielsdos)
+
- Filter:
. Fix explicit FILTER_REQUIRE_SCALAR with FILTER_CALLBACK (ilutov)
diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c
index bada817e301..468d9345880 100644
--- a/ext/dom/php_dom.c
+++ b/ext/dom/php_dom.c
@@ -1465,11 +1465,16 @@ static void dom_reconcile_ns_internal(xmlDocPtr doc, xmlNodePtr nodep, xmlNodePt
static void dom_libxml_reconcile_ensure_namespaces_are_declared(xmlNodePtr nodep)
{
+ /* Ideally we'd use the DOM-wrapped version, but we cannot: https://github.com/php/php-src/pull/12308. */
+#if 0
/* Put on stack to avoid allocation.
* Although libxml2 currently does not use this for the reconciliation, it still
* makes sense to do this just in case libxml2's internal change in the future. */
xmlDOMWrapCtxt dummy_ctxt = {0};
xmlDOMWrapReconcileNamespaces(&dummy_ctxt, nodep, /* options */ 0);
+#else
+ xmlReconciliateNs(nodep->doc, nodep);
+#endif
}
void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep) /* {{{ */
diff --git a/ext/dom/tests/DOMElement_toggleAttribute.phpt b/ext/dom/tests/DOMElement_toggleAttribute.phpt
index ed29be899da..a5a1ac5dd1e 100644
--- a/ext/dom/tests/DOMElement_toggleAttribute.phpt
+++ b/ext/dom/tests/DOMElement_toggleAttribute.phpt
@@ -123,26 +123,26 @@ bool(true)
Toggling namespaces:
bool(false)
-
+
bool(false)
-
+
bool(true)
-
+
bool(false)
-
+
bool(false)
-
+
Toggling namespaced attributes:
bool(true)
bool(true)
bool(true)
bool(false)
-
+
namespace of test:test = NULL
namespace of foo:test = string(8) "some:ns2"
namespace of doesnotexist:test = NULL
@@ -153,6 +153,6 @@ bool(false)
bool(true)
bool(false)
-
+
Checking toggled namespace:
string(0) ""
diff --git a/ext/dom/tests/bug47530.phpt b/ext/dom/tests/bug47530.phpt
index 0fb990e0e7b..301a418fbe8 100644
--- a/ext/dom/tests/bug47530.phpt
+++ b/ext/dom/tests/bug47530.phpt
@@ -118,18 +118,18 @@ test_appendChild_with_shadowing();
--EXPECT--
-- Test document fragment with import --
-
+
-- Test document fragment without import --
-
+
string(7) "foo:bar"
string(19) "https://php.net/bar"
-- Test document import --
-
-
+
+
+ Test-Text
+
-- Test partial document import --
diff --git a/ext/dom/tests/bug47847.phpt b/ext/dom/tests/bug47847.phpt
index 324bf9508d5..1c9ec95418e 100644
--- a/ext/dom/tests/bug47847.phpt
+++ b/ext/dom/tests/bug47847.phpt
@@ -2,6 +2,8 @@
Bug #47847 (importNode loses the namespace of an XML element)
--EXTENSIONS--
dom
+--XFAIL--
+See https://github.com/php/php-src/pull/12308
--FILE--
-Test
+Test
string(1) "2"
string(7) "some:ns"
diff --git a/ext/dom/tests/specific_namespace_behaviour.phpt b/ext/dom/tests/specific_namespace_behaviour.phpt
new file mode 100644
index 00000000000..e6499e6ba52
--- /dev/null
+++ b/ext/dom/tests/specific_namespace_behaviour.phpt
@@ -0,0 +1,27 @@
+--TEST--
+DOM: specific namespace behaviour for applications with fixed serialization requirements
+--EXTENSIONS--
+dom
+--FILE--
+loadXML(<<
+
+
+
+XML);
+$dom2 = new DOMDocument();
+$dom2->loadXML('');
+$wsse = $dom2->importNode($dom1->documentElement, true);
+$dom2->firstChild->firstChild->appendChild($wsse);
+echo $dom2->saveXML();
+
+?>
+--EXPECT--
+
+
+
+
+
diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
index 8529a0c609c..6b9cd64c299 100644
--- a/ext/libxml/libxml.c
+++ b/ext/libxml/libxml.c
@@ -301,8 +301,13 @@ PHP_LIBXML_API void php_libxml_node_free_list(xmlNodePtr node)
if (curnode->type == XML_ELEMENT_NODE) {
/* This ensures that namespace references in this subtree are defined within this subtree,
* otherwise a use-after-free would be possible when the original namespace holder gets freed. */
+#if 0
xmlDOMWrapCtxt dummy_ctxt = {0};
xmlDOMWrapReconcileNamespaces(&dummy_ctxt, curnode, /* options */ 0);
+#else
+ /* See php_dom.c */
+ xmlReconciliateNs(curnode->doc, curnode);
+#endif
}
/* Skip freeing */
curnode = next;