Skip to content

Commit 86a8497

Browse files
authored
Merge pull request #86 from veewee/allow-empty-docs-on-configurators
Allow empty docs inside configurators like pretty_print
2 parents 9a1e9c9 + f207f89 commit 86a8497

10 files changed

Lines changed: 172 additions & 17 deletions

File tree

docs/dom.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,18 @@ $document = Document::fromLoader($loader, ...$configurators);
647647

648648
## Loaders
649649

650+
#### xml_document_loader
651+
652+
Loads an XML document from an external `Dom\XMLDocument`.
653+
It copies the content of the external document into a new `Dom\XMLDocument` and re-applies e.g. LIBXML flags.
654+
655+
```php
656+
use VeeWee\Xml\Dom\Document;
657+
use VeeWee\Xml\Dom\Loader\xml_document_loader;
658+
659+
$doc = Document::fromLoader(xml_document_loader($originalDocument, options: LIBXML_NOCDATA, override_encoding: 'UTF-8'));
660+
```
661+
650662
#### xml_file_loader
651663

652664
Loads an XML document from a file.

src/Xml/Dom/Configurator/canonicalize.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@
1515
*/
1616
function canonicalize(): Closure
1717
{
18-
return static fn (XMLDocument $document): XMLDocument
19-
=> Document::fromLoader(
18+
return static function (XMLDocument $document): XMLDocument {
19+
if (!$document->documentElement) {
20+
return $document;
21+
}
22+
23+
return Document::fromLoader(
2024
xml_string_loader(
2125
non_empty_string()->assert($document->C14N()),
2226
LIBXML_NSCLEAN + LIBXML_NOCDATA
2327
),
2428
pretty_print(),
25-
normalize()
29+
normalize(),
2630
)->toUnsafeDocument();
31+
};
2732
}

src/Xml/Dom/Configurator/pretty_print.php

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,20 @@
77
use Closure;
88
use Dom\XMLDocument;
99
use VeeWee\Xml\Dom\Document;
10-
use function VeeWee\Xml\Dom\Loader\xml_string_loader;
10+
use function VeeWee\Xml\Dom\Loader\xml_document_loader;
1111

1212
/**
1313
* @return Closure(XMLDocument): XMLDocument
1414
*/
1515
function pretty_print(): Closure
1616
{
1717
return static function (XMLDocument $document): XMLDocument {
18-
$trimmed = Document::fromLoader(
19-
xml_string_loader(
20-
Document::fromUnsafeDocument($document)->toXmlString(),
21-
LIBXML_NOBLANKS
22-
)
18+
$prettyPrinted = Document::fromLoader(
19+
xml_document_loader($document, LIBXML_NOBLANKS)
2320
)->toUnsafeDocument();
2421

25-
$trimmed->formatOutput = true;
22+
$prettyPrinted->formatOutput = true;
2623

27-
return $trimmed;
24+
return $prettyPrinted;
2825
};
2926
}

src/Xml/Dom/Configurator/trim_spaces.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Closure;
88
use Dom\XMLDocument;
99
use VeeWee\Xml\Dom\Document;
10-
use function VeeWee\Xml\Dom\Loader\xml_string_loader;
10+
use function VeeWee\Xml\Dom\Loader\xml_document_loader;
1111

1212
/**
1313
* @return Closure(XMLDocument): XMLDocument
@@ -16,10 +16,7 @@ function trim_spaces(): Closure
1616
{
1717
return static function (XMLDocument $document): XMLDocument {
1818
$trimmed = Document::fromLoader(
19-
xml_string_loader(
20-
Document::fromUnsafeDocument($document)->toXmlString(),
21-
LIBXML_NOBLANKS
22-
)
19+
xml_document_loader($document, LIBXML_NOBLANKS)
2320
)->toUnsafeDocument();
2421

2522
$trimmed->formatOutput = false;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace VeeWee\Xml\Dom\Loader;
6+
7+
use Closure;
8+
use Dom\XMLDocument;
9+
use function Psl\Type\non_empty_string;
10+
use function VeeWee\Xml\ErrorHandling\disallow_issues;
11+
12+
/**
13+
* Loads a copy of current document.
14+
*
15+
* @param int $options - bitmask of LIBXML_* constants https://www.php.net/manual/en/libxml.constants.php
16+
* @return Closure(): XMLDocument
17+
*/
18+
function xml_document_loader(
19+
XMLDocument $importedDocument,
20+
int $options = 0,
21+
?string $override_encoding = null
22+
): Closure {
23+
return static fn () => disallow_issues(static function () use ($importedDocument, $options, $override_encoding): XMLDocument {
24+
25+
if ($importedDocument->documentElement === null) {
26+
return XMLDocument::createEmpty($importedDocument->xmlVersion, $importedDocument->xmlEncoding);
27+
}
28+
29+
return XMLDocument::createFromString(
30+
non_empty_string()->assert($importedDocument->saveXml()),
31+
$options,
32+
$override_encoding
33+
);
34+
});
35+
}

src/bootstrap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
'Xml\Dom\Configurator\trim_spaces' => __DIR__.'/Xml/Dom/Configurator/trim_spaces.php',
3333
'Xml\Dom\Configurator\utf8' => __DIR__.'/Xml/Dom/Configurator/utf8.php',
3434
'Xml\Dom\Configurator\validator' => __DIR__.'/Xml/Dom/Configurator/validator.php',
35+
'Xml\Dom\Loader\xml_document_loader' => __DIR__.'/Xml/Dom/Loader/xml_document_loader.php',
3536
'Xml\Dom\Loader\xml_file_loader' => __DIR__.'/Xml/Dom/Loader/xml_file_loader.php',
3637
'Xml\Dom\Loader\xml_node_loader' => __DIR__.'/Xml/Dom/Loader/xml_node_loader.php',
3738
'Xml\Dom\Loader\xml_string_loader' => __DIR__.'/Xml/Dom/Loader/xml_string_loader.php',

tests/Xml/Dom/Configurator/CanonicalizeTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ public function test_it_can_canonicalize(string $input, string $expected): void
2323
static::assertSame($expected, $actual);
2424
}
2525

26+
public function test_it_can_canonicalize_empty_xml(): void
27+
{
28+
$configurator = canonicalize();
29+
30+
$doc = Document::empty()->toUnsafeDocument();
31+
$result = $configurator($doc);
32+
33+
static::assertSame($doc, $result);
34+
}
35+
2636
public static function provideXmls()
2737
{
2838
yield 'no-action' => [

tests/Xml/Dom/Configurator/PrettyPrintTest.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
final class PrettyPrintTest extends TestCase
1313
{
14-
public function test_it_can_trim_contents(): void
14+
public function test_it_can_pretty_print_contents(): void
1515
{
1616
$configurator = pretty_print();
1717

@@ -28,4 +28,27 @@ public function test_it_can_trim_contents(): void
2828
static::assertTrue($result->formatOutput);
2929
static::assertSame($expected, xml_string()($result->documentElement));
3030
}
31+
32+
public function test_it_can_pretty_print_empty_xml(): void
33+
{
34+
$configurator = pretty_print();
35+
36+
$doc = Document::empty()->toUnsafeDocument();
37+
$result = $configurator($doc);
38+
39+
$result->append(
40+
$hello = $result->createElement('hello')
41+
);
42+
$hello->append($result->createElement('world'));
43+
44+
$expected = <<<EOXML
45+
<hello>
46+
<world/>
47+
</hello>
48+
EOXML;
49+
50+
static::assertNotSame($doc, $result);
51+
static::assertTrue($result->formatOutput);
52+
static::assertSame($expected, xml_string()($result->documentElement));
53+
}
3154
}

tests/Xml/Dom/Configurator/TrimSpacesTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,25 @@ public function test_it_can_trim_contents(): void
2121
static::assertFalse($result->formatOutput);
2222
static::assertSame('<hello><world/></hello>', xml_string()($result->documentElement));
2323
}
24+
25+
public function test_it_can_trim_spaces_on_empty_xml(): void
26+
{
27+
$configurator = trim_spaces();
28+
29+
$doc = Document::empty()->toUnsafeDocument();
30+
$result = $configurator($doc);
31+
32+
$result->append(
33+
$hello = $result->createElement('hello')
34+
);
35+
$hello->append($result->createElement('world'));
36+
37+
$expected = <<<EOXML
38+
<hello><world/></hello>
39+
EOXML;
40+
41+
static::assertNotSame($doc, $result);
42+
static::assertFalse($result->formatOutput);
43+
static::assertSame($expected, xml_string()($result->documentElement));
44+
}
2445
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace VeeWee\Tests\Xml\Dom\Loader;
6+
7+
use Dom\XMLDocument;
8+
use PHPUnit\Framework\TestCase;
9+
use function VeeWee\Xml\Dom\Loader\xml_document_loader;
10+
11+
final class XmlDocumentLoaderTest extends TestCase
12+
{
13+
public function test_it_can_load_xml_string(): void
14+
{
15+
$initialDoc = XMLDocument::createFromString('<hello />');
16+
$loader = xml_document_loader($initialDoc);
17+
$doc = $loader();
18+
19+
static::assertXmlStringEqualsXmlString($initialDoc->saveXml(), $doc->saveXML());
20+
}
21+
22+
public function test_it_can_load_xml_string_with_different_charset(): void
23+
{
24+
$initialDoc = XMLDocument::createFromString('<hello>héllo</hello>');
25+
$loader = xml_document_loader($initialDoc, override_encoding: 'Windows-1252');
26+
$doc = $loader();
27+
28+
static::assertNotSame($initialDoc, $doc);
29+
static::assertSame('héllo', $doc->documentElement->textContent);
30+
static::assertSame('Windows-1252', $doc->xmlEncoding);
31+
}
32+
33+
public function test_it_can_load_with_options(): void
34+
{
35+
$initialDoc = XMLDocument::createFromString('<hello><![CDATA[HELLO]]></hello>');
36+
$loader = xml_document_loader($initialDoc, options: LIBXML_NOCDATA);
37+
$doc = $loader();
38+
39+
static::assertNotSame($initialDoc, $doc);
40+
static::assertSame('<hello>HELLO</hello>', $doc->saveXML($doc->documentElement));
41+
}
42+
43+
public function test_it_can_load_empty_xml_string(): void
44+
{
45+
$initialDoc = XMLDocument::createEmpty(version: '1.1', encoding: 'ASCII');
46+
$loader = xml_document_loader($initialDoc);
47+
$doc = $loader();
48+
49+
static::assertSame($initialDoc->saveXml(), $doc->saveXML());
50+
static::assertSame('ASCII', $doc->xmlEncoding);
51+
static::assertSame('1.1', $doc->xmlVersion);
52+
}
53+
54+
}

0 commit comments

Comments
 (0)