diff --git a/docs/dom.md b/docs/dom.md index 4f1b431..1c589b2 100644 --- a/docs/dom.md +++ b/docs/dom.md @@ -860,6 +860,35 @@ $doc->manipulate( ); ``` +### Element + +Element specific manipulators operate on `DOMElement` instances. + +#### copy_named_xmlns_attributes + +Makes it possible to copy all names xmlns attributes from one element to an other element. + +```php +use VeeWee\Xml\Dom\Document; +use function VeeWee\Xml\Dom\Manipulator\Element\copy_named_xmlns_attributes; + +$doc = Document::fromXmlString( + << + + + + EOXML +); + +$a = $doc->xpath()->querySingle('//a'); +$b = $doc->xpath()->querySingle('//b'); + +copy_named_xmlns_attributes($b, $a); + +// > $b will contain xmlns:foo="http://foo" +``` + ### Node Node specific manipulators operate on `DOMNode` instances. diff --git a/src/Xml/Dom/Manipulator/Element/copy_named_xmlns_attributes.php b/src/Xml/Dom/Manipulator/Element/copy_named_xmlns_attributes.php new file mode 100644 index 0000000..0b251a1 --- /dev/null +++ b/src/Xml/Dom/Manipulator/Element/copy_named_xmlns_attributes.php @@ -0,0 +1,23 @@ +forEach(static function (DOMNameSpaceNode $xmlns) use ($target) { + if ($xmlns->prefix && !$target->hasAttribute($xmlns->nodeName)) { + xmlns_attribute($xmlns->prefix, $xmlns->namespaceURI)($target); + } + }); +} diff --git a/src/bootstrap.php b/src/bootstrap.php index a735da7..11f8471 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -48,6 +48,7 @@ require_once __DIR__.'/Xml/Dom/Locator/root_namespace.php'; require_once __DIR__.'/Xml/Dom/Manipulator/Attribute/rename.php'; require_once __DIR__.'/Xml/Dom/Manipulator/Document/optimize_namespaces.php'; +require_once __DIR__.'/Xml/Dom/Manipulator/Element/copy_named_xmlns_attributes.php'; require_once __DIR__.'/Xml/Dom/Manipulator/Element/rename.php'; require_once __DIR__.'/Xml/Dom/Manipulator/Node/append_external_node.php'; require_once __DIR__.'/Xml/Dom/Manipulator/Node/import_node_deeply.php'; diff --git a/tests/Xml/Dom/Manipulator/Element/CopyNamedXmlnsAttributesTest.php b/tests/Xml/Dom/Manipulator/Element/CopyNamedXmlnsAttributesTest.php new file mode 100644 index 0000000..66f7230 --- /dev/null +++ b/tests/Xml/Dom/Manipulator/Element/CopyNamedXmlnsAttributesTest.php @@ -0,0 +1,138 @@ + + + + + EOXML + ); + + $a = $doc->xpath()->querySingle('//a'); + $b = $doc->xpath()->querySingle('//b'); + + copy_named_xmlns_attributes($b, $a); + + static::assertXmlStringEqualsXmlString('', xml_string()($b)); + } + + public function test_it_does_not_copy_root_xmlns(): void + { + $doc = Document::fromXmlString( + << + + + + EOXML + ); + + $a = $doc->xpath(namespaces(['a' => "http://foo"]))->querySingle('//a:a'); + $b = $doc->xpath()->querySingle('//b'); + + copy_named_xmlns_attributes($b, $a); + + static::assertXmlStringEqualsXmlString('', xml_string()($b)); + } + + public function test_it_does_not_overwrite_the_same_name(): void + { + $doc = Document::fromXmlString( + << + + + + EOXML + ); + + $a = $doc->xpath()->querySingle('//a'); + $b = $doc->xpath()->querySingle('//b'); + + copy_named_xmlns_attributes($b, $a); + + static::assertXmlStringEqualsXmlString('', xml_string()($b)); + } + + public function test_it_can_do_many_namespaces_as_well(): void + { + $doc = Document::fromXmlString( + << + + + + EOXML + ); + + $a = $doc->xpath()->querySingle('//a'); + $b = $doc->xpath()->querySingle('//b'); + + copy_named_xmlns_attributes($b, $a); + + static::assertXmlStringEqualsXmlString('', xml_string()($b)); + } + + public function test_it_does_not_include_internally_added_namespaces(): void + { + $doc = Document::fromXmlString( + << + + + + + + EOXML + ); + + $a = $doc->xpath()->querySingle('//a'); + $b = $doc->xpath()->querySingle('//b'); + + copy_named_xmlns_attributes($b, $a); + + static::assertXmlStringEqualsXmlString('', xml_string()($b)); + } + + public function test_it_can_copy_cross_docs(): void + { + $doc1 = Document::fromXmlString( + << + + + + + EOXML + ); + $doc2 = Document::fromXmlString( + << + + + EOXML + ); + + $a = $doc1->xpath()->querySingle('//a'); + $b = $doc2->xpath()->querySingle('//b'); + + copy_named_xmlns_attributes($b, $a); + + static::assertXmlStringEqualsXmlString('', xml_string()($b)); + } +}