Skip to content

Commit e165d7a

Browse files
committed
Rewrite normalizeDocument
1 parent 51602ab commit e165d7a

1 file changed

Lines changed: 18 additions & 33 deletions

File tree

src/XML/DOMDocumentFactory.php

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use function restore_error_handler;
1717
use function set_error_handler;
1818
use function sprintf;
19-
use function strpos;
2019

2120
/**
2221
* @package simplesamlphp/xml-common
@@ -170,51 +169,37 @@ public static function create(string $encoding = 'UTF-8'): Dom\XMLDocument
170169
*/
171170
public static function normalizeDocument(Dom\XMLDocument $doc): Dom\XMLDocument
172171
{
173-
// Get the root element
174172
$root = $doc->documentElement;
175-
if ($root === null) {
173+
if (!$root) {
176174
return $doc;
177175
}
178176

179177
$xpath = XPath::getXPath($doc);
180-
$xmlnsAttributes = [];
181-
182-
// Collect namespace declarations needed for prefixed elements in the document
183-
foreach ($xpath->query('//*[namespace::*]') as $node) {
184-
if ($node instanceof Dom\Element) {
185-
$name = 'xmlns:' . $node->prefix;
186-
// Both prefix and namespaceURI NULL equals the default xmlns:xml namespace
187-
if ($node->prefix !== null && $node->namespaceURI !== null) {
188-
$xmlnsAttributes[$name] = $node->namespaceURI;
189-
}
190-
}
191-
}
192178

193-
// If no xmlns attributes found, return early with debug info
194-
if (empty($xmlnsAttributes)) {
195-
return $doc;
179+
// 1. Collect all xmlns* attributes from the entire document
180+
$xmlnsAttributes = [];
181+
foreach ($xpath->query('//@*[starts-with(name(), "xmlns")]') as $attr) {
182+
$name = $attr->nodeName; // e.g. "xmlns:ssp" or "xmlns"
183+
$value = $attr->nodeValue; // the namespace URI
184+
$xmlnsAttributes[$name] = $value;
196185
}
197186

198-
// Remove xmlns attributes from all elements (proper XMLNS namespace removal)
199-
foreach ($xpath->query('//*[namespace::*]') as $node) {
200-
if (!$node instanceof Dom\Element) {
201-
continue;
202-
}
203-
204-
foreach ($node->attributes as $attr) {
205-
if ($attr->namespaceURI === C::NS_XMLNS) {
206-
$node->removeAttributeNS(C::NS_XMLNS, $attr->localName);
207-
continue;
187+
// 2. Remove all xmlns* attributes from every element
188+
foreach ($xpath->query('//*') as $element) {
189+
if ($element instanceof \Dom\Element) { // or DOMElement if still mixed
190+
$toRemove = [];
191+
foreach ($element->attributes as $attr) {
192+
if (str_starts_with($attr->nodeName, 'xmlns')) {
193+
$toRemove[] = $attr->nodeName;
194+
}
208195
}
209-
210-
if (strpos($attr->nodeName, 'xmlns') === 0 || $attr->nodeName === 'xmlns') {
211-
// Fallback for implementations that still expose xmlns attrs without namespaceURI
212-
$node->removeAttribute($attr->nodeName);
196+
foreach ($toRemove as $name) {
197+
$element->removeAttribute($name);
213198
}
214199
}
215200
}
216201

217-
// Add all collected xmlns attributes to the root element
202+
// 3. Re-attach all collected declarations to the root (correctly)
218203
foreach ($xmlnsAttributes as $name => $value) {
219204
$root->setAttributeNS(C::NS_XMLNS, $name, $value);
220205
}

0 commit comments

Comments
 (0)