From e74f37a3b1e6c234f3fb631c9fee129e3ba561ff Mon Sep 17 00:00:00 2001 From: REZ1DENT3 Date: Thu, 4 May 2017 10:32:01 +0300 Subject: [PATCH] first version --- .gitignore | 6 +- composer.json | 21 ++++ demo/c.xml | 15 +++ demo/reader.php | 9 ++ src/XMLReader/XMLReader.php | 221 ++++++++++++++++++++++++++++++++++++ 5 files changed, 268 insertions(+), 4 deletions(-) create mode 100644 composer.json create mode 100644 demo/c.xml create mode 100644 demo/reader.php create mode 100644 src/XMLReader/XMLReader.php diff --git a/.gitignore b/.gitignore index c422267..b1a238d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ composer.phar /vendor/ - -# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file -# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file -# composer.lock +composer.lock +.idea \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..353ed31 --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "bavix/xml", + "description": "XML Reader", + "minimum-stability": "stable", + "license": "MIT", + "authors": [ + { + "name": "Babichev Maxim", + "email": "info@babichev.net" + } + ], + "require": { + "bavix/foundation": "^1.0", + "bavix/exceptions": "^1.0" + }, + "autoload": { + "psr-4": { + "Bavix\\": "src/" + } + } +} \ No newline at end of file diff --git a/demo/c.xml b/demo/c.xml new file mode 100644 index 0000000..8bdd3c8 --- /dev/null +++ b/demo/c.xml @@ -0,0 +1,15 @@ + + + + 1972 + Dennis Ritchie + + + 1995 + Rasmus Lerdorf + + + 1995 + James Gosling + + diff --git a/demo/reader.php b/demo/reader.php new file mode 100644 index 0000000..3d2b341 --- /dev/null +++ b/demo/reader.php @@ -0,0 +1,9 @@ +asArray('c.xml'); + +var_dump($reader->asXML($data)); diff --git a/src/XMLReader/XMLReader.php b/src/XMLReader/XMLReader.php new file mode 100644 index 0000000..e0791a4 --- /dev/null +++ b/src/XMLReader/XMLReader.php @@ -0,0 +1,221 @@ + 'https://github.com/bavix/xml']; + + /** + * @var \DOMDocument + */ + protected $document; + + /** + * @return \DOMDocument + */ + protected function document() + { + if (!$this->document) + { + $this->document = new \DOMDocument('1.0', 'utf-8'); + $this->document->formatOutput = true; + $this->copyright['created-at'] = date('Y-m-d H:i:s'); + } + + return $this->document; + } + + /** + * @param string $name + * + * @return \DOMElement + */ + protected function element($name) + { + return $this->document()->createElement($name); + } + + /** + * @param string $file + * + * @return array + */ + public function asArray($file) + { + $reader = \simplexml_load_file($file); + + return json_decode(json_encode((array)$reader), true); + } + + /** + * @param array $storage + * + * @return string + */ + public function asXML(array $storage) + { + $element = $this->element('bavix'); + + $this->addAttributes($element, $this->copyright); + $this->document()->appendChild($element); + $this->convert($element, $storage); + $xml = $this->document()->saveXML(); + + $this->document = null; + + return $xml; + } + + /** + * @param DOMElement $element + * @param mixed $storage + * + * @throws Exceptions\Blank + */ + protected function convert(DOMElement $element, $storage) + { + if (!is_array($storage)) + { + $element->nodeValue = htmlspecialchars($storage); + + return; + } + + if (count($storage) === 0) + { + throw new Exceptions\Blank('Array is empty'); + } + + $isInt = array_map('is_int', array_keys($storage)); + $sequential = !in_array(false, $isInt, true); + + foreach ($storage as $key => $data) + { + if ($sequential) + { + $this->sequential($element, $data); + continue; + } + + $this->addNodeWithKey($key, $element, $data); + } + } + + /** + * @param string $key + * @param DOMElement $element + * @param mixed $storage + */ + protected function addNodeWithKey($key, DOMElement $element, $storage) + { + if ($key === '@attributes') + { + $this->addAttributes($element, $storage); + } + elseif ($key === '@value' && is_string($storage)) + { + $element->nodeValue = htmlspecialchars($storage); + } + else + { + $this->addNode($element, $key, $storage); + } + } + + /** + * @param DOMElement $element + * @param mixed $storage + */ + protected function sequential(DOMElement $element, $storage) + { + if (is_array($storage)) + { + $this->addCollectionNode($element, $storage); + } + else + { + + $this->addSequentialNode($element, $storage); + } + } + + /** + * @param DOMElement $element + * @param string $key + * @param mixed $value + * + * @throws Exceptions\Blank + */ + protected function addNode(DOMElement $element, $key, $value) + { + $key = str_replace(' ', '_', $key); + $child = $this->document()->createElement($key); + $element->appendChild($child); + $this->convert($child, $value); + } + + /** + * @param DOMElement $element + * @param mixed $value + * + * @throws Exceptions\Blank + */ + protected function addCollectionNode(DOMElement $element, $value) + { + if ($element->childNodes->length === 0) + { + $this->convert($element, $value); + + return; + } + + /** + * @var $child DOMElement + */ + $child = $element->cloneNode(); + $element->parentNode->appendChild($child); + $this->convert($child, $value); + } + + /** + * @param DOMElement $element + * @param mixed $value + */ + protected function addSequentialNode(DOMElement $element, $value) + { + if (empty($element->nodeValue)) + { + $element->nodeValue = htmlspecialchars($value); + + return; + } + + $child = $element->cloneNode(); + $child->nodeValue = htmlspecialchars($value); + $element->parentNode->appendChild($child); + } + + /** + * @param DOMElement $element + * @param array $storage + */ + protected function addAttributes(DOMElement $element, array $storage) + { + foreach ($storage as $attrKey => $attrVal) + { + $element->setAttribute($attrKey, $attrVal); + } + } + +}