From 3a6e0b476cff3672bf71233d6f63054ea9e90b61 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Tue, 26 Sep 2017 11:08:47 +0300 Subject: [PATCH] update tests & patch xml library --- src/XMLReader/XMLReader.php | 146 +++++++++++++++++++++++++----------- storage.php | 53 +++++++++++++ tests/XMLReaderTest.php | 1 + tests/storage.php | 27 ++++++- xml.php | 53 +++++++++++++ 5 files changed, 232 insertions(+), 48 deletions(-) create mode 100644 storage.php create mode 100644 xml.php diff --git a/src/XMLReader/XMLReader.php b/src/XMLReader/XMLReader.php index dce5f85..694587b 100644 --- a/src/XMLReader/XMLReader.php +++ b/src/XMLReader/XMLReader.php @@ -2,11 +2,10 @@ namespace Bavix\XMLReader; -use Bavix\Exceptions; use Bavix\Foundation\SharedInstance; -use Bavix\Helpers\Arr; use Bavix\Helpers\File; -use Bavix\Helpers\JSON; +use Bavix\Helpers\Arr; +use Bavix\Exceptions; use DOMElement; class XMLReader @@ -17,7 +16,9 @@ class XMLReader /** * @var array */ - protected $copyright = ['created-with' => 'https://github.com/bavix/xml']; + protected $copyright = [ + 'created-with' => 'https://github.com/bavix/xml' + ]; /** * @var \DOMDocument @@ -33,7 +34,7 @@ protected function document() { $this->document = new \DOMDocument('1.0', 'utf-8'); $this->document->formatOutput = true; - $this->copyright['created-at'] = date('Y-m-d H:i:s'); + $this->copyright['created-at'] = \date('Y-m-d H:i:s'); } return $this->document; @@ -51,27 +52,47 @@ protected function element($name) /** * @param \SimpleXMLElement $element + * @param string $property * - * @return array|string - * - * @codeCoverageIgnore + * @return array */ - protected function _asData(\SimpleXMLElement $element) + protected function _property(\SimpleXMLElement $element, $property) { $output = []; - $attributes = $element->attributes(); - - if ($attributes) + if (method_exists($element, $property)) { - $output['@attributes'] = $this->_asArray($attributes); - if (empty($output['@attributes'])) + $properties = $element->$property(); + + if ($properties) { - Arr::remove($output, '@attributes'); + $output['@' . $property] = is_array($properties) ? + $properties : + $this->_asArray($properties); + + if (empty($output['@' . $property])) + { + Arr::remove($output, '@' . $property); + } } + } + return $output; + } + + /** + * @param \SimpleXMLElement $element + * + * @return array|string + * + * @codeCoverageIgnore + */ + protected function _asData(\SimpleXMLElement $element) + { + $output = $this->_property($element, 'attributes'); + if (!$element->count()) { $output['@value'] = (string)$element; @@ -101,22 +122,27 @@ protected function _asArray(\SimpleXMLElement $element) return $output; } + $first = []; + /** * @var \SimpleXMLElement $item */ foreach ($element as $key => $item) { - if (!$item->count()) + if (!isset($output[$key])) + { + $first[$key] = true; + $output[$key] = $this->_asArray($item); + continue; + } + + if (!empty($first[$key])) { - $output[$key] = $this->_asArray($item); - continue; + $output[$key] = [$output[$key]]; } - Arr::initOrPush( - $output, - $key, - $this->_asArray($item) - ); + $output[$key][] = $this->_asArray($item); + $first[$key] = false; } return $output; @@ -125,21 +151,35 @@ protected function _asArray(\SimpleXMLElement $element) /** * @param string|\DOMNode $mixed * - * @return array + * @return \SimpleXMLElement */ - public function asArray($mixed) + protected function _simpleXml($mixed) { if ($mixed instanceof \DOMNode) { - return $this->_asArray(\simplexml_import_dom($mixed)); + return \simplexml_import_dom($mixed); } if (File::isFile($mixed)) { - return $this->_asArray(\simplexml_load_file($mixed)); + return \simplexml_load_file($mixed); } - return $this->_asArray(\simplexml_load_string($mixed)); + return \simplexml_load_string($mixed); + } + + /** + * @param string|\DOMNode $mixed + * + * @return array + */ + public function asArray($mixed) + { + $data = $this->_simpleXml($mixed); + + return $data ? + $this->_asArray($data) : + null; } /** @@ -151,17 +191,33 @@ public function asObject() } /** - * @param array $storage + * @param array|\Traversable $storage + * + * @return array + */ + protected function _convertStorage($storage) + { + if ($storage instanceof \Traversable) + { + return \iterator_to_array($storage); + } + + return $storage; + } + + /** + * @param array|\Traversable $storage + * @param string $name * * @return string */ - public function asXML(array $storage) + public function asXML($storage, $name = 'bavix') { - $element = $this->element('bavix'); + $element = $this->element($name); $this->addAttributes($element, $this->copyright); $this->document()->appendChild($element); - $this->convert($element, $storage); + $this->convert($element, $this->_convertStorage($storage)); $xml = $this->document()->saveXML(); $this->document = null; @@ -189,8 +245,8 @@ protected function convert(DOMElement $element, $storage) throw new Exceptions\Blank('Array is empty'); } - $isInt = Arr::map(Arr::getKeys($storage), 'is_int'); - $sequential = !Arr::in($isInt, false, true); + $isInt = Arr::map(Arr::getKeys($storage), '\is_int'); + $sequential = !Arr::in($isInt, false); foreach ($storage as $key => $data) { @@ -215,9 +271,9 @@ protected function addNodeWithKey($key, DOMElement $element, $storage) { $this->addAttributes($element, $storage); } - else if ($key === '@value' && is_string($storage)) + else if ($key === '@value' && \is_string($storage)) { - $element->nodeValue = htmlspecialchars($storage); + $element->nodeValue = \htmlspecialchars($storage); } else { @@ -250,7 +306,7 @@ protected function sequential(DOMElement $element, $storage) */ protected function addNode(DOMElement $element, $key, $value) { - $key = str_replace(' ', '_', $key); + $key = \str_replace(' ', '-', $key); $child = $this->document()->createElement($key); $element->appendChild($child); $this->convert($child, $value); @@ -274,7 +330,8 @@ protected function addCollectionNode(DOMElement $element, $value) /** * @var $child DOMElement */ - $child = $element->cloneNode(); + $child = $this->document()->createElement($element->nodeName); +// $child = $element->cloneNode(); $element->parentNode->appendChild($child); $this->convert($child, $value); } @@ -287,21 +344,22 @@ protected function addSequentialNode(DOMElement $element, $value) { if (empty($element->nodeValue)) { - $element->nodeValue = htmlspecialchars($value); + $element->nodeValue = \htmlspecialchars($value); return; } - $child = $element->cloneNode(); - $child->nodeValue = htmlspecialchars($value); + $child = $this->document()->createElement($element->nodeName); +// $child = $element->cloneNode(); + $child->nodeValue = \htmlspecialchars($value); $element->parentNode->appendChild($child); } /** - * @param DOMElement $element - * @param array $storage + * @param DOMElement $element + * @param array|\Traversable $storage */ - protected function addAttributes(DOMElement $element, array $storage) + protected function addAttributes(DOMElement $element, $storage) { foreach ($storage as $attrKey => $attrVal) { diff --git a/storage.php b/storage.php new file mode 100644 index 0000000..c418a7e --- /dev/null +++ b/storage.php @@ -0,0 +1,53 @@ + + array ( + 0 => + array ( + 'name' => 'Alex', + 'age' => 34, + 'cars' => + array ( + 0 => + array ( + '@attributes' => + array ( + 'drive' => 'test', + ), + '@value' => 'Volvo', + ), + 1 => 'BMW', + 2 => 'Toyota', + 3 => 'Honda', + 4 => 'Mercedes', + 5 => 'Opel', + ), + ), + 1 => + array ( + 'name' => + array ( + '@attributes' => + array ( + 'age' => 44, + ), + '@value' => 'Ivan', + ), + 'cars' => 'Opel', + ), + 2 => + array ( + '@attributes' => + array ( + 'name' => 'Anton', + ), + 'age' => 22, + 'cars' => + array ( + 0 => 'Volvo', + 1 => 'BMW', + ), + ), + ), +); \ No newline at end of file diff --git a/tests/XMLReaderTest.php b/tests/XMLReaderTest.php index 833bcb6..9d1a01f 100644 --- a/tests/XMLReaderTest.php +++ b/tests/XMLReaderTest.php @@ -2,6 +2,7 @@ namespace Tests; +use Bavix\Helpers\File; use Bavix\Tests\Unit; use Bavix\XMLReader\XMLReader; diff --git a/tests/storage.php b/tests/storage.php index e5a7875..28ccfb0 100644 --- a/tests/storage.php +++ b/tests/storage.php @@ -4,21 +4,40 @@ 'person' => [ [ 'name' => 'Alex', - 'age' => 34 + 'age' => 34, + 'cars' => [ + [ + '@attributes' => [ + 'drive' => 'test' + ], + '@value' => 'Volvo' + ], + + 'BMW', + 'Toyota', + 'Honda', + 'Mercedes', + 'Opel' + ] ], [ 'name' => [ '@attributes' => [ 'age' => 44 ], - '@value' => 'Ivan' - ] + '@value' => 'Ivan' + ], + 'cars' => 'Opel' ], [ '@attributes' => [ 'name' => 'Anton' ], - 'age' => 22 + 'age' => 22, + 'cars' => [ + 'Volvo', + 'BMW' + ] ] ] ]; diff --git a/xml.php b/xml.php new file mode 100644 index 0000000..ab5dc48 --- /dev/null +++ b/xml.php @@ -0,0 +1,53 @@ + + array ( + 0 => + array ( + 'name' => 'Alex', + 'age' => '34', + 'cars' => + array ( + 0 => + array ( + '@attributes' => + array ( + 'drive' => 'test', + ), + '@value' => 'Volvo', + ), + 1 => 'BMW', + 2 => 'Toyota', + 3 => 'Honda', + 4 => 'Mercedes', + 5 => 'Opel', + ), + ), + 1 => + array ( + 'name' => + array ( + '@attributes' => + array ( + 'age' => '44', + ), + '@value' => 'Ivan', + ), + 'cars' => 'Opel', + ), + 2 => + array ( + '@attributes' => + array ( + 'name' => 'Anton', + ), + 'age' => '22', + 'cars' => + array ( + 0 => 'Volvo', + 1 => 'BMW', + ), + ), + ), +); \ No newline at end of file