Restore old namespace reconciliation behaviour

The xmlDOMWrapReconcileNamespaces method we used to fix the namespace
corruption issues in 8.1.21/8.2.8 caused regressions.
Primarily, there is a similar corruption that the xmlReconciliateNs method
used to have in which a namespace is suddenly shifted
(SAML-Toolkits/php-saml#562) and the side-effect of removing redundant
namespaces causes problems when a specific serialization is required.

Closes GH-12308.
This commit is contained in:
Niels Dossche 2023-09-27 22:32:01 +02:00
parent 07811b6390
commit e127f87114
6 changed files with 45 additions and 6 deletions

3
NEWS
View File

@ -13,6 +13,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)

View File

@ -1489,11 +1489,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) /* {{{ */

View File

@ -118,18 +118,18 @@ test_appendChild_with_shadowing();
--EXPECT--
-- Test document fragment with import --
<?xml version="1.0"?>
<html xmlns="https://php.net/something" xmlns:ns="https://php.net/whatever"><element ns:foo="https://php.net/bar"/></html>
<html xmlns="https://php.net/something" xmlns:ns="https://php.net/whatever"><default:element xmlns:default="https://php.net/something" ns:foo="https://php.net/bar"/></html>
-- Test document fragment without import --
<?xml version="1.0"?>
<html xmlns=""><element xmlns:foo="https://php.net/bar"><foo:bar/><bar xmlns=""/></element></html>
<html xmlns=""><element xmlns:foo="https://php.net/bar"><foo:bar/><bar/></element></html>
string(7) "foo:bar"
string(19) "https://php.net/bar"
-- Test document import --
<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<div xmlns="http://www.w3.org/1999/xhtml">
<p>Test-Text</p>
</div>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:default="http://www.w3.org/1999/xhtml">
<default:div xmlns="http://www.w3.org/1999/xhtml">
<default:p>Test-Text</default:p>
</default:div>
</feed>
-- Test partial document import --
<?xml version="1.0"?>

View File

@ -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--
<?php
$fromdom = new DOMDocument();

View File

@ -2,6 +2,8 @@
Bug #55294 (DOMDocument::importNode shifts namespaces when "default" namespace exists)
--EXTENSIONS--
dom
--XFAIL--
See https://github.com/php/php-src/pull/12308
--FILE--
<?php

View File

@ -0,0 +1,27 @@
--TEST--
DOM: specific namespace behaviour for applications with fixed serialization requirements
--EXTENSIONS--
dom
--FILE--
<?php
$dom1 = new DOMDocument();
$dom1->loadXML(<<<XML
<wsse:Security xmlns:wsse="foo:bar">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
</ds:Signature>
</wsse:Security>
XML);
$dom2 = new DOMDocument();
$dom2->loadXML('<xml><child/></xml>');
$wsse = $dom2->importNode($dom1->documentElement, true);
$dom2->firstChild->firstChild->appendChild($wsse);
echo $dom2->saveXML();
?>
--EXPECT--
<?xml version="1.0"?>
<xml><child><wsse:Security xmlns:wsse="foo:bar" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
</ds:Signature>
</wsse:Security></child></xml>