[php-src] Issue #21544: Dom\XMLDocument::C14N() drops namespace declarations on DOM-built documents

[email protected] (veewee)
Newsgroups php.bugs
Message-ID <[email protected]>
Issue: https://github.com/php/php-src/issues/21544
Author: veewee

### Description

I ran into a C14N issue with Dom\XMLDocument while upgrading php-soap/xml to veewee/xml v4.

When a document is built via the DOM API (createElementNS + appendChild), non-exclusive C14N() strips all namespace declarations while keeping the prefixed element names, producing invalid XML.

Reproducer: https://3v4l.org/PGDSl#v8.5.3

```php
<?php
echo "PHP " . PHP_VERSION . PHP_EOL . PHP_EOL;

// 1. DOM-built document: C14N drops namespace declarations
$doc = Dom\XMLDocument::createEmpty();
$root = $doc->createElementNS("urn:envelope", "env:Root");
$doc->appendChild($root);
$child = $doc->createElementNS("urn:child", "x:Child");
$root->appendChild($child);

echo "DOM-built Dom\XMLDocument" . PHP_EOL;
echo "  saveXML: " . trim($doc->saveXML()) . PHP_EOL;
echo "  C14N:    " . $doc->C14N() . PHP_EOL;
// Expected: <env:Root xmlns:env="urn:envelope"><x:Child xmlns:x="urn:child"></x:Child></env:Root>
// Actual:   <env:Root><x:Child></x:Child></env:Root>
//           ^ namespace declarations are missing, this is not valid XML

echo PHP_EOL;

// 2. Same structure parsed from string: C14N works correctly
$doc2 = Dom\XMLDocument::createFromString(
  '<env:Root xmlns:env="urn:envelope"><x:Child xmlns:x="urn:child"/></env:Root>'
);
echo "Parsed Dom\XMLDocument" . PHP_EOL;
echo "  C14N:    " . $doc2->C14N() . PHP_EOL;
// Correct: <env:Root xmlns:env="urn:envelope"><x:Child xmlns:x="urn:child"></x:Child></env:Root>

echo PHP_EOL;

// 3. Legacy DOMDocument DOM-built: C14N works correctly
$doc3 = new DOMDocument();
$root3 = $doc3->createElementNS("urn:envelope", "env:Root");
$doc3->appendChild($root3);
$child3 = $doc3->createElementNS("urn:child", "x:Child");
$root3->appendChild($child3);
echo "DOM-built DOMDocument (legacy)" . PHP_EOL;
echo "  C14N:    " . $doc3->C14N() . PHP_EOL;
// Correct: <env:Root xmlns:env="urn:envelope"><x:Child xmlns:x="urn:child"></x:Child></env:Root>

echo PHP_EOL;

// 4. Exclusive C14N on DOM-built document: works correctly
echo "DOM-built Dom\XMLDocument (exclusive C14N)" . PHP_EOL;
echo "  C14N:    " . $doc->C14N(exclusive: true) . PHP_EOL;
// Correct: <env:Root xmlns:env="urn:envelope"><x:Child xmlns:x="urn:child"></x:Child></env:Root>
```

Output:

```
DOM-built Dom\XMLDocument
  saveXML: <?xml version="1.0" encoding="UTF-8"?>
<env:Root xmlns:env="urn:envelope"><x:Child xmlns:x="urn:child"/></env:Root>
  C14N:    <env:Root><x:Child></x:Child></env:Root>

Parsed Dom\XMLDocument
  C14N:    <env:Root xmlns:env="urn:envelope"><x:Child xmlns:x="urn:child"></x:Child></env:Root>

DOM-built DOMDocument (legacy)
  C14N:    <env:Root xmlns:env="urn:envelope"><x:Child xmlns:x="urn:child"></x:Child></env:Root>

DOM-built Dom\XMLDocument (exclusive C14N)
  C14N:    <env:Root xmlns:env="urn:envelope"><x:Child xmlns:x="urn:child"></x:Child></env:Root>
```

As you can see, the first C14N output is invalid XML.

The key observations:
- DOM-built Dom\XMLDocument: C14N() outputs <env:Root><x:Child></x:Child></env:Root> (missing xmlns:env and xmlns:x)
- Same structure parsed via createFromString: works correctly
- Legacy DOMDocument DOM-built: works correctly
- Exclusive C14N(exclusive: true) on DOM-built: also works correctly

So the issue is specific to non-exclusive C14N on programmatically built Dom\XMLDocument documents.

Related:
- https://github.com/php/php-src/issues/20444 (same root cause, closed)
- https://github.com/php/php-src/commit/40c291cf932c31a302fa584bb50b6edb199fb07e (fix for the above, but doesn't cover the DOM-built case)

The issue persists on 8.4.19 and 8.5.3.

Cheers,
Toon


### PHP Version

```plain
Any 8.4 and 8.5
```

### Operating System

any
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.