Skip to content

Commit

Permalink
New namspaces system
Browse files Browse the repository at this point in the history
  • Loading branch information
veewee committed Feb 24, 2024
1 parent 74328c7 commit c5c3c5b
Show file tree
Hide file tree
Showing 19 changed files with 79 additions and 68 deletions.
16 changes: 11 additions & 5 deletions src/Xml/Dom/Configurator/pretty_print.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@
namespace VeeWee\Xml\Dom\Configurator;

use Closure;
use \DOM\XMLDocument;
use VeeWee\Xml\Dom\Document;
use function VeeWee\Xml\Dom\Loader\xml_string_loader;

/**
* @return Closure(\DOM\XMLDocument): \DOM\XMLDocument
*/
function pretty_print(): Closure
{
return static function (\DOM\XMLDocument $document): \DOM\XMLDocument {
// TODO : not fully implemented yet in the new API
//$document->preserveWhiteSpace = false;
$document->formatOutput = true;
$trimmed = Document::fromLoader(
xml_string_loader(
Document::fromUnsafeDocument($document)->toXmlString(),
LIBXML_NOBLANKS
)
)->toUnsafeDocument();

return $document;
$trimmed->formatOutput = true;

return $trimmed;
};
}
15 changes: 11 additions & 4 deletions src/Xml/Dom/Configurator/trim_spaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,24 @@

use Closure;
use \DOM\XMLDocument;
use VeeWee\Xml\Dom\Document;
use function VeeWee\Xml\Dom\Loader\xml_string_loader;

/**
* @return Closure(\DOM\XMLDocument): \DOM\XMLDocument
*/
function trim_spaces(): Closure
{
return static function (\DOM\XMLDocument $document): \DOM\XMLDocument {
// TODO : not fully implemented yet in the new API
//$document->preserveWhiteSpace = false;
$document->formatOutput = false;
$trimmed = Document::fromLoader(
xml_string_loader(
Document::fromUnsafeDocument($document)->toXmlString(),
LIBXML_NOBLANKS
)
)->toUnsafeDocument();

return $document;
$trimmed->formatOutput = false;

return $trimmed;
};
}
15 changes: 4 additions & 11 deletions src/Xml/Dom/Locator/Attribute/xmlns_attributes_list.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,16 @@

namespace VeeWee\Xml\Dom\Locator\Attribute;

use \DOM\NameSpaceNode;
use \DOM\Node;
use VeeWee\Xml\Dom\Collection\NodeList;
use VeeWee\Xml\Exception\RuntimeException;
use function VeeWee\Xml\Dom\Locator\Xmlns\linked_namespaces;
use function VeeWee\Xml\Dom\Predicate\is_element;
use function VeeWee\Xml\Dom\Predicate\is_xmlns_attribute;

