|
| 1 | +--TEST-- |
| 2 | +GH-11404: DOMDocument::savexml and friends ommit xmlns="" declaration for null namespace, creating incorrect xml representation of the DOM |
| 3 | +--EXTENSIONS-- |
| 4 | +dom |
| 5 | +--FILE-- |
| 6 | +<?php |
| 7 | + |
| 8 | +echo "-- Test append and attributes: with default namespace variation --\n"; |
| 9 | + |
| 10 | +function testAppendAndAttributes($dom) { |
| 11 | + $nodeA = $dom->createElement('a'); |
| 12 | + $nodeB = $dom->createElementNS(null, 'b'); |
| 13 | + $nodeC = $dom->createElementNS('', 'c'); |
| 14 | + $nodeD = $dom->createElement('d'); |
| 15 | + $nodeD->setAttributeNS('some:ns', 'x:attrib', 'val'); |
| 16 | + $nodeE = $dom->createElementNS('some:ns', 'e'); |
| 17 | + // And these two respect the default ns. |
| 18 | + $nodeE->setAttributeNS(null, 'attrib1', 'val'); |
| 19 | + $nodeE->setAttributeNS('', 'attrib2', 'val'); |
| 20 | + |
| 21 | + $dom->documentElement->appendChild($nodeA); |
| 22 | + $dom->documentElement->appendChild($nodeB); |
| 23 | + $dom->documentElement->appendChild($nodeC); |
| 24 | + $dom->documentElement->appendChild($nodeD); |
| 25 | + $dom->documentElement->appendChild($nodeE); |
| 26 | + |
| 27 | + var_dump($nodeA->namespaceURI); |
| 28 | + var_dump($nodeB->namespaceURI); |
| 29 | + var_dump($nodeC->namespaceURI); |
| 30 | + var_dump($nodeD->namespaceURI); |
| 31 | + var_dump($nodeE->namespaceURI); |
| 32 | + |
| 33 | + echo $dom->saveXML(); |
| 34 | + |
| 35 | + // Create a subtree without using a fragment |
| 36 | + $subtree = $dom->createElement('subtree'); |
| 37 | + $subtree->appendChild($dom->createElementNS('some:ns', 'subtreechild1')); |
| 38 | + $subtree->firstElementChild->appendChild($dom->createElement('subtreechild2')); |
| 39 | + $dom->documentElement->appendChild($subtree); |
| 40 | + |
| 41 | + echo $dom->saveXML(); |
| 42 | + |
| 43 | + // Create a subtree with the use of a fragment |
| 44 | + $subtree = $dom->createDocumentFragment(); |
| 45 | + $subtree->appendChild($child3 = $dom->createElement('child3')); |
| 46 | + $child3->appendChild($dom->createElement('child4')); |
| 47 | + $subtree->appendChild($dom->createElement('child5')); |
| 48 | + $dom->documentElement->appendChild($subtree); |
| 49 | + |
| 50 | + echo $dom->saveXML(); |
| 51 | +} |
| 52 | + |
| 53 | +$dom1 = new DOMDocument; |
| 54 | +$dom1->loadXML('<?xml version="1.0" ?><with xmlns="some:ns" />'); |
| 55 | +testAppendAndAttributes($dom1); |
| 56 | + |
| 57 | +echo "-- Test append and attributes: without default namespace variation --\n"; |
| 58 | + |
| 59 | +$dom1 = new DOMDocument; |
| 60 | +$dom1->loadXML('<?xml version="1.0" ?><with/>'); |
| 61 | +testAppendAndAttributes($dom1); |
| 62 | + |
| 63 | +echo "-- Test import --\n"; |
| 64 | + |
| 65 | +function testImport(?string $href, string $toBeImported) { |
| 66 | + $dom1 = new DOMDocument; |
| 67 | + $decl = $href === NULL ? '' : "xmlns=\"$href\""; |
| 68 | + $dom1->loadXML('<?xml version="1.0" ?><with ' . $decl . '/>'); |
| 69 | + |
| 70 | + $dom2 = new DOMDocument; |
| 71 | + $dom2->loadXML('<?xml version="1.0" ?>' . $toBeImported); |
| 72 | + |
| 73 | + $dom1->documentElement->append( |
| 74 | + $imported = $dom1->importNode($dom2->documentElement, true) |
| 75 | + ); |
| 76 | + |
| 77 | + var_dump($imported->namespaceURI); |
| 78 | + |
| 79 | + echo $dom1->saveXML(); |
| 80 | +} |
| 81 | + |
| 82 | +testImport(null, '<none/>'); |
| 83 | +testImport('', '<none/>'); |
| 84 | +testImport('some:ns', '<none/>'); |
| 85 | +testImport('', '<none><div xmlns="some:ns"/></none>'); |
| 86 | +testImport('some:ns', '<none xmlns="some:ns"><div xmlns=""/></none>'); |
| 87 | + |
| 88 | +echo "-- Namespace URI comparison --\n"; |
| 89 | + |
| 90 | +$dom1 = new DOMDocument; |
| 91 | +$dom1->loadXML('<?xml version="1.0"?><test xmlns="a:b"><div/></test>'); |
| 92 | +var_dump($dom1->firstElementChild->namespaceURI); |
| 93 | +var_dump($dom1->firstElementChild->firstElementChild->namespaceURI); |
| 94 | + |
| 95 | +$dom1 = new DOMDocument; |
| 96 | +$dom1->appendChild($dom1->createElementNS('a:b', 'parent')); |
| 97 | +$dom1->firstElementChild->appendChild($dom1->createElementNS('a:b', 'child1')); |
| 98 | +$dom1->firstElementChild->appendChild($second = $dom1->createElement('child2')); |
| 99 | +var_dump($dom1->firstElementChild->namespaceURI); |
| 100 | +var_dump($dom1->firstElementChild->firstElementChild->namespaceURI); |
| 101 | +var_dump($second->namespaceURI); |
| 102 | +echo $dom1->saveXML(); |
| 103 | + |
| 104 | +$dom1 = new DOMDocument; |
| 105 | +$dom1->loadXML('<?xml version="1.0"?><test xmlns="a:b"/>'); |
| 106 | +var_dump($dom1->firstElementChild->namespaceURI); |
| 107 | +$dom1->firstElementChild->appendChild($dom1->createElementNS('a:b', 'tag')); |
| 108 | +var_dump($dom1->firstElementChild->firstElementChild->namespaceURI); |
| 109 | +?> |
| 110 | +--EXPECT-- |
| 111 | +-- Test append and attributes: with default namespace variation -- |
| 112 | +NULL |
| 113 | +NULL |
| 114 | +NULL |
| 115 | +NULL |
| 116 | +string(7) "some:ns" |
| 117 | +<?xml version="1.0"?> |
| 118 | +<with xmlns="some:ns"><a xmlns=""/><b xmlns=""/><c xmlns=""/><d xmlns:x="some:ns" xmlns="" x:attrib="val"/><e attrib1="val" attrib2="val"/></with> |
| 119 | +<?xml version="1.0"?> |
| 120 | +<with xmlns="some:ns"><a xmlns=""/><b xmlns=""/><c xmlns=""/><d xmlns:x="some:ns" xmlns="" x:attrib="val"/><e attrib1="val" attrib2="val"/><subtree xmlns=""><subtreechild1 xmlns="some:ns"><subtreechild2 xmlns=""/></subtreechild1></subtree></with> |
| 121 | +<?xml version="1.0"?> |
| 122 | +<with xmlns="some:ns"><a xmlns=""/><b xmlns=""/><c xmlns=""/><d xmlns:x="some:ns" xmlns="" x:attrib="val"/><e attrib1="val" attrib2="val"/><subtree xmlns=""><subtreechild1 xmlns="some:ns"><subtreechild2 xmlns=""/></subtreechild1></subtree><child3 xmlns=""><child4/></child3><child5 xmlns=""/></with> |
| 123 | +-- Test append and attributes: without default namespace variation -- |
| 124 | +NULL |
| 125 | +NULL |
| 126 | +NULL |
| 127 | +NULL |
| 128 | +string(7) "some:ns" |
| 129 | +<?xml version="1.0"?> |
| 130 | +<with><a/><b/><c/><d xmlns:x="some:ns" x:attrib="val"/><e xmlns="some:ns" attrib1="val" attrib2="val"/></with> |
| 131 | +<?xml version="1.0"?> |
| 132 | +<with><a/><b/><c/><d xmlns:x="some:ns" x:attrib="val"/><e xmlns="some:ns" attrib1="val" attrib2="val"/><subtree><subtreechild1 xmlns="some:ns"><subtreechild2 xmlns=""/></subtreechild1></subtree></with> |
| 133 | +<?xml version="1.0"?> |
| 134 | +<with><a/><b/><c/><d xmlns:x="some:ns" x:attrib="val"/><e xmlns="some:ns" attrib1="val" attrib2="val"/><subtree><subtreechild1 xmlns="some:ns"><subtreechild2 xmlns=""/></subtreechild1></subtree><child3><child4/></child3><child5/></with> |
| 135 | +-- Test import -- |
| 136 | +NULL |
| 137 | +<?xml version="1.0"?> |
| 138 | +<with><none/></with> |
| 139 | +NULL |
| 140 | +<?xml version="1.0"?> |
| 141 | +<with xmlns=""><none/></with> |
| 142 | +NULL |
| 143 | +<?xml version="1.0"?> |
| 144 | +<with xmlns="some:ns"><none xmlns=""/></with> |
| 145 | +NULL |
| 146 | +<?xml version="1.0"?> |
| 147 | +<with xmlns=""><none><div xmlns="some:ns"/></none></with> |
| 148 | +string(7) "some:ns" |
| 149 | +<?xml version="1.0"?> |
| 150 | +<with xmlns="some:ns"><none><div xmlns=""/></none></with> |
| 151 | +-- Namespace URI comparison -- |
| 152 | +string(3) "a:b" |
| 153 | +string(3) "a:b" |
| 154 | +string(3) "a:b" |
| 155 | +string(3) "a:b" |
| 156 | +NULL |
| 157 | +<?xml version="1.0"?> |
| 158 | +<parent xmlns="a:b"><child1/><child2 xmlns=""/></parent> |
| 159 | +string(3) "a:b" |
| 160 | +string(3) "a:b" |
0 commit comments