XmlTest.php 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. <?php
  2. /**
  3. * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  12. * @since 1.2.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Utility;
  16. use Cake\Collection\Collection;
  17. use Cake\Core\Configure;
  18. use Cake\TestSuite\TestCase;
  19. use Cake\Utility\Error\XmlException;
  20. use Cake\Utility\Xml;
  21. /**
  22. * XmlTest class
  23. *
  24. */
  25. class XmlTest extends TestCase {
  26. /**
  27. * autoFixtures property
  28. *
  29. * @var bool
  30. */
  31. public $autoFixtures = false;
  32. /**
  33. * fixtures property
  34. * @var array
  35. */
  36. public $fixtures = array(
  37. 'core.article', 'core.user'
  38. );
  39. /**
  40. * setUp method
  41. *
  42. * @return void
  43. */
  44. public function setUp() {
  45. parent::setUp();
  46. $this->_appEncoding = Configure::read('App.encoding');
  47. Configure::write('App.encoding', 'UTF-8');
  48. }
  49. /**
  50. * tearDown method
  51. *
  52. * @return void
  53. */
  54. public function tearDown() {
  55. parent::tearDown();
  56. Configure::write('App.encoding', $this->_appEncoding);
  57. }
  58. /**
  59. * testBuild method
  60. *
  61. * @return void
  62. */
  63. public function testBuild() {
  64. $xml = '<tag>value</tag>';
  65. $obj = Xml::build($xml);
  66. $this->assertTrue($obj instanceof \SimpleXMLElement);
  67. $this->assertEquals('tag', (string)$obj->getName());
  68. $this->assertEquals('value', (string)$obj);
  69. $xml = '<?xml version="1.0" encoding="UTF-8"?><tag>value</tag>';
  70. $this->assertEquals($obj, Xml::build($xml));
  71. $obj = Xml::build($xml, array('return' => 'domdocument'));
  72. $this->assertTrue($obj instanceof \DOMDocument);
  73. $this->assertEquals('tag', $obj->firstChild->nodeName);
  74. $this->assertEquals('value', $obj->firstChild->nodeValue);
  75. $xml = CORE_TESTS . 'Fixture/sample.xml';
  76. $obj = Xml::build($xml);
  77. $this->assertEquals('tags', $obj->getName());
  78. $this->assertEquals(2, count($obj));
  79. $this->assertEquals(Xml::build($xml), Xml::build(file_get_contents($xml)));
  80. $obj = Xml::build($xml, array('return' => 'domdocument'));
  81. $this->assertEquals('tags', $obj->firstChild->nodeName);
  82. $this->assertEquals(
  83. Xml::build($xml, array('return' => 'domdocument')),
  84. Xml::build(file_get_contents($xml), array('return' => 'domdocument'))
  85. );
  86. $xml = array('tag' => 'value');
  87. $obj = Xml::build($xml);
  88. $this->assertEquals('tag', $obj->getName());
  89. $this->assertEquals('value', (string)$obj);
  90. $obj = Xml::build($xml, array('return' => 'domdocument'));
  91. $this->assertEquals('tag', $obj->firstChild->nodeName);
  92. $this->assertEquals('value', $obj->firstChild->nodeValue);
  93. $obj = Xml::build($xml, array('return' => 'domdocument', 'encoding' => null));
  94. $this->assertNotRegExp('/encoding/', $obj->saveXML());
  95. }
  96. /**
  97. * Test build() with a Collection instance.
  98. *
  99. * @return void
  100. */
  101. public function testBuildCollection() {
  102. $xml = new Collection(['tag' => 'value']);
  103. $obj = Xml::build($xml);
  104. $this->assertEquals('tag', $obj->getName());
  105. $this->assertEquals('value', (string)$obj);
  106. $xml = new Collection([
  107. 'response' => [
  108. 'users' => new Collection(['leonardo', 'raphael'])
  109. ]
  110. ]);
  111. $obj = Xml::build($xml);
  112. $this->assertContains('<users>leonardo</users>', $obj->saveXML());
  113. }
  114. /**
  115. * data provider function for testBuildInvalidData
  116. *
  117. * @return array
  118. */
  119. public static function invalidDataProvider() {
  120. return array(
  121. array(null),
  122. array(false),
  123. array(''),
  124. array('http://localhost/notthere.xml'),
  125. );
  126. }
  127. /**
  128. * testBuildInvalidData
  129. *
  130. * @dataProvider invalidDataProvider
  131. * @expectedException \Cake\Error\Exception
  132. * @return void
  133. */
  134. public function testBuildInvalidData($value) {
  135. $this->assertFalse(defined('HHVM_VERSION') && !empty($value), 'Segfaults HHVM');
  136. Xml::build($value);
  137. }
  138. /**
  139. * Test that building SimpleXmlElement with invalid XML causes the right exception.
  140. *
  141. * @expectedException \Cake\Utility\Error\XmlException
  142. * @return void
  143. */
  144. public function testBuildInvalidDataSimpleXml() {
  145. $input = '<derp';
  146. $xml = Xml::build($input, array('return' => 'simplexml'));
  147. }
  148. /**
  149. * test build with a single empty tag
  150. *
  151. * @return void
  152. */
  153. public function testBuildEmptyTag() {
  154. try {
  155. Xml::build('<tag>');
  156. $this->fail('No exception');
  157. } catch (\Exception $e) {
  158. $this->assertTrue(true, 'An exception was raised');
  159. }
  160. }
  161. /**
  162. * testFromArray method
  163. *
  164. * @return void
  165. */
  166. public function testFromArray() {
  167. $xml = array('tag' => 'value');
  168. $obj = Xml::fromArray($xml);
  169. $this->assertEquals('tag', $obj->getName());
  170. $this->assertEquals('value', (string)$obj);
  171. $xml = array('tag' => null);
  172. $obj = Xml::fromArray($xml);
  173. $this->assertEquals('tag', $obj->getName());
  174. $this->assertEquals('', (string)$obj);
  175. $xml = array('tag' => array('@' => 'value'));
  176. $obj = Xml::fromArray($xml);
  177. $this->assertEquals('tag', $obj->getName());
  178. $this->assertEquals('value', (string)$obj);
  179. $xml = array(
  180. 'tags' => array(
  181. 'tag' => array(
  182. array(
  183. 'id' => '1',
  184. 'name' => 'defect'
  185. ),
  186. array(
  187. 'id' => '2',
  188. 'name' => 'enhancement'
  189. )
  190. )
  191. )
  192. );
  193. $obj = Xml::fromArray($xml, 'attributes');
  194. $this->assertTrue($obj instanceof \SimpleXMLElement);
  195. $this->assertEquals('tags', $obj->getName());
  196. $this->assertEquals(2, count($obj));
  197. $xmlText = <<<XML
  198. <?xml version="1.0" encoding="UTF-8"?>
  199. <tags>
  200. <tag id="1" name="defect"/>
  201. <tag id="2" name="enhancement"/>
  202. </tags>
  203. XML;
  204. $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML());
  205. $obj = Xml::fromArray($xml);
  206. $this->assertTrue($obj instanceof \SimpleXMLElement);
  207. $this->assertEquals('tags', $obj->getName());
  208. $this->assertEquals(2, count($obj));
  209. $xmlText = <<<XML
  210. <?xml version="1.0" encoding="UTF-8"?>
  211. <tags>
  212. <tag>
  213. <id>1</id>
  214. <name>defect</name>
  215. </tag>
  216. <tag>
  217. <id>2</id>
  218. <name>enhancement</name>
  219. </tag>
  220. </tags>
  221. XML;
  222. $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML());
  223. $xml = array(
  224. 'tags' => array(
  225. )
  226. );
  227. $obj = Xml::fromArray($xml);
  228. $this->assertEquals('tags', $obj->getName());
  229. $this->assertEquals('', (string)$obj);
  230. $xml = array(
  231. 'tags' => array(
  232. 'bool' => true,
  233. 'int' => 1,
  234. 'float' => 10.2,
  235. 'string' => 'ok',
  236. 'null' => null,
  237. 'array' => array()
  238. )
  239. );
  240. $obj = Xml::fromArray($xml, 'tags');
  241. $this->assertEquals(6, count($obj));
  242. $this->assertSame((string)$obj->bool, '1');
  243. $this->assertSame((string)$obj->int, '1');
  244. $this->assertSame((string)$obj->float, '10.2');
  245. $this->assertSame((string)$obj->string, 'ok');
  246. $this->assertSame((string)$obj->null, '');
  247. $this->assertSame((string)$obj->array, '');
  248. $xml = array(
  249. 'tags' => array(
  250. 'tag' => array(
  251. array(
  252. '@id' => '1',
  253. 'name' => 'defect'
  254. ),
  255. array(
  256. '@id' => '2',
  257. 'name' => 'enhancement'
  258. )
  259. )
  260. )
  261. );
  262. $obj = Xml::fromArray($xml, 'tags');
  263. $xmlText = <<<XML
  264. <?xml version="1.0" encoding="UTF-8"?>
  265. <tags>
  266. <tag id="1">
  267. <name>defect</name>
  268. </tag>
  269. <tag id="2">
  270. <name>enhancement</name>
  271. </tag>
  272. </tags>
  273. XML;
  274. $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML());
  275. $xml = array(
  276. 'tags' => array(
  277. 'tag' => array(
  278. array(
  279. '@id' => '1',
  280. 'name' => 'defect',
  281. '@' => 'Tag 1'
  282. ),
  283. array(
  284. '@id' => '2',
  285. 'name' => 'enhancement'
  286. ),
  287. ),
  288. '@' => 'All tags'
  289. )
  290. );
  291. $obj = Xml::fromArray($xml, 'tags');
  292. $xmlText = <<<XML
  293. <?xml version="1.0" encoding="UTF-8"?>
  294. <tags>All tags<tag id="1">Tag 1<name>defect</name></tag><tag id="2"><name>enhancement</name></tag></tags>
  295. XML;
  296. $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML());
  297. $xml = array(
  298. 'tags' => array(
  299. 'tag' => array(
  300. 'id' => 1,
  301. '@' => 'defect'
  302. )
  303. )
  304. );
  305. $obj = Xml::fromArray($xml, 'attributes');
  306. $xmlText = '<' . '?xml version="1.0" encoding="UTF-8"?><tags><tag id="1">defect</tag></tags>';
  307. $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML());
  308. $xml = array(
  309. 'tag' => array(
  310. '@' => 0,
  311. '@test' => 'A test'
  312. )
  313. );
  314. $obj = Xml::fromArray($xml);
  315. $xmlText = <<<XML
  316. <?xml version="1.0" encoding="UTF-8"?>
  317. <tag test="A test">0</tag>
  318. XML;
  319. $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML());
  320. }
  321. /**
  322. * Test non-sequential keys in list types.
  323. *
  324. * @return void
  325. */
  326. public function testFromArrayNonSequentialKeys() {
  327. $xmlArray = array(
  328. 'Event' => array(
  329. array(
  330. 'id' => '235',
  331. 'Attribute' => array(
  332. 0 => array(
  333. 'id' => '9646',
  334. ),
  335. 2 => array(
  336. 'id' => '9647',
  337. )
  338. )
  339. )
  340. )
  341. );
  342. $obj = Xml::fromArray($xmlArray);
  343. $expected = <<<XML
  344. <?xml version="1.0" encoding="UTF-8"?>
  345. <Event>
  346. <id>235</id>
  347. <Attribute>
  348. <id>9646</id>
  349. </Attribute>
  350. <Attribute>
  351. <id>9647</id>
  352. </Attribute>
  353. </Event>
  354. XML;
  355. $this->assertXmlStringEqualsXmlString($expected, $obj->asXML());
  356. }
  357. /**
  358. * testFromArrayPretty method
  359. *
  360. * @return void
  361. */
  362. public function testFromArrayPretty() {
  363. $xml = array(
  364. 'tags' => array(
  365. 'tag' => array(
  366. array(
  367. 'id' => '1',
  368. 'name' => 'defect'
  369. ),
  370. array(
  371. 'id' => '2',
  372. 'name' => 'enhancement'
  373. )
  374. )
  375. )
  376. );
  377. $expected = <<<XML
  378. <?xml version="1.0" encoding="UTF-8"?>
  379. <tags><tag><id>1</id><name>defect</name></tag><tag><id>2</id><name>enhancement</name></tag></tags>
  380. XML;
  381. $xmlResponse = Xml::fromArray($xml, array('pretty' => false));
  382. $this->assertTextEquals($expected, $xmlResponse->asXML());
  383. $expected = <<<XML
  384. <?xml version="1.0" encoding="UTF-8"?>
  385. <tags>
  386. <tag>
  387. <id>1</id>
  388. <name>defect</name>
  389. </tag>
  390. <tag>
  391. <id>2</id>
  392. <name>enhancement</name>
  393. </tag>
  394. </tags>
  395. XML;
  396. $xmlResponse = Xml::fromArray($xml, array('pretty' => true));
  397. $this->assertTextEquals($expected, $xmlResponse->asXML());
  398. $xml = array(
  399. 'tags' => array(
  400. 'tag' => array(
  401. array(
  402. 'id' => '1',
  403. 'name' => 'defect'
  404. ),
  405. array(
  406. 'id' => '2',
  407. 'name' => 'enhancement'
  408. )
  409. )
  410. )
  411. );
  412. $expected = <<<XML
  413. <?xml version="1.0" encoding="UTF-8"?>
  414. <tags><tag id="1" name="defect"/><tag id="2" name="enhancement"/></tags>
  415. XML;
  416. $xmlResponse = Xml::fromArray($xml, array('pretty' => false, 'format' => 'attributes'));
  417. $this->assertTextEquals($expected, $xmlResponse->asXML());
  418. $expected = <<<XML
  419. <?xml version="1.0" encoding="UTF-8"?>
  420. <tags>
  421. <tag id="1" name="defect"/>
  422. <tag id="2" name="enhancement"/>
  423. </tags>
  424. XML;
  425. $xmlResponse = Xml::fromArray($xml, array('pretty' => true, 'format' => 'attributes'));
  426. $this->assertTextEquals($expected, $xmlResponse->asXML());
  427. }
  428. /**
  429. * data provider for fromArray() failures
  430. *
  431. * @return array
  432. */
  433. public static function invalidArrayDataProvider() {
  434. return array(
  435. array(''),
  436. array(null),
  437. array(false),
  438. array(array()),
  439. array(array('numeric key as root')),
  440. array(array('item1' => '', 'item2' => '')),
  441. array(array('items' => array('item1', 'item2'))),
  442. array(array(
  443. 'tags' => array(
  444. 'tag' => array(
  445. array(
  446. array(
  447. 'string'
  448. )
  449. )
  450. )
  451. )
  452. )),
  453. array(array(
  454. 'tags' => array(
  455. '@tag' => array(
  456. array(
  457. '@id' => '1',
  458. 'name' => 'defect'
  459. ),
  460. array(
  461. '@id' => '2',
  462. 'name' => 'enhancement'
  463. )
  464. )
  465. )
  466. )),
  467. array(new \DateTime())
  468. );
  469. }
  470. /**
  471. * testFromArrayFail method
  472. *
  473. * @dataProvider invalidArrayDataProvider
  474. * @return void
  475. */
  476. public function testFromArrayFail($value) {
  477. try {
  478. Xml::fromArray($value);
  479. $this->fail('No exception.');
  480. } catch (\Exception $e) {
  481. $this->assertTrue(true, 'Caught exception.');
  482. }
  483. }
  484. /**
  485. * Test that there are not unterminated errors when building xml
  486. *
  487. * @return void
  488. */
  489. public function testFromArrayUnterminatedError() {
  490. $data = array(
  491. 'product_ID' => 'GENERT-DL',
  492. 'deeplink' => 'http://example.com/deep',
  493. 'image_URL' => 'http://example.com/image',
  494. 'thumbnail_image_URL' => 'http://example.com/thumb',
  495. 'brand' => 'Malte Lange & Co',
  496. 'availability' => 'in stock',
  497. 'authors' => array(
  498. 'author' => array('Malte Lange & Co')
  499. )
  500. );
  501. $xml = Xml::fromArray(array('products' => $data), 'tags');
  502. $expected = <<<XML
  503. <?xml version="1.0" encoding="UTF-8"?>
  504. <products>
  505. <product_ID>GENERT-DL</product_ID>
  506. <deeplink>http://example.com/deep</deeplink>
  507. <image_URL>http://example.com/image</image_URL>
  508. <thumbnail_image_URL>http://example.com/thumb</thumbnail_image_URL>
  509. <brand>Malte Lange &amp; Co</brand>
  510. <availability>in stock</availability>
  511. <authors>
  512. <author>Malte Lange &amp; Co</author>
  513. </authors>
  514. </products>
  515. XML;
  516. $this->assertXmlStringEqualsXmlString($expected, $xml->asXML());
  517. }
  518. /**
  519. * testToArray method
  520. *
  521. * @return void
  522. */
  523. public function testToArray() {
  524. $xml = '<tag>name</tag>';
  525. $obj = Xml::build($xml);
  526. $this->assertEquals(array('tag' => 'name'), Xml::toArray($obj));
  527. $xml = CORE_TESTS . 'Fixture/sample.xml';
  528. $obj = Xml::build($xml);
  529. $expected = array(
  530. 'tags' => array(
  531. 'tag' => array(
  532. array(
  533. '@id' => '1',
  534. 'name' => 'defect'
  535. ),
  536. array(
  537. '@id' => '2',
  538. 'name' => 'enhancement'
  539. )
  540. )
  541. )
  542. );
  543. $this->assertEquals($expected, Xml::toArray($obj));
  544. $array = array(
  545. 'tags' => array(
  546. 'tag' => array(
  547. array(
  548. 'id' => '1',
  549. 'name' => 'defect'
  550. ),
  551. array(
  552. 'id' => '2',
  553. 'name' => 'enhancement'
  554. )
  555. )
  556. )
  557. );
  558. $this->assertEquals(Xml::toArray(Xml::fromArray($array, 'tags')), $array);
  559. $expected = array(
  560. 'tags' => array(
  561. 'tag' => array(
  562. array(
  563. '@id' => '1',
  564. '@name' => 'defect'
  565. ),
  566. array(
  567. '@id' => '2',
  568. '@name' => 'enhancement'
  569. )
  570. )
  571. )
  572. );
  573. $this->assertEquals($expected, Xml::toArray(Xml::fromArray($array, 'attributes')));
  574. $this->assertEquals($expected, Xml::toArray(Xml::fromArray($array, array('return' => 'domdocument', 'format' => 'attributes'))));
  575. $this->assertEquals(Xml::toArray(Xml::fromArray($array)), $array);
  576. $this->assertEquals(Xml::toArray(Xml::fromArray($array, array('return' => 'domdocument'))), $array);
  577. $array = array(
  578. 'tags' => array(
  579. 'tag' => array(
  580. 'id' => '1',
  581. 'posts' => array(
  582. array('id' => '1'),
  583. array('id' => '2')
  584. )
  585. ),
  586. 'tagOther' => array(
  587. 'subtag' => array(
  588. 'id' => '1'
  589. )
  590. )
  591. )
  592. );
  593. $expected = array(
  594. 'tags' => array(
  595. 'tag' => array(
  596. '@id' => '1',
  597. 'posts' => array(
  598. array('@id' => '1'),
  599. array('@id' => '2')
  600. )
  601. ),
  602. 'tagOther' => array(
  603. 'subtag' => array(
  604. '@id' => '1'
  605. )
  606. )
  607. )
  608. );
  609. $this->assertEquals($expected, Xml::toArray(Xml::fromArray($array, 'attributes')));
  610. $this->assertEquals($expected, Xml::toArray(Xml::fromArray($array, array('format' => 'attributes', 'return' => 'domdocument'))));
  611. $xml = <<<XML
  612. <root>
  613. <tag id="1">defect</tag>
  614. </root>
  615. XML;
  616. $obj = Xml::build($xml);
  617. $expected = array(
  618. 'root' => array(
  619. 'tag' => array(
  620. '@id' => 1,
  621. '@' => 'defect'
  622. )
  623. )
  624. );
  625. $this->assertEquals($expected, Xml::toArray($obj));
  626. $xml = <<<XML
  627. <root>
  628. <table xmlns="http://www.w3.org/TR/html4/"><tr><td>Apples</td><td>Bananas</td></tr></table>
  629. <table xmlns="http://www.cakephp.org"><name>CakePHP</name><license>MIT</license></table>
  630. <table>The book is on the table.</table>
  631. </root>
  632. XML;
  633. $obj = Xml::build($xml);
  634. $expected = array(
  635. 'root' => array(
  636. 'table' => array(
  637. array('tr' => array('td' => array('Apples', 'Bananas'))),
  638. array('name' => 'CakePHP', 'license' => 'MIT'),
  639. 'The book is on the table.'
  640. )
  641. )
  642. );
  643. $this->assertEquals($expected, Xml::toArray($obj));
  644. $xml = <<<XML
  645. <root xmlns:cake="http://www.cakephp.org/">
  646. <tag>defect</tag>
  647. <cake:bug>1</cake:bug>
  648. </root>
  649. XML;
  650. $obj = Xml::build($xml);
  651. $expected = array(
  652. 'root' => array(
  653. 'tag' => 'defect',
  654. 'cake:bug' => 1
  655. )
  656. );
  657. $this->assertEquals($expected, Xml::toArray($obj));
  658. $xml = '<tag type="myType">0</tag>';
  659. $obj = Xml::build($xml);
  660. $expected = array(
  661. 'tag' => array(
  662. '@type' => 'myType',
  663. '@' => 0
  664. )
  665. );
  666. $this->assertEquals($expected, Xml::toArray($obj));
  667. }
  668. /**
  669. * testRss
  670. *
  671. * @return void
  672. */
  673. public function testRss() {
  674. $rss = file_get_contents(CORE_TESTS . 'Fixture/rss.xml');
  675. $rssAsArray = Xml::toArray(Xml::build($rss));
  676. $this->assertEquals('2.0', $rssAsArray['rss']['@version']);
  677. $this->assertEquals(2, count($rssAsArray['rss']['channel']['item']));
  678. $atomLink = array('@href' => 'http://bakery.cakephp.org/articles/rss', '@rel' => 'self', '@type' => 'application/rss+xml');
  679. $this->assertEquals($rssAsArray['rss']['channel']['atom:link'], $atomLink);
  680. $this->assertEquals('http://bakery.cakephp.org/', $rssAsArray['rss']['channel']['link']);
  681. $expected = array(
  682. 'title' => 'Alertpay automated sales via IPN',
  683. 'link' => 'http://bakery.cakephp.org/articles/view/alertpay-automated-sales-via-ipn',
  684. 'description' => 'I\'m going to show you how I implemented a payment module via the Alertpay payment processor.',
  685. 'pubDate' => 'Tue, 31 Aug 2010 01:42:00 -0500',
  686. 'guid' => 'http://bakery.cakephp.org/articles/view/alertpay-automated-sales-via-ipn'
  687. );
  688. $this->assertSame($expected, $rssAsArray['rss']['channel']['item'][1]);
  689. $rss = array(
  690. 'rss' => array(
  691. 'xmlns:atom' => 'http://www.w3.org/2005/Atom',
  692. '@version' => '2.0',
  693. 'channel' => array(
  694. 'atom:link' => array(
  695. '@href' => 'http://bakery.cakephp.org/articles/rss',
  696. '@rel' => 'self',
  697. '@type' => 'application/rss+xml'
  698. ),
  699. 'title' => 'The Bakery: ',
  700. 'link' => 'http://bakery.cakephp.org/',
  701. 'description' => 'Recent Articles at The Bakery.',
  702. 'pubDate' => 'Sun, 12 Sep 2010 04:18:26 -0500',
  703. 'item' => array(
  704. array(
  705. 'title' => 'CakePHP 1.3.4 released',
  706. 'link' => 'http://bakery.cakephp.org/articles/view/cakephp-1-3-4-released'
  707. ),
  708. array(
  709. 'title' => 'Wizard Component 1.2 Tutorial',
  710. 'link' => 'http://bakery.cakephp.org/articles/view/wizard-component-1-2-tutorial'
  711. )
  712. )
  713. )
  714. )
  715. );
  716. $rssAsSimpleXML = Xml::fromArray($rss);
  717. $xmlText = <<<XML
  718. <?xml version="1.0" encoding="UTF-8"?>
  719. <rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  720. <channel>
  721. <atom:link href="http://bakery.cakephp.org/articles/rss" rel="self" type="application/rss+xml"/>
  722. <title>The Bakery: </title>
  723. <link>http://bakery.cakephp.org/</link>
  724. <description>Recent Articles at The Bakery.</description>
  725. <pubDate>Sun, 12 Sep 2010 04:18:26 -0500</pubDate>
  726. <item>
  727. <title>CakePHP 1.3.4 released</title>
  728. <link>http://bakery.cakephp.org/articles/view/cakephp-1-3-4-released</link>
  729. </item>
  730. <item>
  731. <title>Wizard Component 1.2 Tutorial</title>
  732. <link>http://bakery.cakephp.org/articles/view/wizard-component-1-2-tutorial</link>
  733. </item>
  734. </channel>
  735. </rss>
  736. XML;
  737. $this->assertXmlStringEqualsXmlString($xmlText, $rssAsSimpleXML->asXML());
  738. }
  739. /**
  740. * testXmlRpc
  741. *
  742. * @return void
  743. */
  744. public function testXmlRpc() {
  745. $xml = Xml::build('<methodCall><methodName>test</methodName><params /></methodCall>');
  746. $expected = array(
  747. 'methodCall' => array(
  748. 'methodName' => 'test',
  749. 'params' => ''
  750. )
  751. );
  752. $this->assertSame($expected, Xml::toArray($xml));
  753. $xml = Xml::build('<methodCall><methodName>test</methodName><params><param><value><array><data><value><int>12</int></value><value><string>Egypt</string></value><value><boolean>0</boolean></value><value><int>-31</int></value></data></array></value></param></params></methodCall>');
  754. $expected = array(
  755. 'methodCall' => array(
  756. 'methodName' => 'test',
  757. 'params' => array(
  758. 'param' => array(
  759. 'value' => array(
  760. 'array' => array(
  761. 'data' => array(
  762. 'value' => array(
  763. array('int' => '12'),
  764. array('string' => 'Egypt'),
  765. array('boolean' => '0'),
  766. array('int' => '-31')
  767. )
  768. )
  769. )
  770. )
  771. )
  772. )
  773. )
  774. );
  775. $this->assertSame($expected, Xml::toArray($xml));
  776. $xmlText = <<<XML
  777. <?xml version="1.0" encoding="UTF-8"?>
  778. <methodResponse>
  779. <params>
  780. <param>
  781. <value>
  782. <array>
  783. <data>
  784. <value>
  785. <int>1</int>
  786. </value>
  787. <value>
  788. <string>testing</string>
  789. </value>
  790. </data>
  791. </array>
  792. </value>
  793. </param>
  794. </params>
  795. </methodResponse>
  796. XML;
  797. $xml = Xml::build($xmlText);
  798. $expected = array(
  799. 'methodResponse' => array(
  800. 'params' => array(
  801. 'param' => array(
  802. 'value' => array(
  803. 'array' => array(
  804. 'data' => array(
  805. 'value' => array(
  806. array('int' => '1'),
  807. array('string' => 'testing')
  808. )
  809. )
  810. )
  811. )
  812. )
  813. )
  814. )
  815. );
  816. $this->assertSame($expected, Xml::toArray($xml));
  817. $xml = Xml::fromArray($expected, 'tags');
  818. $this->assertXmlStringEqualsXmlString($xmlText, $xml->asXML());
  819. }
  820. /**
  821. * testSoap
  822. *
  823. * @return void
  824. */
  825. public function testSoap() {
  826. $xmlRequest = Xml::build(CORE_TESTS . 'Fixture/soap_request.xml');
  827. $expected = array(
  828. 'Envelope' => array(
  829. '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding',
  830. 'soap:Body' => array(
  831. 'm:GetStockPrice' => array(
  832. 'm:StockName' => 'IBM'
  833. )
  834. )
  835. )
  836. );
  837. $this->assertEquals($expected, Xml::toArray($xmlRequest));
  838. $xmlResponse = Xml::build(CORE_TESTS . DS . 'Fixture/soap_response.xml');
  839. $expected = array(
  840. 'Envelope' => array(
  841. '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding',
  842. 'soap:Body' => array(
  843. 'm:GetStockPriceResponse' => array(
  844. 'm:Price' => '34.5'
  845. )
  846. )
  847. )
  848. );
  849. $this->assertEquals($expected, Xml::toArray($xmlResponse));
  850. $xml = array(
  851. 'soap:Envelope' => array(
  852. 'xmlns:soap' => 'http://www.w3.org/2001/12/soap-envelope',
  853. '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding',
  854. 'soap:Body' => array(
  855. 'xmlns:m' => 'http://www.example.org/stock',
  856. 'm:GetStockPrice' => array(
  857. 'm:StockName' => 'IBM'
  858. )
  859. )
  860. )
  861. );
  862. $xmlRequest = Xml::fromArray($xml, array('encoding' => null));
  863. $xmlText = <<<XML
  864. <?xml version="1.0"?>
  865. <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
  866. <soap:Body xmlns:m="http://www.example.org/stock">
  867. <m:GetStockPrice><m:StockName>IBM</m:StockName></m:GetStockPrice>
  868. </soap:Body>
  869. </soap:Envelope>
  870. XML;
  871. $this->assertXmlStringEqualsXmlString($xmlText, $xmlRequest->asXML());
  872. }
  873. /**
  874. * testNamespace
  875. *
  876. * @return void
  877. */
  878. public function testNamespace() {
  879. $xml = <<<XML
  880. <root xmlns:ns="http://cakephp.org">
  881. <ns:tag id="1">
  882. <child>good</child>
  883. <otherchild>bad</otherchild>
  884. </ns:tag>
  885. <tag>Tag without ns</tag>
  886. </root>
  887. XML;
  888. $xmlResponse = Xml::build($xml);
  889. $expected = array(
  890. 'root' => array(
  891. 'ns:tag' => array(
  892. '@id' => '1',
  893. 'child' => 'good',
  894. 'otherchild' => 'bad'
  895. ),
  896. 'tag' => 'Tag without ns'
  897. )
  898. );
  899. $this->assertEquals($expected, Xml::toArray($xmlResponse));
  900. $xmlResponse = Xml::build('<root xmlns:ns="http://cakephp.org"><ns:tag id="1" /><tag><id>1</id></tag></root>');
  901. $expected = array(
  902. 'root' => array(
  903. 'ns:tag' => array(
  904. '@id' => '1'
  905. ),
  906. 'tag' => array(
  907. 'id' => '1'
  908. )
  909. )
  910. );
  911. $this->assertEquals($expected, Xml::toArray($xmlResponse));
  912. $xmlResponse = Xml::build('<root xmlns:ns="http://cakephp.org"><ns:attr>1</ns:attr></root>');
  913. $expected = array(
  914. 'root' => array(
  915. 'ns:attr' => '1'
  916. )
  917. );
  918. $this->assertEquals($expected, Xml::toArray($xmlResponse));
  919. $xmlResponse = Xml::build('<root><ns:attr xmlns:ns="http://cakephp.org">1</ns:attr></root>');
  920. $this->assertEquals($expected, Xml::toArray($xmlResponse));
  921. $xml = array(
  922. 'root' => array(
  923. 'ns:attr' => array(
  924. 'xmlns:ns' => 'http://cakephp.org',
  925. '@' => 1
  926. )
  927. )
  928. );
  929. $expected = '<' . '?xml version="1.0" encoding="UTF-8"?><root><ns:attr xmlns:ns="http://cakephp.org">1</ns:attr></root>';
  930. $xmlResponse = Xml::fromArray($xml);
  931. $this->assertEquals($expected, str_replace(array("\r", "\n"), '', $xmlResponse->asXML()));
  932. $xml = array(
  933. 'root' => array(
  934. 'tag' => array(
  935. 'xmlns:pref' => 'http://cakephp.org',
  936. 'pref:item' => array(
  937. 'item 1',
  938. 'item 2'
  939. )
  940. )
  941. )
  942. );
  943. $expected = <<<XML
  944. <?xml version="1.0" encoding="UTF-8"?>
  945. <root>
  946. <tag xmlns:pref="http://cakephp.org">
  947. <pref:item>item 1</pref:item>
  948. <pref:item>item 2</pref:item>
  949. </tag>
  950. </root>
  951. XML;
  952. $xmlResponse = Xml::fromArray($xml);
  953. $this->assertXmlStringEqualsXmlString($expected, $xmlResponse->asXML());
  954. $xml = array(
  955. 'root' => array(
  956. 'tag' => array(
  957. 'xmlns:' => 'http://cakephp.org'
  958. )
  959. )
  960. );
  961. $expected = '<' . '?xml version="1.0" encoding="UTF-8"?><root><tag xmlns="http://cakephp.org"/></root>';
  962. $xmlResponse = Xml::fromArray($xml);
  963. $this->assertXmlStringEqualsXmlString($expected, $xmlResponse->asXML());
  964. $xml = array(
  965. 'root' => array(
  966. 'xmlns:' => 'http://cakephp.org'
  967. )
  968. );
  969. $expected = '<' . '?xml version="1.0" encoding="UTF-8"?><root xmlns="http://cakephp.org"/>';
  970. $xmlResponse = Xml::fromArray($xml);
  971. $this->assertXmlStringEqualsXmlString($expected, $xmlResponse->asXML());
  972. $xml = array(
  973. 'root' => array(
  974. 'xmlns:ns' => 'http://cakephp.org'
  975. )
  976. );
  977. $expected = '<' . '?xml version="1.0" encoding="UTF-8"?><root xmlns:ns="http://cakephp.org"/>';
  978. $xmlResponse = Xml::fromArray($xml);
  979. $this->assertXmlStringEqualsXmlString($expected, $xmlResponse->asXML());
  980. }
  981. /**
  982. * test that CDATA blocks don't get screwed up by SimpleXml
  983. *
  984. * @return void
  985. */
  986. public function testCdata() {
  987. $xml = '<' . '?xml version="1.0" encoding="UTF-8"?>' .
  988. '<people><name><![CDATA[ Mark ]]></name></people>';
  989. $result = Xml::build($xml);
  990. $this->assertEquals(' Mark ', (string)$result->name);
  991. }
  992. /**
  993. * data provider for toArray() failures
  994. *
  995. * @return array
  996. */
  997. public static function invalidToArrayDataProvider() {
  998. return array(
  999. array(new \DateTime()),
  1000. array(array())
  1001. );
  1002. }
  1003. /**
  1004. * testToArrayFail method
  1005. *
  1006. * @dataProvider invalidToArrayDataProvider
  1007. * @expectedException \Cake\Utility\Error\XmlException
  1008. * @return void
  1009. */
  1010. public function testToArrayFail($value) {
  1011. Xml::toArray($value);
  1012. }
  1013. /**
  1014. * testWithModel method
  1015. *
  1016. * @return void
  1017. */
  1018. public function testWithModel() {
  1019. $this->markTestIncomplete('Models do not work right now');
  1020. $this->loadFixtures('User', 'Article');
  1021. $user = new XmlUser();
  1022. $data = $user->read(null, 1);
  1023. $obj = Xml::build(compact('data'));
  1024. $expected = <<<XML
  1025. <?xml version="1.0" encoding="UTF-8"?><data>
  1026. <User><id>1</id><user>mariano</user><password>5f4dcc3b5aa765d61d8327deb882cf99</password>
  1027. <created>2007-03-17 01:16:23</created><updated>2007-03-17 01:18:31</updated></User>
  1028. <Article><id>1</id><user_id>1</user_id><title>First Article</title><body>First Article Body</body>
  1029. <published>Y</published><created>2007-03-18 10:39:23</created><updated>2007-03-18 10:41:31</updated></Article>
  1030. <Article><id>3</id><user_id>1</user_id><title>Third Article</title><body>Third Article Body</body>
  1031. <published>Y</published><created>2007-03-18 10:43:23</created><updated>2007-03-18 10:45:31</updated></Article>
  1032. </data>
  1033. XML;
  1034. $this->assertXmlStringEqualsXmlString($expected, $obj->asXML());
  1035. //multiple model results - without a records key it would fatal error
  1036. $data = $user->find('all', array('limit' => 2));
  1037. $data = array('records' => $data);
  1038. $obj = Xml::build(compact('data'));
  1039. $expected = <<<XML
  1040. <?xml version="1.0" encoding="UTF-8"?><data>
  1041. <records>
  1042. <User><id>1</id><user>mariano</user><password>5f4dcc3b5aa765d61d8327deb882cf99</password>
  1043. <created>2007-03-17 01:16:23</created><updated>2007-03-17 01:18:31</updated></User>
  1044. <Article><id>1</id><user_id>1</user_id><title>First Article</title><body>First Article Body</body>
  1045. <published>Y</published><created>2007-03-18 10:39:23</created><updated>2007-03-18 10:41:31</updated></Article>
  1046. <Article><id>3</id><user_id>1</user_id><title>Third Article</title><body>Third Article Body</body>
  1047. <published>Y</published><created>2007-03-18 10:43:23</created><updated>2007-03-18 10:45:31</updated></Article>
  1048. </records><records><User><id>2</id><user>nate</user><password>5f4dcc3b5aa765d61d8327deb882cf99</password>
  1049. <created>2007-03-17 01:18:23</created><updated>2007-03-17 01:20:31</updated></User><Article/>
  1050. </records>
  1051. </data>
  1052. XML;
  1053. $obj->asXML();
  1054. $this->assertXmlStringEqualsXmlString($expected, $obj->asXML());
  1055. }
  1056. /**
  1057. * Test ampersand in text elements.
  1058. *
  1059. * @return void
  1060. */
  1061. public function testAmpInText() {
  1062. $data = array(
  1063. 'outer' => array(
  1064. 'inner' => array('name' => 'mark & mark')
  1065. )
  1066. );
  1067. $obj = Xml::build($data);
  1068. $result = $obj->asXml();
  1069. $this->assertContains('mark &amp; mark', $result);
  1070. }
  1071. /**
  1072. * Test that entity loading is disabled by default.
  1073. *
  1074. * @return void
  1075. */
  1076. public function testNoEntityLoading() {
  1077. $file = str_replace(' ', '%20', CAKE . 'VERSION.txt');
  1078. $xml = <<<XML
  1079. <!DOCTYPE cakephp [
  1080. <!ENTITY payload SYSTEM "file://$file" >]>
  1081. <request>
  1082. <xxe>&payload;</xxe>
  1083. </request>
  1084. XML;
  1085. try {
  1086. $result = Xml::build($xml);
  1087. $this->assertEquals('', (string)$result->xxe);
  1088. } catch (Exception $e) {
  1089. $this->assertTrue(true, 'A warning was raised meaning external entities were not loaded');
  1090. }
  1091. }
  1092. }