XmlToArray::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Vyuldashev\XmlToArray;
6
7
use DOMAttr;
8
use DOMCdataSection;
9
use DOMDocument;
10
use DOMElement;
11
use DOMNamedNodeMap;
12
use DOMText;
13
14
class XmlToArray
15
{
16
    protected $document;
17
18
    public function __construct(string $xml)
19
    {
20
        $this->document = new DOMDocument();
21
        $this->document->loadXML($xml);
22
    }
23
24
    public static function convert(string $xml): array
25
    {
26
        $converter = new static($xml);
27
28
        return $converter->toArray();
29
    }
30
31
    protected function convertAttributes(DOMNamedNodeMap $nodeMap): ?array
32
    {
33
        if ($nodeMap->length === 0) {
34
            return null;
35
        }
36
37
        $result = [];
38
39
        /** @var DOMAttr $item */
40
        foreach ($nodeMap as $item) {
41
            $result[$item->name] = $item->value;
42
        }
43
44
        return ['_attributes' => $result];
45
    }
46
47
    protected function isHomogenous(array $arr)
48
    {
49
        $firstValue = current($arr);
50
        foreach ($arr as $val) {
51
            if ($firstValue !== $val) {
52
                return false;
53
            }
54
        }
55
56
        return true;
57
    }
58
59
    protected function convertDomElement(DOMElement $element)
60
    {
61
        $sameNames = false;
62
        $result = $this->convertAttributes($element->attributes);
63
64
        if ($element->childNodes->length > 1) {
65
            $childNodeNames = [];
66
            foreach ($element->childNodes as $key => $node) {
67
                $childNodeNames[] = $node->nodeName;
68
            }
69
            $sameNames = $this->isHomogenous($childNodeNames);
70
        }
71
72
        foreach ($element->childNodes as $key => $node) {
73
            if ($node instanceof DOMCdataSection) {
74
                $result['_cdata'] = $node->data;
75
76
                continue;
77
            }
78
            if ($node instanceof DOMText) {
79
                $result = $node->textContent;
80
81
                continue;
82
            }
83
            if ($node instanceof DOMElement) {
84
                if ($sameNames) {
85
                    $result[$node->nodeName][$key] = $this->convertDomElement($node);
86
                } else {
87
                    $result[$node->nodeName] = $this->convertDomElement($node);
88
                }
89
90
                continue;
91
            }
92
        }
93
94
        return $result;
95
    }
96
97
    public function toArray(): array
98
    {
99
        $result = [];
100
101
        if ($this->document->hasChildNodes()) {
102
            $children = $this->document->childNodes;
103
104
            foreach ($children as $child) {
105
                $result[$child->nodeName] = $this->convertDomElement($child);
106
            }
107
        }
108
109
        return $result;
110
    }
111
}
112