/**
* @return NodeList<\DOM\NameSpaceNode>
* @return NodeList<\DOM\Attr>
* @throws RuntimeException
*/
function xmlns_attributes_list(\DOM\Node $node): NodeList
{
if (! is_element($node)) {
return NodeList::empty();
}

return linked_namespaces($node)
->filter(static fn (\DOM\NameSpaceNode $namespace): bool => $node->hasAttribute($namespace->nodeName));
return attributes_list($node)
->filter(static fn (\DOM\Attr $attribute): bool => is_xmlns_attribute($attribute));
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,16 @@

namespace VeeWee\Xml\Dom\Manipulator\Element;

use \DOM\Element;
use \DOM\NameSpaceNode;
use VeeWee\Xml\Exception\RuntimeException;
use function VeeWee\Xml\Dom\Builder\xmlns_attribute;
use function VeeWee\Xml\Dom\Locator\Xmlns\linked_namespaces;
use function VeeWee\Xml\Dom\Locator\Attribute\xmlns_attributes_list;

/**
* @throws RuntimeException
*/
function copy_named_xmlns_attributes(\DOM\Element $target, \DOM\Element $source): void
{
linked_namespaces($source)->forEach(static function (\DOM\NameSpaceNode $xmlns) use ($target) {
xmlns_attributes_list($source)->forEach(static function (\DOM\Attr $xmlns) use ($target) {
if ($xmlns->prefix && !$target->hasAttribute($xmlns->nodeName)) {
xmlns_attribute($xmlns->prefix, $xmlns->namespaceURI)($target);
}
Expand Down
3 changes: 1 addition & 2 deletions src/Xml/Dom/Manipulator/Element/rename.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace VeeWee\Xml\Dom\Manipulator\Element;

use \DOM\NameSpaceNode;
use VeeWee\Xml\Exception\RuntimeException;
use function VeeWee\Xml\Dom\Builder\element;
use function VeeWee\Xml\Dom\Builder\namespaced_element;
Expand Down Expand Up @@ -33,7 +32,7 @@ function rename(\DOM\Element $target, string $newQName, ?string $newNamespaceURI
append(...children($target))($newElement);

xmlns_attributes_list($target)->forEach(
static function (\DOM\NameSpaceNode $attribute) use ($target, $newElement): void {
static function (\DOM\Attr $attribute) use ($target, $newElement): void {
if (is_default_xmlns_attribute($attribute) || $target->prefix === $attribute->prefix) {
return;
}
Expand Down
8 changes: 3 additions & 5 deletions src/Xml/Dom/Manipulator/Node/remove_namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,22 @@

namespace VeeWee\Xml\Dom\Manipulator\Node;

use \DOM\Element;
use \DOM\NameSpaceNode;
use VeeWee\Xml\Exception\RuntimeException;
use function VeeWee\Xml\ErrorHandling\disallow_issues;
use function VeeWee\Xml\ErrorHandling\disallow_libxml_false_returns;

/**
* @throws RuntimeException
*/
function remove_namespace(\DOM\NameSpaceNode $target, \DOM\Element $parent): \DOM\NameSpaceNode
function remove_namespace(\DOM\Attr $target, \DOM\Element $parent): \DOM\Attr
{
return disallow_issues(
/**
* @throws RuntimeException
*/
static function () use ($target, $parent): \DOM\NameSpaceNode {
static function () use ($target, $parent): \DOM\Attr {
disallow_libxml_false_returns(
$parent->removeAttributeNS($target->namespaceURI, $target->prefix),
$parent->removeAttributeNode($target),
'Could not remove xmlns attribute from dom element'
);

Expand Down
2 changes: 1 addition & 1 deletion src/Xml/Dom/Manipulator/Xmlns/rename.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ static function (\DOM\Node $node) use ($namespaceURI, $newPrefix, $predicate, $r
// Remove old xmlns declarations:
$namespaceNodes = xmlns_attributes_list($node)
->filter(
static fn (\DOM\NameSpaceNode $xmlns): bool
static fn (\DOM\Attr $xmlns): bool
=> $xmlns->namespaceURI === $namespaceURI && $xmlns->prefix !== $newPrefix
);

Expand Down
10 changes: 10 additions & 0 deletions src/Xml/Dom/Manipulator/append.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
use Closure;
use \DOM\Node;
use VeeWee\Xml\Exception\RuntimeException;
use function VeeWee\Xml\Dom\Predicate\is_attribute;
use function VeeWee\Xml\Dom\Predicate\is_element;
use function VeeWee\Xml\ErrorHandling\disallow_issues;
use function VeeWee\Xml\ErrorHandling\disallow_libxml_false_returns;

/**
* @no-named-arguments
Expand All @@ -19,6 +22,13 @@ function append(\DOM\Node ... $nodes): Closure
return static fn (\DOM\Node $target): \DOM\Node => disallow_issues(
static function () use ($target, $nodes) {
foreach ($nodes as $node) {
// Attributes cannot be appended with appendChild.
// Setting the attribute node to the element is the correct way to append an attribute.
if (is_attribute($node) && is_element($target)) {
$target->setAttributeNode($node);
continue;
}

$target->appendChild($node);
}

Expand Down
3 changes: 1 addition & 2 deletions src/Xml/Dom/Predicate/is_default_xmlns_attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

namespace VeeWee\Xml\Dom\Predicate;

use \DOM\NameSpaceNode;
use \DOM\Node;

function is_default_xmlns_attribute(\DOM\Node|\DOM\NameSpaceNode $node): bool
function is_default_xmlns_attribute(\DOM\Node $node): bool
{
return is_xmlns_attribute($node) && $node->prefix === '';
}
3 changes: 1 addition & 2 deletions src/Xml/Dom/Predicate/is_document_element.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

namespace VeeWee\Xml\Dom\Predicate;

use \DOM\NameSpaceNode;
use \DOM\Node;
use function VeeWee\Xml\Dom\Locator\Node\detect_document;

function is_document_element(\DOM\Node|\DOM\NameSpaceNode $node): bool
function is_document_element(\DOM\Node $node): bool
{
return is_element($node) && detect_document($node)->documentElement === $node;
}
8 changes: 4 additions & 4 deletions src/Xml/Dom/Predicate/is_xmlns_attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

namespace VeeWee\Xml\Dom\Predicate;

use \DOM\NameSpaceNode;
use \DOM\Node;
use VeeWee\Xml\Xmlns\Xmlns;

/**
* @psalm-assert-if-true \DOM\NameSpaceNode $node
* @psalm-assert-if-true \DOM\Attr $node
*/
function is_xmlns_attribute(\DOM\Node|\DOM\NameSpaceNode $node): bool
function is_xmlns_attribute(\DOM\Node $node): bool
{
return $node instanceof \DOM\NameSpaceNode;
return is_attribute($node) && $node->namespaceURI === Xmlns::xmlns()->value();
}
21 changes: 10 additions & 11 deletions src/Xml/Dom/Traverser/Visitor/RemoveNamespaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,24 @@

namespace VeeWee\Xml\Dom\Traverser\Visitor;

use \DOM\NameSpaceNode;
use \DOM\Attr;
use \DOM\Node;
use VeeWee\Xml\Dom\Traverser\Action;
use VeeWee\Xml\Exception\RuntimeException;
use function Psl\Iter\contains;
use function VeeWee\Xml\Dom\Locator\Attribute\xmlns_attributes_list;
use function VeeWee\Xml\Dom\Predicate\is_element;
use function VeeWee\Xml\Dom\Predicate\is_xmlns_attribute;

final class RemoveNamespaces extends AbstractVisitor
{
/**
* @var null | callable(\DOM\NameSpaceNode): bool
* @var null | callable(\DOM\Attr): bool
*/
private $filter;

/**
* @param null | callable(\DOM\NameSpaceNode): bool $filter
* @param null | callable(\DOM\Attr): bool $filter
*/
public function __construct(
?callable $filter = null
Expand All @@ -35,14 +36,14 @@ public static function all(): self
public static function prefixed(): self
{
return new self(
static fn (\DOM\NameSpaceNode $node): bool => $node->prefix !== ''
static fn (\DOM\Attr $node): bool => $node->prefix !== null
);
}

public static function unprefixed(): self
{
return new self(
static fn (\DOM\NameSpaceNode $node): bool => $node->prefix === ''
static fn (\DOM\Attr $node): bool => $node->prefix === null
);
}

Expand All @@ -52,7 +53,7 @@ public static function unprefixed(): self
public static function byPrefixNames(array $prefixes): self
{
return new self(
static fn (\DOM\NameSpaceNode $node): bool => contains($prefixes, $node->prefix)
static fn (\DOM\Attr $node): bool => contains($prefixes, $node->localName)
);
}

Expand All @@ -62,7 +63,7 @@ public static function byPrefixNames(array $prefixes): self
public static function byNamespaceURIs(array $URIs): self
{
return new self(
static fn (\DOM\NameSpaceNode $node): bool => contains($URIs, $node->namespaceURI)
static fn (\DOM\Attr $node): bool => contains($URIs, $node->value)
);
}

Expand All @@ -80,11 +81,9 @@ public function onNodeLeave(\DOM\Node $node): Action
$namespaces = $namespaces->filter($this->filter);
}

// TODO : convert to is_xmlns_attribute based visitor instead of acting on element level
foreach ($namespaces as $namespace) {
$node->removeAttributeNS(
$namespace->namespaceURI,
$namespace->prefix
);
$node->removeAttributeNode($namespace);
}

return new Action\Noop();
Expand Down
6 changes: 4 additions & 2 deletions src/Xml/Dom/Traverser/Visitor/SortAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use VeeWee\Xml\Dom\Traverser\Action;
use function VeeWee\Xml\Dom\Locator\Attribute\attributes_list;
use function VeeWee\Xml\Dom\Manipulator\append;
use function VeeWee\Xml\Dom\Manipulator\Node\remove;
use function VeeWee\Xml\Dom\Predicate\is_element;
use function VeeWee\Xml\ErrorHandling\disallow_issues;

Expand All @@ -22,8 +24,8 @@ public function onNodeEnter(\DOM\Node $node): Action
->forEach(
static function (\DOM\Attr $attr) use ($node): void {
disallow_issues(static function () use ($node, $attr) {
$node->removeAttributeNode($attr);
$node->setAttributeNode($attr);
remove($attr);
append($attr)($node);
});
}
);
Expand Down
4 changes: 3 additions & 1 deletion src/Xml/Encoding/Internal/Decoder/Builder/attributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use function Psl\Dict\filter;
use function Psl\Dict\merge;
use function Psl\Iter\reduce;
use function VeeWee\Xml\Dom\Locator\Attribute\attributes_list;
use function VeeWee\Xml\Dom\Predicate\is_xmlns_attribute;

/**
* @psalm-internal VeeWee\Xml\Encoding
Expand All @@ -17,7 +19,7 @@ function attributes(\DOM\Element $element): array
{
return filter([
'@attributes' => reduce(
$element->attributes,
attributes_list($element)->filter(static fn(\DOM\Attr $attr): bool => !is_xmlns_attribute($attr)),
static fn (array $attributes, \DOM\Attr $attr): array
=> merge($attributes, attribute($attr)),
[]
Expand Down
7 changes: 4 additions & 3 deletions src/Xml/Encoding/Internal/Decoder/Builder/namespaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace VeeWee\Xml\Encoding\Internal\Decoder\Builder;

use \DOM\Element;
use \DOM\NameSpaceNode;
use VeeWee\Xml\Exception\RuntimeException;
use function Psl\Dict\filter;
use function Psl\Dict\merge;
Expand All @@ -20,9 +19,11 @@ function namespaces(\DOM\Element $element): array
{
return filter([
'@namespaces' => xmlns_attributes_list($element)->reduce(
static fn (array $namespaces, \DOM\NameSpaceNode $node)
static fn (array $namespaces, \DOM\Attr $node)
=> $node->namespaceURI
? merge($namespaces, [(string) $node->prefix => $node->namespaceURI])
? merge($namespaces, [
($node->prefix ? $node->localName : '') => $node->value
])
: $namespaces,
[]
),
Expand Down
7 changes: 3 additions & 4 deletions tests/Xml/Dom/Configurator/PrettyPrintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ public function test_it_can_trim_contents(): void
</hello>
EOXML;

static::assertSame($doc, $result);
// TODO : static::assertFalse($doc->preserveWhiteSpace);
static::assertTrue($doc->formatOutput);
static::assertSame($expected, xml_string()($doc->documentElement));
static::assertNotSame($doc, $result);
static::assertTrue($result->formatOutput);
static::assertSame($expected, xml_string()($result->documentElement));
}
}
7 changes: 3 additions & 4 deletions tests/Xml/Dom/Configurator/TrimSpacesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ public function test_it_can_trim_contents(): void
$configurator = trim_spaces();
$result = $configurator($doc);

static::assertSame($doc, $result);
// TODO : static::assertFalse($doc->preserveWhiteSpace);
static::assertFalse($doc->formatOutput);
static::assertSame('<hello><world/></hello>', xml_string()($doc->documentElement));
static::assertNotSame($doc, $result);
static::assertFalse($result->formatOutput);
static::assertSame('<hello><world/></hello>', xml_string()($result->documentElement));
}
}
Loading

0 comments on commit c5c3c5b

Please sign in to comment.