From a69346521a6eec63fab84fe2a65b4900ae32b5d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Delr=C3=A9?= Date: Mon, 11 May 2026 00:11:21 +0200 Subject: [PATCH] fix: skip DOMDocumentType when importing XML with DOCTYPE declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DOMDocument::importNode() returns false for DOMDocumentType nodes, causing appendChild() to receive a boolean and throw a fatal error. This happens when loading or inserting XML that contains a declaration: the node list from childNodes includes the DOMDocumentType node alongside the root element. Skip DOMDocumentType entries in attachNodes() before attempting the import, so the document content is imported correctly and the DOCTYPE declaration is silently discarded. Fixes #44 Fixes #50 Signed-off-by: Guillaume Delré --- source/FluidXml/FluidInsertionHandler.php | 5 ++++ specs/FluidXml.php | 28 +++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/source/FluidXml/FluidInsertionHandler.php b/source/FluidXml/FluidInsertionHandler.php index f47fd46..1c0e695 100644 --- a/source/FluidXml/FluidInsertionHandler.php +++ b/source/FluidXml/FluidInsertionHandler.php @@ -226,6 +226,11 @@ protected function attachNodes($parent, $nodes, $fn): array $context = []; foreach ($nodes as $el) { + // DOMDocumentType cannot be imported as a child node. + if ($el instanceof \DOMDocumentType) { + continue; + } + $el = $this->dom->importNode($el, true); $context[] = $fn($parent, $el); } diff --git a/specs/FluidXml.php b/specs/FluidXml.php index 6cac1ef..5132f19 100644 --- a/specs/FluidXml.php +++ b/specs/FluidXml.php @@ -142,6 +142,34 @@ assert_is_a($actual, \Exception::class); }); + + it('should import an XML file containing a DOCTYPE declaration', function () { + $file = "{$this->out_dir}.test_load_doctype.xml"; + $doc = "\n" + . "\n" + . ""; + + \file_put_contents($file, $doc); + $xml = FluidXml::load($file); + \unlink($file); + + $expected = "\n \n"; + assert_equal_xml($xml, $expected); + }); + }); + + describe('.addChild() with DOCTYPE', function () { + it('should not throw when adding an XML string with a DOCTYPE declaration', function () { + $xml = new FluidXml(null); + $xmlStr = "\n" + . "\n" + . ""; + + $xml->addChild($xmlStr); + + $expected = "\n \n"; + assert_equal_xml($xml, $expected); + }); }); if (\version_compare(\phpversion(), '7', '>=')) {