Skip to content

Commit 385f91d

Browse files
committed
Rewrite normalizeDocument
1 parent 51602ab commit 385f91d

1 file changed

Lines changed: 23 additions & 33 deletions

File tree

src/XML/DOMDocumentFactory.php

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -170,53 +170,43 @@ public static function create(string $encoding = 'UTF-8'): Dom\XMLDocument
170170
*/
171171
public static function normalizeDocument(Dom\XMLDocument $doc): Dom\XMLDocument
172172
{
173-
// Get the root element
174173
$root = $doc->documentElement;
175-
if ($root === null) {
174+
if (!$root) {
176175
return $doc;
177176
}
178177

179178
$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-
}
192179

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

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;
188+
// 2. Remove all xmlns* attributes from every element
189+
foreach ($xpath->query('//*') as $element) {
190+
if ($element instanceof \Dom\Element) { // or DOMElement if still mixed
191+
$toRemove = [];
192+
foreach ($element->attributes as $attr) {
193+
if (str_starts_with($attr->nodeName, 'xmlns')) {
194+
$toRemove[] = $attr->nodeName;
195+
}
208196
}
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);
197+
foreach ($toRemove as $name) {
198+
$element->removeAttribute($name);
213199
}
214200
}
215201
}
216202

217-
// Add all collected xmlns attributes to the root element
203+
// 3. Re-attach all collected declarations to the root (correctly)
218204
foreach ($xmlnsAttributes as $name => $value) {
219-
$root->setAttributeNS(C::NS_XMLNS, $name, $value);
205+
$root->setAttributeNS(
206+
'http://www.w3.org/2000/xmlns/',
207+
$name,
208+
$value
209+
);
220210
}
221211

222212
return $doc;

0 commit comments

Comments
 (0)