Skip to content

Commit

Permalink
Allow empty docs inside configurators like pretty_print
Browse files Browse the repository at this point in the history
  • Loading branch information
veewee committed Dec 8, 2024
1 parent 9a1e9c9 commit f207f89
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 17 deletions.
12 changes: 12 additions & 0 deletions docs/dom.md
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,18 @@ $document = Document::fromLoader($loader, ...$configurators);

## Loaders

#### xml_document_loader

Loads an XML document from an external `Dom\XMLDocument`.
It copies the content of the external document into a new `Dom\XMLDocument` and re-applies e.g. LIBXML flags.

```php
use VeeWee\Xml\Dom\Document;
use VeeWee\Xml\Dom\Loader\xml_document_loader;

$doc = Document::fromLoader(xml_document_loader($originalDocument, options: LIBXML_NOCDATA, override_encoding: 'UTF-8'));
```

#### xml_file_loader

Loads an XML document from a file.
Expand Down
11 changes: 8 additions & 3 deletions src/Xml/Dom/Configurator/canonicalize.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@
*/
function canonicalize(): Closure
{
return static fn (XMLDocument $document): XMLDocument
=> Document::fromLoader(
return static function (XMLDocument $document): XMLDocument {
if (!$document->documentElement) {
return $document;
}

return Document::fromLoader(
xml_string_loader(
non_empty_string()->assert($document->C14N()),
LIBXML_NSCLEAN + LIBXML_NOCDATA
),
pretty_print(),
normalize()
normalize(),
)->toUnsafeDocument();
};
}
13 changes: 5 additions & 8 deletions src/Xml/Dom/Configurator/pretty_print.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,20 @@
use Closure;
use Dom\XMLDocument;
use VeeWee\Xml\Dom\Document;
use function VeeWee\Xml\Dom\Loader\xml_string_loader;
use function VeeWee\Xml\Dom\Loader\xml_document_loader;

/**
* @return Closure(XMLDocument): XMLDocument
*/
function pretty_print(): Closure
{
return static function (XMLDocument $document): XMLDocument {
$trimmed = Document::fromLoader(
xml_string_loader(
Document::fromUnsafeDocument($document)->toXmlString(),
LIBXML_NOBLANKS
)
$prettyPrinted = Document::fromLoader(
xml_document_loader($document, LIBXML_NOBLANKS)
)->toUnsafeDocument();

$trimmed->formatOutput = true;
$prettyPrinted->formatOutput = true;

return $trimmed;
return $prettyPrinted;
};
}
7 changes: 2 additions & 5 deletions src/Xml/Dom/Configurator/trim_spaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Closure;
use Dom\XMLDocument;
use VeeWee\Xml\Dom\Document;
use function VeeWee\Xml\Dom\Loader\xml_string_loader;
use function VeeWee\Xml\Dom\Loader\xml_document_loader;

/**
* @return Closure(XMLDocument): XMLDocument
Expand All @@ -16,10 +16,7 @@ function trim_spaces(): Closure
{
return static function (XMLDocument $document): XMLDocument {
$trimmed = Document::fromLoader(
xml_string_loader(
Document::fromUnsafeDocument($document)->toXmlString(),
LIBXML_NOBLANKS
)
xml_document_loader($document, LIBXML_NOBLANKS)
)->toUnsafeDocument();

$trimmed->formatOutput = false;
Expand Down
35 changes: 35 additions & 0 deletions src/Xml/Dom/Loader/xml_document_loader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace VeeWee\Xml\Dom\Loader;

use Closure;
use Dom\XMLDocument;
use function Psl\Type\non_empty_string;
use function VeeWee\Xml\ErrorHandling\disallow_issues;

/**
* Loads a copy of current document.
*
* @param int $options - bitmask of LIBXML_* constants https://www.php.net/manual/en/libxml.constants.php
* @return Closure(): XMLDocument
*/
function xml_document_loader(
XMLDocument $importedDocument,
int $options = 0,
?string $override_encoding = null
): Closure {
return static fn () => disallow_issues(static function () use ($importedDocument, $options, $override_encoding): XMLDocument {

if ($importedDocument->documentElement === null) {
return XMLDocument::createEmpty($importedDocument->xmlVersion, $importedDocument->xmlEncoding);
}

return XMLDocument::createFromString(
non_empty_string()->assert($importedDocument->saveXml()),
$options,
$override_encoding
);
});
}
1 change: 1 addition & 0 deletions src/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
'Xml\Dom\Configurator\trim_spaces' => __DIR__.'/Xml/Dom/Configurator/trim_spaces.php',
'Xml\Dom\Configurator\utf8' => __DIR__.'/Xml/Dom/Configurator/utf8.php',
'Xml\Dom\Configurator\validator' => __DIR__.'/Xml/Dom/Configurator/validator.php',
'Xml\Dom\Loader\xml_document_loader' => __DIR__.'/Xml/Dom/Loader/xml_document_loader.php',
'Xml\Dom\Loader\xml_file_loader' => __DIR__.'/Xml/Dom/Loader/xml_file_loader.php',
'Xml\Dom\Loader\xml_node_loader' => __DIR__.'/Xml/Dom/Loader/xml_node_loader.php',
'Xml\Dom\Loader\xml_string_loader' => __DIR__.'/Xml/Dom/Loader/xml_string_loader.php',
Expand Down
10 changes: 10 additions & 0 deletions tests/Xml/Dom/Configurator/CanonicalizeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ public function test_it_can_canonicalize(string $input, string $expected): void
static::assertSame($expected, $actual);
}

public function test_it_can_canonicalize_empty_xml(): void
{
$configurator = canonicalize();

$doc = Document::empty()->toUnsafeDocument();
$result = $configurator($doc);

static::assertSame($doc, $result);
}

public static function provideXmls()
{
yield 'no-action' => [
Expand Down
25 changes: 24 additions & 1 deletion tests/Xml/Dom/Configurator/PrettyPrintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

final class PrettyPrintTest extends TestCase
{
public function test_it_can_trim_contents(): void
public function test_it_can_pretty_print_contents(): void
{
$configurator = pretty_print();

Expand All @@ -28,4 +28,27 @@ public function test_it_can_trim_contents(): void
static::assertTrue($result->formatOutput);
static::assertSame($expected, xml_string()($result->documentElement));
}

public function test_it_can_pretty_print_empty_xml(): void
{
$configurator = pretty_print();

$doc = Document::empty()->toUnsafeDocument();
$result = $configurator($doc);

$result->append(
$hello = $result->createElement('hello')
);
$hello->append($result->createElement('world'));

$expected = <<<EOXML
<hello>
<world/>
</hello>
EOXML;

static::assertNotSame($doc, $result);
static::assertTrue($result->formatOutput);
static::assertSame($expected, xml_string()($result->documentElement));
}
}
21 changes: 21 additions & 0 deletions tests/Xml/Dom/Configurator/TrimSpacesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,25 @@ public function test_it_can_trim_contents(): void
static::assertFalse($result->formatOutput);
static::assertSame('<hello><world/></hello>', xml_string()($result->documentElement));
}

public function test_it_can_trim_spaces_on_empty_xml(): void
{
$configurator = trim_spaces();

$doc = Document::empty()->toUnsafeDocument();
$result = $configurator($doc);

$result->append(
$hello = $result->createElement('hello')
);
$hello->append($result->createElement('world'));

$expected = <<<EOXML
<hello><world/></hello>
EOXML;

static::assertNotSame($doc, $result);
static::assertFalse($result->formatOutput);
static::assertSame($expected, xml_string()($result->documentElement));
}
}
54 changes: 54 additions & 0 deletions tests/Xml/Dom/Loader/XmlDocumentLoaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace VeeWee\Tests\Xml\Dom\Loader;

use Dom\XMLDocument;
use PHPUnit\Framework\TestCase;
use function VeeWee\Xml\Dom\Loader\xml_document_loader;

final class XmlDocumentLoaderTest extends TestCase
{
public function test_it_can_load_xml_string(): void
{
$initialDoc = XMLDocument::createFromString('<hello />');
$loader = xml_document_loader($initialDoc);
$doc = $loader();

static::assertXmlStringEqualsXmlString($initialDoc->saveXml(), $doc->saveXML());
}

public function test_it_can_load_xml_string_with_different_charset(): void
{
$initialDoc = XMLDocument::createFromString('<hello>héllo</hello>');
$loader = xml_document_loader($initialDoc, override_encoding: 'Windows-1252');
$doc = $loader();

static::assertNotSame($initialDoc, $doc);
static::assertSame('héllo', $doc->documentElement->textContent);
static::assertSame('Windows-1252', $doc->xmlEncoding);
}

public function test_it_can_load_with_options(): void
{
$initialDoc = XMLDocument::createFromString('<hello><![CDATA[HELLO]]></hello>');
$loader = xml_document_loader($initialDoc, options: LIBXML_NOCDATA);
$doc = $loader();

static::assertNotSame($initialDoc, $doc);
static::assertSame('<hello>HELLO</hello>', $doc->saveXML($doc->documentElement));
}

public function test_it_can_load_empty_xml_string(): void
{
$initialDoc = XMLDocument::createEmpty(version: '1.1', encoding: 'ASCII');
$loader = xml_document_loader($initialDoc);
$doc = $loader();

static::assertSame($initialDoc->saveXml(), $doc->saveXML());
static::assertSame('ASCII', $doc->xmlEncoding);
static::assertSame('1.1', $doc->xmlVersion);
}

}

0 comments on commit f207f89

Please sign in to comment.